포트와 어댑터(Ports and Adapters) 아키텍처는 헥사고날 아키텍처(Hexagonal Architecture)로도 알려져 있으며, 애플리케이션의 핵심 비즈니스 로직을 외부 환경(UI, 데이터베이스, 외부 API 등)으로부터 완벽하게 격리하기 위한 설계 패턴이다. 내부 비즈니스 로직은 외부 세계와 소통하기 위한 규격인 '포트(인터페이스)'만 정의하고, 실제 외부 기술과의 연동은 이 포트를 구현한 '어댑터(구현체)'가 담당하게 함으로써 기술 변화에 무관한 견고한 도메인 중심 설계를 지향한다.
2. 핵심 구성 요소
포트 (Ports): 애플리케이션 핵심 계층에 정의된 인터페이스. 외부에서 내부로 들어오는 진입점(Primary/Inbound Port)과 내부에서 외부 인프라를 호출하는 규격(Secondary/Outbound Port)으로 나뉜다.
어댑터 (Adapters): 포트를 통해 애플리케이션과 외부 기술을 연결하는 구체적인 구현체.
드라이빙 어댑터 (Driving Adapters): 사용자의 요청을 받아 포트를 호출 (예: REST Controller, CLI).
드리븐 어댑터 (Driven Adapters): 애플리케이션의 요청을 받아 외부 시스템과 통신 (예: DB Repository, Mail Client).
의존성 규칙: 모든 의존성은 외부에서 내부(도메인)로 향해야 한다. 도메인은 어댑터의 존재를 몰라야 하며, 오직 포트에 정의된 추상화된 규격에만 의존한다.
3. 엔지니어링 가치
기술 스택의 독립성: 데이터베이스를 RDBMS에서 NoSQL로 바꾸거나, Web 프레임워크를 교체하더라도 애플리케이션의 핵심 비즈니스 로직은 전혀 수정할 필요가 없음.
테스트 용이성 (Testability): 외부 인프라(어댑터) 없이도 포트에 모의 객체(Mock)를 연결하여 도메인 로직만 독립적으로 완벽하게 검증 가능.
비즈니스 중심 설계: 기술적인 제약 조건에 얽매이지 않고 비즈니스 요구사항과 유즈케이스 자체에 집중하여 시스템의 핵심 가치 구현 가능.
4. 트레이드오프 및 주의사항
구현 복잡도 증가: 단순한 CRUD 애플리케이션에서도 인터페이스와 어댑터를 분리해야 하므로 초기 개발 공수와 코드량이 늘어날 수 있음.
간접 참조 오버헤드: 추상화 계층이 늘어남에 따라 코드를 직접 읽고 흐름을 파악하는 데 더 많은 인지 노력이 필요하며, IDE의 도움 없이 런타임 구현체를 찾기 어려울 수 있음.
과도한 엔지니어링 경계: 변화가 거의 확실하지 않은 영역까지 무리하게 포트/어댑터로 감싸는 것은 생산성을 저하시키는 오버엔지니어링이 될 수 있으므로 적절한 수준의 판단 요구됨.