코드 품질 개선 기법 12편: 세트 할인 (새 탭에서 열림)

여러 속성을 개별적으로 변경할 수 있게 허용하는 구조는 상태 간의 불일치를 초래하고 예기치 못한 버그를 유발할 수 있습니다. 이를 해결하기 위해 서로 연관된 상태들을 하나의 객체로 묶어 한 번에 업데이트하도록 인터페이스를 제한하면 시스템의 예측 가능성을 높일 수 있습니다. 결과적으로 코드의 의도가 명확해지고 스레드 안전성 확보와 디버깅이 훨씬 용이해집니다.

개별 속성 변경의 위험성

  • 실행 순서 의존성: 활성화 상태(isActive)와 세부 설정(minImportanceToRecord 등)이 분리되어 있으면, 설정을 변경하기 전에 활성화를 먼저 시도할 경우 의도치 않게 이전 설정값이 적용되는 문제가 발생합니다.
  • 상태 초기화의 불일치: 특정 속성이 변경될 때 내부 카운터가 초기화되어야 함에도 불구하고, 어떤 속성은 초기화를 수행하고 어떤 속성은 누락하는 등의 관리 포인트가 파편화되어 로직이 복잡해집니다.
  • 경쟁 상태(Race Condition): 비동기 환경에서 여러 속성을 순차적으로 변경하면, 변경 중간에 다른 로직이 개입하여 불완전한 상태의 데이터를 읽게 될 위험이 있습니다.

데이터 묶음과 인터페이스 제한을 통한 개선

  • 객체 캡슐화: 연관된 설정값들을 SamplingPolicy와 같은 별도의 불변(Immutable) 클래스로 묶어 관리함으로써 속성들이 항상 한 세트로 업데이트되도록 강제합니다.
  • 상태 표현의 최적화: 별도의 불리언 플래그 대신 상태 객체의 null 여부로 활성화 상태를 표현하여, 활성 상태일 때는 반드시 유효한 설정값이 존재함을 보장합니다.
  • 원자적 업데이트: startRecording과 같이 명시적인 메서드를 통해서만 상태를 변경하게 함으로써 내부 카운터 초기화와 설정 변경이 한 번에(Atomic) 이루어지도록 제어합니다.

실용적인 결론 단순히 모든 필드에 세터(setter)를 열어두는 것보다, 비즈니스 로직상 함께 움직여야 하는 데이터는 하나의 '상태 객체'로 정의하는 것이 좋습니다. 특히 한 속성의 변화가 다른 속성의 의미나 동작에 영향을 주는 경우에는 인터페이스를 엄격하게 제한하여 잘못된 상태 조합이 발생하는 것을 원천적으로 차단해야 합니다.