실무에서 디자인 패턴은 이상과 타협의 연속이다
패턴을 공부할 때는 기대가 생긴다. 싱글톤, 팩토리, 옵저버… 각각 어떤 문제를 해결하는지 이해하고, 예제 코드를 보면서 “이걸 알면 설계를 제대로 할 수 있겠다”는 확신이 온다. 그런데 실무에 가져가면 교과서와 다른 이야기가 시작된다.
레거시 코드 앞에서의 현실
처음 레거시 시스템을 만났을 때 가장 먼저 든 생각은 다 갈아엎고 싶다는 것이었다. 이상적인 구조로 처음부터 다시 짜면 얼마나 좋을까. 그런데 막상 건드려보면 뭐 하나 고쳤더니 예상치 못한 곳에서 문제가 생기고, 얽혀 있는 게 얼마나 많은지 실감하게 된다.
결국 배운 건 점진적 개선이다. 완벽한 구조로 한 번에 바꾸겠다는 접근은 레거시 앞에서 통하지 않는다. 조금씩, 영향 범위를 최소화하면서 나아가는 것이 현실적인 방법이다.
패턴별 실무 후기
싱글톤은 전역 상태를 관리할 때 편하다. 설정 값, 공통 유틸 인스턴스 같은 것들. 그런데 테스트 코드를 짜다 보면 고통받는다. 전역 상태가 테스트 간에 오염되고, 의존성을 교체하기도 어렵다. 편리함 뒤에 대가가 있는 패턴이다.
팩토리 패턴은 객체 생성 로직을 한 곳에 모아두는 데 유용하다. 그런데 프로젝트가 작으면 오히려 인다이렉션만 늘어나는 느낌이 든다. 추상화 레이어가 하나 더 생기는 셈이라, 코드 파악이 더 어려워질 때도 있다.
옵저버는 이벤트 기반 처리에 강하다. 그런데 디버깅이 어렵다. 이벤트가 어디서 발행되고 어디서 소비되는지를 추적하려면 코드를 꽤 파고 들어가야 한다. 콜백이 중첩되기 시작하면 흐름을 따라가기 더 힘들어진다.
아키텍처 결정의 현실
완벽한 설계는 없다. SOLID 원칙을 그대로 지키는 것과 내일까지 배포해야 하는 현실 사이 어딘가에서 실무의 설계가 이루어진다. 팀원들의 이해도, 코드베이스의 역사, 납기일—이것들을 함께 고려해야 한다. 확장성이 중요해 보여도 당장 운영이 안 되면 의미가 없다.
패턴이 해결책이 아니라 도구라는 것. 어떤 패턴을 쓰느냐보다 현재 상황에서 어떤 문제를 해결하려는지를 먼저 물어야 한다. 그 타협 과정을 부끄러워할 필요는 없다. 제약 안에서 최선을 찾는 것 자체가 실무 개발자의 역량이다.
연결 (이유)
- 레거시 시스템 유지보수에서 문서화 부재는 예상치 못한 복잡성으로 이어진다 — 레거시 코드 앞에서 ‘완벽한 패턴’은 현실과 충돌하고, 점진적 개선이라는 같은 결론에 도달함
- 리팩토링할 때는 쿼리 호출을 로직 바깥으로 꺼내야 프로세스가 보인다 — 디자인 패턴 원칙이 실무에서 어떤 구체적 형태로 타협되는지 보여주는 직접적 사례
- FSD 아키텍처는 대규모 프론트엔드 프로젝트의 구조 문제를 계층 분리로 다룬다 — 아키텍처 도입 시 이상과 현실 사이의 타협이라는 동일한 질문을 프론트엔드 맥락에서 다룸