612. 헥사고날 포트와 어댑터 외부 격리 (Hexagonal Architecture / Ports and Adapters)
핵심 인사이트 (3줄 요약)
- 본질: 헥사고날 아키텍처(Hexagonal Architecture / Ports and Adapters)는 611장 클린 아키텍처의 원형 도면을 "육각형"으로 찌그러뜨린 실전 설계 템플릿으로, 시스템의 핵인 도메인(Domain)을 정중앙에 두고 외부 세계와의 모든 통신을 오직 '포트(Port)'와 '어댑터(Adapter)'라는 플러그(Plug) 구멍으로만 제한하는 극강의 망분리 헌법이다.
- 가치: 안에서 밖으로 나가는 DB 저장이나 밖에서 들어오는 웹 요청은 철저히 포트를 통한다. 비즈니스 로직 뇌는 내가 웹에 있는지, 뒤에 붙은 DB가 오라클인지 모르는 '완벽한 맹인(Agnostic)' 상태가 되어, 언제든 앞뒤 부품을 1초 컷으로 갈아 끼울 수 있는 진정한 플랫폼 독립성을 이룩한다.
- 융합: 객체 지향의 **의존성 역전 원칙(DIP, 601장)**을 인프라 레벨로 승격시킨 마스터피스로, **마이크로서비스 아키텍처(MSA, 532장)**와 도메인 주도 설계(DDD, 534장) 생태계를 지배하는 실무 백엔드 개발자들의 절대 1순위 코딩 표준 족보로 숭배받고 있다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
-
개념:
- 육각형 (Hexagon): 코어 뇌에 꽂히는 외부 잡동사니(웹, DB, 메시지 큐)가 다방면으로 무한히 많다는 걸 보여주기 위해 육각형으로 그린 것.
- Port (구멍/소켓): 코어(뇌)가 세상과 대화하기 위해 자기 몸에 뚫어놓은 'USB 잭 구멍(Interface)'.
- Adapter (어댑터/변환기): 밖의 220V 전기를 그 USB 구멍에 맞게 깎아서 꽂아주는 통역사.
-
필요성 (양방향 스파게티 침공의 멸망): 옛날엔
Controller ➡ Service ➡ DB로 화살표가 무조건 밑으로 쏠렸다. 주니어가Service로직 안에@KafkaListener를 떡칠하고, 파싱 코드를 한가운데 쑤셔 박아 코어 뇌가 오염됐다. "비즈니스 로직은 순수한 수학 공식이어야 하잖아!! 왜 통신 프로토콜이 내 뇌를 직접 찌르게 냅둬?! 뇌 겉에다 '입력 포트' 하나만 뚫고, 밖에서 카프카용 어댑터 따로 짜서 꽂아 넣게 분리해!!" 이 오염에 대한 강박적 혐오가 헥사고날 철창을 완성했다. -
💡 비유: 쌩 코딩은 **'컴퓨터 메인보드에 모니터, 키보드 선을 아예 인두기로 영구 납땜해 버린 짓'**입니다. 헥사고날 아키텍처는 본체 뒤에 'USB 포트(Port)' 딱 10개만 뚫어두는 겁니다. 본체는 밖에 키보드가 달렸는지 마우스가 달렸는지 알 필요 없습니다. 'USB 어댑터' 규격만 맞게 만들어서 찰칵 꽂으면, 무선 키보드든 마우스든 1초 만에 핑퐁 대화가 돌아가는 완벽한 플러그 앤 플레이 조립식 생태계입니다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
1. 육각형을 가로지르는 3대 티어 (Left ➡ Center ➡ Right)
① 좌측: Inbound (Driving / 찌르는 놈들)
- 밖에서 내 시스템(뇌)을 때리며 명령하는 주동자들 (Web Controller).
- Inbound Port: 코어 뇌가 뚫어둔 방패 껍데기(Interface).
interface OrderUseCase - Inbound Adapter: 유저의 HTTP 텍스트를 예쁘게 포장해 포트 대문을 찔러 호출하는 봇.
② 정중앙: Domain & Application Core (신성한 뇌 🧠)
- "주문 시 재고 까고 돈 깐다." 비즈니스 규칙과 유스케이스.
- 왼쪽도 오른쪽도 모른다. 모든 소스 코드에
import된 패키지는 오직 '자바 순수 라이브러리(POJO)'뿐이어야 한다.
③ 우측: Outbound (Driven / 찔림 당하는 놈들) 💥 (핵심)
- 코어 뇌가 "정보 모자라네" 하고 밖을 찌를 대상들 (MySQL DB, 외부 API).
- Outbound Port: 코어 뇌가 파둔 대문(Interface).
interface DBPort { void save(); }. - Outbound Adapter: 저 밖에서 땀 뻘뻘 흘리며 오라클 쌩쿼리를 쳐서 DB에 데이터를 박아넣고, 다시 예쁜 객체로 통역해서
DBPort를 통해 뇌한테 바친다. ▶ 결과: 화살표는 우주가 두 쪽 나도 오직왼쪽(어댑터) ➡ 중앙(코어) ⬅ 오른쪽(어댑터)으로만 꽂힌다.
2. 안티패턴: '포트 생략(Bypassing Port)'의 스파게티 지름길 💥
- 똥볼:
OrderService(코어) 뱃속에서new MySQLAdapter()를 쌩으로 하드코딩 쳐 부르거나, Outbound Port(인터페이스)를 안 파고 밖의 어댑터 클래스 파일을 다이렉트로import쳐버린다. - 파국: 코어 뇌가 바깥 세상(MySQL)의 똥내를 직접 맡게 된다(의존성 화살표 밖으로 튀어나감). 1년 뒤 MySQL을 Redis로 바꿀 때 코어 로직 수천 줄에 시뻘건 컴파일 에러가 터진다.
- 아키텍트 철퇴: "포트(Interface)는 코어 뇌와 바깥 세상 사이의 '방독면'이다!! 방독면 안 끼고 밖의 똥 공기(Adapter)를 마시는 순간 코어는 오염된다. 껍데기(Port)를 생략하면 헥사고날 아키텍처는 거대한 스파게티 쓰레기봉투로 전락한다."
Ⅲ. 융합 비교 및 다각도 분석
1. 아키텍처 뼈대 삼국지 (Layered vs Clean vs Hexagonal)
| 척도 | 1. 3단 레이어드 (Layered) 🪨 | 2. 클린 아키텍처 (Clean) 👑 | 3. 헥사고날 (Hexagonal) 🚀 |
|---|---|---|---|
| 모양새 | 위에서 아래로 층층이 | 둥근 양궁 과녁 4개 | 육각형 (왼쪽 Inbound, 오른쪽 Outbound) |
| 의존성 방향 | 무조건 위 ➡ 아래 (DB가 1짱) | 무조건 밖 ➡ 안 (코어가 1짱) | 무조건 밖 ➡ 안 (코어가 1짱) |
| 핵심 철학 | "데이터(DB)가 최고야! 다 DB 봐!" | "DB는 쓰레기야! 비즈니스 로직 짱!" | "클린 아키텍처 짱! 근데 실전 코딩하기 짱 편하게 정리해 줄게 ㅋ" |
과목 융합 관점
- 소프트웨어 공학 (TDD 테스트 자동화 폭격의 지상낙원 470장): 헥사고날의 뇌(Domain)는 바깥과 완벽히 찢어져 있다. 밖을 쳐다보는
Outbound Port에다가 **가짜 더미 객체(Mockito)**를 푹! 꽂아버린다. DB 다 끄고 오직 램(RAM) 위에서 내 코어 로직만 0.001초 컷으로 폭격(Unit Test)하며 무결성을 증명해 내는 '목킹 생태계'의 전제 조건이다.
Ⅳ. 실무 적용 및 기술사적 판단
실무 시나리오
-
시나리오 — 'DTO와 Entity의 비빔밥 스파게티', 컨트롤러가 DB 심장을 직빵 찔러 해킹 폭파 대재앙: 주니어 개발자가 DB랑 1:1 매핑된
UserJpaEntity객체(비밀번호 포함)를 코어 뇌(Use Case)를 관통시켜 밖의WebController까지 끌어 올렸다. 그리고 쌩 JSON으로 쏴버려 해커가 비밀번호를 다 털어갔다.- 아키텍트의 해결책: 3단 분할 맵핑(Mapping) 수술과 껍데기(DTO) 환승 강제다.
Web DTO(바깥 원, 이름/나이만),Domain Entity(중앙 뇌, 비즈니스 로직),JpaEntity(바깥 원 DB, DB 매핑용). 이 3개의 세상은 절대 직빵으로 넘어갈 수 없다!! 어댑터 놈들이 땀 뻘뻘 흘리며 1개씩 핀셋으로 뽑아 수동으로 옮겨 담아(Mapping) 넘겨줘야만 방화벽이 성립된다.
- 아키텍트의 해결책: 3단 분할 맵핑(Mapping) 수술과 껍데기(DTO) 환승 강제다.
-
시나리오 — '무거운 프레임워크(Spring)의 코어 뇌 오염': 시니어 개발자가 코어 뇌 뱃속에다 Spring의
@Transactional어노테이션을 이마에 찍어놨다. 3년 뒤 Spring 버리고 Node.js로 이사 가려 했더니 컴파일러가 시뻘건 에러를 토하며 즉사했다!!- 아키텍트의 해결책: 극단적 POJO 순결주의와 프레임워크 오프로딩이다. 뇌 뱃속의
@Transactional을 찢어내어 휴지통에 던지고, 밖의Outbound Adapter단으로 트래픽 권한을 100% 쫓아내어 짬처리(Offloading) 쳐야 한다.
- 아키텍트의 해결책: 극단적 POJO 순결주의와 프레임워크 오프로딩이다. 뇌 뱃속의
도입 체크리스트
- 비즈니스적: "전사 개발자가 5년 이상 달라붙어 수십 번 기획 변동을 쳐맞을 코어(Money-making) 도메인인가?" 단순 게시판 짜는데 파일 5장을 쌩노가다로 파서 조립하면 인건비 낭비로 사장님한테 뺨 맞는다. 헥사고날은 오직 "결제/정산/주문" 코어 도메인에 핀셋으로 대서 텐트를 쳐야 유지보수 꿀을 빨아먹는 타겟팅 전술이다.
Ⅴ. 기대효과 및 결론
정량/정성 기대효과
| 구분 | Spring + JPA @Entity 강결합 3단 햄버거 레이어 | Hexagonal Port & Adapter 철통 방어막 융합 | 개선 효과 |
|---|---|---|---|
| 정량 | 오라클 ➡ Redis 이관 시 소스 1만 줄 파괴 수정 1달 | Core 수정 0줄. 밖의 Adapter 파일 딱 1개 핫스왑 1일 컷 | 외부 인프라 스위칭 리드타임 99% 다이어트 |
| 정성 | "스프링 어노테이션 꼬여서 전사 파드 에러 뿜어!! ㅠ" | "내 코어 뇌는 순수 자바야 ㅋ 스프링 뒤져도 끄떡없어" | 기술 스택 락인으로부터 비즈니스 코어의 이식성 획득 |
미래 전망
- 프레임워크 레벨 자동 구조화 (Spring Modulith): 주니어들의 헥사고날 폴더 파기 노가다를 부수기 위해
Spring Modulith(599장 연계) 흑마법이 등장했다. 애노테이션 1방 치면 인/아웃바운드 Port 침투 룰을 컴파일 단계에서 기계적으로 락(Lock) 걸어주고 UML 다이어그램까지 그려주는 Zero-Toil 시대가 안착 중이다. - Serverless (FaaS)와의 시너지 (Nano-Architecture): 웹을 받는
Inbound Adapter람다(A), 비즈니스Core람다(B), DB 찌르는Outbound Adapter람다(C)로 띄워 카프카로 엮어버린다!! 무거운 코어 람다만 오토스케일링 치는 궁극의 하드웨어-소프트웨어 일치형 분산 다이어트 아키텍처가 빛나고 있다.