259. 어댑터 (Adapter) - 인터페이스 호환성 제공 레거시 연동 래퍼(Wrapper) 클래스 구조 패턴 재사용성

핵심 인사이트: (모든 구조 패턴의 시작, 변환기) 내 폰은 C타입 잭을 쓴다. 근데 이어폰은 옛날 3.5mm 동그란 구멍용이다. 내 폰 구멍에 이어폰이 절대 안 들어간다! 빡친 나는 이어폰 선을 가위로 잘라서 C타입 꼬다리로 납땜해서 뜯어고쳤다(OCP 위반). 근데 다음 날 폰을 아이폰(라이트닝)으로 바꿨다! 또 이어폰 선을 잘라서 납땜해야 한다. 개발자가 혀를 찼다. "야 이 미련한 놈아!! 네 멀쩡한 이어폰(기존 클래스) 선을 왜 가위로 잘라!! 그냥 다이소 가서 500원짜리 'C타입-to-3.5mm 변환 젠더(어댑터 Adapter)' 하나 사 와서 중간에 찰칵 끼워버리면 끝이잖아!! 네가 가진 옛날 코드가 최신 시스템 규격에 안 맞으면, 코드를 뜯어고칠 생각 하지 말고 중간에 '번역기(어댑터 클래스)'를 하나 딱 만들어서 헌 놈과 새 놈이 입을 맞추게 통역을 해버려라!!" 서로 얼굴을 붉히는 두 시스템을 화해시키는 평화의 통역기, 어댑터 패턴이다.

Ⅰ. 인터페이스 불일치 (호환성의 비극)

  • 상황: 회사에서 기가 막힌 최신_결제_기계를 만들었습니다. 이 기계는 무조건 pay(int money) 라는 함수(인터페이스 규격)만 받아들입니다.
  • 근데 10년 전부터 외주 줘서 쓰고 있던 낡은 구형_카드사_모듈이 있습니다. 이놈은 무조건 doPayment(String price) 라는 더럽게 긴 함수로만 작동합니다.
  • 재앙: 내 최신_결제_기계구형_카드사_모듈을 꽂으려고 하니 함수 이름도 다르고 파라미터도 달라서 자바 컴파일러가 쌍욕(에러)을 뱉으며 조립이 안 됩니다. 구형 모듈 코드를 뜯어서 함수 이름을 pay로 바꾸려니, 소스 코드가 없거나(남이 짠 jar 파일) 수정 시 기존 코드가 다 터질까 봐 무섭습니다(OCP 위반의 공포).

Ⅱ. 어댑터 (Adapter) 패턴의 개념 🌟

  • 개념: GoF 구조 패턴 중 하나로, 한 클래스의 인터페이스(껍데기)를 클라이언트가 요구하는 다른 인터페이스로 100% 동일하게 변환(감싸기)하여, 인터페이스가 맞지 않아 같이 쓸 수 없었던 두 클래스가 호환되어 찰떡같이 엮여 돌아가게 만들어주는 래퍼(Wrapper) 설계 패턴입니다.
  • 목적: 224번에서 배운 ACL(충돌 방지 계층)의 가장 기본이 되는 기술적 구현체로, 기존 코드(구형 모듈)를 1줄도 건드리지 않고(Closed) 새 시스템에 억지로 편입시키는 기적의 재사용 기술입니다.

Ⅲ. 변환기(Adapter)의 동작 원리와 뼈대 🌟 핵심 🌟

  1. Target (새로운 규격): 내 최신_결제_기계가 요구하는 표준 구멍입니다. (interface PaySystem { void pay(); })
  2. Adaptee (헌 놈 / 적응 대상): 구멍에 꽂히지 않는 뚱뚱한 플러그입니다. (구형_카드사_모듈.doPayment())
  3. Adapter (어댑터 번역기) 🌟:
    • 내가 다이소에서 사 온 번역기 클래스입니다.
    • 이놈은 내 시스템에 꽂혀야 하니 PaySystem 인터페이스를 상속(implements) 받습니다. (이제 밖에서 보면 이놈은 완벽한 최신_결제_기계 플러그로 보입니다.)
    • 하지만 이 번역기 뱃속(멤버 변수)에는 낡은 구형_카드사_모듈(Adaptee)객체로 몰래 품고(합성 Composition) 있습니다.
    • 밖에서 내 시스템이 Adapter.pay() 전원 버튼을 누르는 순간! 번역기는 뱃속에서 구형_카드사_모듈.doPayment() 를 대신 찰칵 눌러주어 번역을 완벽히 마칩니다!

Ⅳ. 언제 최고의 무기가 되는가?

  • 이미 엄청난 돈을 들여 만들어 놓은 낡은 **레거시(Legacy) 코드나 서드파티 외부 라이브러리(남이 짠 코드)**를 내 최신 시스템 구조에 억지로 우겨넣어야 할 때, 99.9% 확률로 이 패턴을 씁니다.
  • (※ 만약 처음부터 둘 다 내가 짜는 코드라면? 굳이 어댑터 만들지 말고 처음부터 인터페이스를 통일해서 짜는 게 당연히 백배 빠릅니다. 어댑터는 '손댈 수 없는 남의 코드'를 엮을 때 쓰는 방패입니다.)

📢 섹션 요약 비유: 어댑터(Adapter) 패턴은 해외여행 갈 때 필수품인 **'다이소 돼지코(여행용 변환 멀티 어댑터)'**입니다. 내가 한국에서 쓰던 노트북 충전기(Adaptee 낡은 시스템)는 뾰족한 220V 쇠꼬챙이 규격을 가졌습니다. 유럽 호텔(Target 새로운 시스템) 벽에 달린 콘센트는 네모난 구멍 3개 규격입니다. 내 충전기를 벽에 냅다 꽂으려 하면 구멍이 안 맞아 죽어도 안 들어갑니다(인터페이스 불일치 에러). 멍청한 사람(어댑터 패턴 모르는 놈)은 충전기 선을 가위로 잘라서 네모난 철사를 납땜으로 붙여버립니다(기존 코드 수정). 한국 오면 다시 뜯어야 하는 끔찍한 삽질입니다. 똑똑한 사람은 여행 가방에서 **'변환 돼지코(Adapter 클래스)'**를 꺼냅니다. 이 돼지코의 겉모습(Target 인터페이스 구현)은 완벽한 유럽식 네모 3구라서 벽에 쏙 들어갑니다. 그리고 돼지코의 뒷면(뱃속)에는 내 한국식 충전기가 꽂힐 수 있는 둥근 구멍이 뚫려있어 내 충전기를 품습니다(합성 Composition). 벽에서 유럽 전기가 흘러 들어오면 돼지코가 뱃속에서 그걸 한국 전기로 통역해 노트북에 흘려보냅니다. 내 소중한 충전기(기존 코드)는 흠집 하나 내지 않고 100% 무사히 보존하면서, 전혀 호환되지 않는 낯선 호텔(새로운 시스템)과 완벽한 결합(호환)을 이뤄낸 객체지향 최고의 평화협정 통역사입니다.