캡슐화와 불변 조건
3강. 캡슐화와 불변 조건
1. 이번 강의에서 해결할 문제
모든 필드에 getter/setter를 만들면 private 표시는 있어도 누구나 잘못된 조합을 만들 수 있습니다. private은 보안 기능이 아니라 사용 규칙과 불변식을 보호하는 경계입니다.
2. 학습 목표
3. 핵심 개념
Task의 완료 시각은 완료 상태일 때만 존재한다는 불변식이 있습니다. setStatus와 setCompletedAt을 따로 노출하면 중간 불일치가 생깁니다. complete(now) 한 연산이 둘을 함께 바꿉니다.
용어 정리
- 캡슐화: 필드를 숨기는 데서 끝나지 않고, 객체가 허용하는 상태 변화만 공개하는 설계입니다.
- 불변 조건(invariant): 객체가 외부에 정상 상태로 보이는 모든 순간에 반드시 참이어야 하는 규칙입니다.
- 상태 전이: 진행 중 → 완료처럼 한 유효 상태에서 다른 유효 상태로 이동하는 일입니다.
- 원자적 변경: 관련된 값이 중간의 깨진 상태를 노출하지 않고 하나의 의미 있는 연산으로 함께 바뀌는 것입니다.
이 강의의 불변 조건은 다음 문장으로 먼저 고정합니다.
진행 중 작업은 완료 시각이 없고, 완료된 작업은 반드시 완료 시각이 있다.
setStatus(Status::completed)와 setCompletedAt(now)를 따로 호출하게 하면 두 호출 사이에 “완료인데 완료 시각 없음”이라는 잘못된 상태가 생깁니다. 호출자가 두 함수의 순서를 기억해야 하므로 책임도 밖으로 새어 나갑니다.
4. 가장 작은 구현으로 시작하기
complete를 호출하기 전 status_는 inProgress입니다. 함수는 먼저 전이가 허용되는지 검사하고, 모든 검사를 통과한 뒤 관련 필드 두 개를 바꿉니다.
void Task::complete(TimePoint now) {
if (status_ != Status::inProgress) {
throw InvalidTransition{"task is not in progress"};
}
status_ = Status::completed;
completedAt_ = now;
}
생성자도 빈 제목과 잘못된 초기 상태를 거부합니다. 조회는 필요한 값만 const 함수로 제공합니다.
코드 한 줄씩 이해하기
status_ != Status::inProgress는 현재 작업이 완료 가능한 출발 상태인지 확인합니다.- 조건이 참이면
InvalidTransition을 던지고, 아래 대입은 한 줄도 실행하지 않습니다. status_ = Status::completed로 상태를 완료로 전이합니다.completedAt_ = now로 같은 전이에 필요한 완료 시각을 저장합니다.
| 호출 전 상태 | 호출 결과 | 호출 뒤 상태 |
|---|---|---|
| 진행 중, 완료 시각 없음 | 성공 | 완료, 전달한 완료 시각 있음 |
| 이미 완료, 완료 시각 있음 | 예외 | 기존 완료 상태와 시각 유지 |
| 취소됨, 완료 시각 없음 | 예외 | 기존 취소 상태 유지 |
검증보다 대입을 먼저 하면 첫 필드만 바뀐 뒤 예외가 발생할 수 있습니다. 따라서 실패 가능한 조건을 먼저 검사한 다음 상태를 한꺼번에 확정합니다.
5. 코드가 동작하는 이유
호출자는 내부 필드 변경 순서를 알 필요가 없고 실패 시 아무 상태도 바뀌지 않습니다. 불변식 검증이 한곳에 모입니다.
이 설계에서 호출자는 task.complete(now)라는 의도만 표현합니다. 완료 시각을 언제 저장해야 하는지, 어떤 상태에서 거부할지는 Task가 결정합니다. 향후 완료 규칙이 바뀌어도 모든 호출자를 수정하지 않고 이 경계와 테스트를 중심으로 변경할 수 있습니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
8. 이해 점검 질문 3개
9. 핵심 요약
10. 다음 강의 연결
불변 조건을 Task 안에 보호했으므로 호출자는 상태 변경 순서를 알 필요가 없습니다. 다음 강의에서는 행동의 변형이 늘어날 때 이 안정된 핵심을 상속 계층으로 흔들지 않고, 작은 객체를 조합해 확장하는 방법을 다룹니다.
캡슐화와 불변 조건 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.