요즘 소마에서 프로젝트를 해보며 개발 기술들에 대해 배우고 적용해보고 있습니다. 이러한 기술들에 대해 개념을 자세히 설명하기보다는 실제로 어떻게 썼는지, 어떤 점이 좋았는지 정리해보고자 합니다!
캡슐화의 정의에 대해 찾아보면 크게 두가지로 얘기하는 경우가 많습니다.
1. 객체의 속성과 행위를 하나로 묶기
2. 실제 구현 내용 일부를 외부에 감추어 은닉하기
저 또한 이렇게 이해하고 있었는데 이번 포스팅에서는 코드와 함께 추가로 설명해보고자 합니다.
우선 캡슐화를 앞에 개념과 덧붙여서 제 스스로 간단하게 정리를 하자면 아래와 같습니다.
주로 메소드를 통해서 변수를 조작했을 경우의 장점을 말함
접근 제어에 대해 따로 설명하지는 않지만, 아래 사진에서 잘 정리해주셨다고 생각합니다. 사진의 출처는 이곳 입니다.

코드와 함께 어떻게 구현했는지 설명드리겠습니다.
우선은 간단하게 동작을 설명드리자면 아래와 같습니다.
// App 영역 - View
public struct ProfileSettingView: View {
@StateObject private var viewModel: ProfileSettingViewModel
public init(viewModel: ProfileSettingViewModel) {
self._viewModel = StateObject(wrappedValue: viewModel)
}
public var body: some View {
VStack {
finishButtonView()
...
}
}
@ViewBuilder
private func finishButtonView() -> some View {
Button {
// 작업 처리 도중 버튼을 연속으로 누르는 것을 방지
if !viewModel.buttonIsLocked {
viewModel.lockButton(true)
viewModel.moveToLearningHomeView()
}
} label: {
Text("설정하기")
}
}
}
// App 영역 - ViewModel
public class ProfileSettingViewModel: BaseViewModel {
// View에게 쓰기 권한은 주지 않고, 읽기 권한만 주기
private(set) var buttonIsLocked: Bool = false
// 버튼 잠그기 or 풀기
func lockButton(_ setLock: Bool) {
buttonIsLocked = setLock
}
// 다음 화면으로 이동하기
func moveToLearningHomeView() {
...
}
}
ViewModel의 코드를 보면 buttonIsLocked 변수가 private(set) 으로 되어 있습니다. 다시 말하자면 외부에서는 읽기만 가능하다는 것인데, 이로 인해 어쩔 수 없이 값을 바꾸고 싶으면 lockButton 함수를 호출해야합니다.
외부 객체 중 같은 모듈 안에 있다면 읽기만 허락하고, 그 외의 것들을 읽기와 쓰기 모두 허락하지 않는 것, 즉 앞서 말했듯이 읽기 및 쓰기 권한을 분리하고 원하는 대상에게 원하는 만큼만 허락하는 것이 바로 캡슐화입니다.
물론 아래와 같이 코드를 작성하더라도 실행 결과는 완전히 똑같습니다.
// App 영역 - View
public struct ProfileSettingView: View {
...
@ViewBuilder
private func finishButtonView() -> some View {
Button {
if !viewModel.buttonIsLocked {
viewModel.buttonIsLocked = true // 직접 접근하여 set
viewModel.moveToLearningHomeView()
}
} label: {
Text("설정하기")
}
}
}
// App 영역 - ViewModel
public class ProfileSettingViewModel: BaseViewModel {
var buttonIsLocked: Bool = false
...
}
다만 접근을 제어하는 것은 중복 방지, 잘못된 사용 예방 등 앞서 말한 이유때문이기도 하고 궁극적으로는 사람의 실수를 막기 위해서라고 개인적으로 생각합니다.
buttonIsLocked에 실수로 이상한 값을 대입하지 못하도록, buttonIsLocked를 Set하는 로직이 바뀌었을 때 해당 로직이 쓰이는 코드 중 일부를 실수로 빠뜨리는 경우가 없도록 하는 것이 결국엔 캡슐화의 목적이 아닐까하고 생각합니다.
이상으로 제가 사용해본 캡슐화를 코드와 함께 설명드렸습니다. 사실 저도 현재 배우고 있는 입장이기 때문에 틀린 개념, 부족한 개념들이 있을 수 있습니다. 혹시라도 그런 부분이 있다면 언제든지 지적해주셔도 됩니다. 긴 글 읽어주셔서 감사합니다. 😊