좋은 설계는 변하지 않는 것을 퍼뜨리는 대신 자주 바뀌는 것을 한곳에 숨긴다

소프트웨어 설계를 어렵게 만드는 이유는 지금 필요한 기능만으로는 미래 변경 지점을 완전히 알 수 없기 때문이다. 그래도 한 가지는 분명하다. 어떤 시스템이든 더 자주 바뀌는 결정과 덜 바뀌는 결정이 있다. 좋은 설계는 이 둘을 구분하고, 자주 바뀌는 것을 한곳에 숨기려 한다.
데이비드 파나스의 정보 은닉 원칙이 오래 살아남은 것도 이 때문이다. 모듈은 기능 단위로만 나누는 것이 아니라, 변경될 가능성이 있는 결정을 감추는 경계로 나눠야 한다는 생각이다.
변동성은 기능보다 결정에 붙어 있다
예를 들어 결제 시스템을 생각해 보면, 결제라는 기능 자체보다 외부 PG사 연동 방식, 실패 재시도 규칙, 정산 형식 같은 것이 더 자주 바뀔 수 있다. 게임에서도 전투 시스템보다 수치 테이블, 입력 장치, 렌더링 백엔드, 저장 포맷이 더 자주 바뀌는 경우가 많다.
이런 결정을 여러 모듈에 흩뿌리면 변경은 곧 연쇄 수정이 된다. 반대로 경계 안에 숨겨 두면 변경 영향은 줄어든다.
리팩터링이 중요한 이유도 결국 변동성 때문이다
마틴 파울러가 말하는 리팩터링은 설계를 멋지게 보이게 하는 작업이 아니다. 행동을 유지한 채 구조를 바꿔, 다음 변경을 더 안전하게 만드는 작업에 가깝다. 그래서 리팩터링이 가장 힘을 발휘하는 순간도 자주 바뀌는 것이 퍼져 있는 걸 발견했을 때다.
좋은 리팩터링은 대개 이런 방향으로 간다.
- 중복된 변경 지점을 한곳으로 모은다
- 경계 밖에서 내부 세부를 몰라도 되게 만든다
- 인터페이스에는 덜 바뀌는 약속만 남긴다
이렇게 해야 모듈이 진짜 의미를 갖는다.
마치며
좋은 설계를 복잡한 추상화나 거대한 패턴으로만 이해하면 실무에서 자주 길을 잃는다. 더 실용적인 질문은 이것이다. 무엇이 자주 바뀌고, 그 변경이 지금 어디까지 퍼져 있는가.
설계의 핵심은 늘 거기서 시작된다. 변동성을 읽고, 그것을 모듈 경계 안에 숨기고, बाकी는 가능한 한 단순하게 유지하는 것. 결국 유지보수성이란 이 원리를 얼마나 일관되게 지키느냐의 문제에 가깝다.