Chapter 6

스프링이 사랑한 디자인 패턴

  • 6.1 어댑터 패턴
  • 6.2 프록시 패턴
  • 6.3 데코레이터 패턴
  • 6.4 싱글턴 패턴
  • 6.5 템플릿 메서드 패턴
  • 6.6 팩터리 메서드 패턴
  • 6.7 전략 패턴
  • 6.8 템플릿 콜백 패턴

디자인 패턴을 외우는 건 의미 없어. 패턴은 SOLID 원칙이 실제 코드에서 나타나는 형태일 뿐이고, 이 장에서 다루는 패턴들은 전부 스프링 내부에서 쓰이고 있거든.

어댑터는 호환 안 되는 인터페이스 사이에 끼우는 변환기야. 한국 플러그를 미국 콘센트에 꽂을 때 어댑터가 필요하듯이, 기존 코드를 수정하지 않고 새 인터페이스에 대응할 수 있어. 프록시는 대리인이야. 실제 객체 대신 먼저 요청을 받아서 접근 제어나 지연 초기화 같은 부가 작업을 한 뒤에 실제 객체에게 넘기는 구조지. 데코레이터는 구조가 프록시와 거의 같은데 목적이 달라 — 프록시는 제어 흐름을 조정하고 반환값은 안 바꾸지만, 데코레이터는 반환값에 기능을 추가해. 기본 커피에 우유 데코레이터, 샷 데코레이터를 겹겹이 쌓아서 기능을 확장하는 식이야. 자바 I/O 스트림의 BufferedReader(InputStreamReader(FileInputStream())) 구조가 정확히 이 패턴이지.

싱글턴은 클래스의 인스턴스를 하나만 만들어 쓰는 패턴이야. 생성자를 private으로 막고 static 메서드로만 접근하게 해서 프로그램 전체에서 단 하나의 객체만 존재하게 하지. 스프링 빈이 기본적으로 싱글턴인 이유가 여기 있어.

템플릿 메서드는 상위 클래스에서 알고리즘의 골격을 정하고, 구체적인 단계만 하위 클래스가 채우는 구조야. "물 끓이기 → 우리기 → 컵에 따르기 → 첨가물 추가"에서 우리기와 첨가물만 커피와 차가 다르게 구현하는 식이지. 팩터리 메서드는 객체 생성을 하위 클래스에 위임해서, 새 타입이 추가돼도 기존 코드를 안 건드리게 만들어.

그리고 이 장에서 가장 중요한 건 전략 패턴이야. 알고리즘을 인터페이스로 캡슐화하고, 구체적인 전략을 외부에서 주입하는 구조거든. Sorter에게 BubbleSort를 넣었다가 QuickSort로 바꿀 수 있는 거지. 여기서 "전략을 외부에서 주입한다"는 부분이 7장의 DI(의존성 주입) 와 정확히 같은 원리야. 템플릿 콜백 패턴은 전략 패턴의 변형인데, 별도 클래스를 만드는 대신 익명 클래스나 람다로 전략을 즉석에서 넘겨. 스프링의 JdbcTemplate, RestTemplate이 전부 이 패턴이야 — 변하지 않는 보일러플레이트는 템플릿이 가져가고, 변하는 로직만 콜백으로 받는 거지.

결국 모든 패턴은 SOLID 위에 서 있어. 어댑터와 데코레이터는 OCP, 전략 패턴은 OCP + DIP, 템플릿 메서드는 DIP. 패턴 이름을 외우기보다 어떤 원칙을 어떻게 구현하는지 연결해서 이해하는 게 핵심이야.


정리

6장 읽고 기억할 거 네 가지:

  1. 어댑터는 변환기, 프록시는 대리인, 데코레이터는 장식자. 구조는 비슷하지만 목적이 다르다. 프록시는 제어 흐름 조정(반환값 안 바꿈), 데코레이터는 기능 추가(반환값 바꿈)
  2. 전략 패턴은 스프링의 설계 철학이다. 알고리즘을 인터페이스로 캡슐화하고 외부에서 주입하는 구조 — 이게 DI의 원형
  3. 템플릿 콜백 패턴은 스프링에서 가장 많이 보이는 패턴이다. 변하지 않는 코드는 템플릿이, 변하는 코드는 콜백으로 분리
  4. 모든 패턴은 SOLID 위에 서 있다. 패턴을 외우기보다, 어떤 원칙을 어떻게 구현하는지 연결해서 이해하는 게 중요하다