[SpringBoot] 스프링부트 프로젝트의 아키텍처 | Layered, Hexagoal, Clean

도톨이·2025년 8월 27일

SpringBoot

목록 보기
3/4
post-thumbnail

안드로이드, 플러터 개발을 할 때에도 클린 아키텍처(+MVVM) 를 사용하거나 MVC 패턴을 적용해서 구조를 잡고 시작했었다.
그렇다면 스프링 부트 프로젝트에서는 어떤 아키텍처를 사용하는지 알아보려고 한다.


아키텍처란?

소프트웨어 아키텍처란 애플리케이션의 구조와 계층을 정의하고, 각 계층의 책임을 분리하는 설계 방식이다.
쉽게 말해 “프로젝트를 어떤 방식으로 나눠서 유지보수성과 확장성을 높일지”를 정하는 설계도라고 보면 된다.

스프링 진영에서 대표적으로 사용되는 아키텍처는 다음과 같다:

  1. 레이어드 아키텍처 (Layered Architecture)
  2. 헥사고날 아키텍처 (Hexagonal Architecture)
  3. 클린 아키텍처 (Clean Architecture)

그리고 최근 현업에서는 DDD(도메인 주도 설계) + 레이어드 아키텍처 조합이 흔히 쓰인다. (단, 상황에 따라 헥사고날/클린을 선택하는 팀도 있다)


1. 레이어드 아키텍처

레이어드 아키텍처는 애플리케이션을 서로 다른 논리적 계층으로 분리하는 패턴이다.
흔히 n-티어 아키텍처(n-tier architecture) 라고도 불리는데, 여기서 n은 계층의 수를 의미한다.
(다만 n-티어는 배포 관점, 레이어드는 논리 계층 분리를 의미한다는 점에서 개념적으로 구분된다)

가장 기본적인 구조는 다음과 같은 4계층이다:

  1. Presentation Layer (Controller)

    • 사용자와 직접 상호작용
    • 브라우저/클라이언트와 통신, 요청을 받아 Service로 전달
  2. Business Layer (Service)

    • 핵심 비즈니스 로직 수행
    • 규칙과 트랜잭션 관리
  3. Persistence Layer (Repository)

    • 데이터 접근 계층
    • JPA, MyBatis, JDBC 등을 이용해 CRUD 수행
  4. Database

    • 실제 데이터가 저장되는 외부 시스템 (MySQL, PostgreSQL 등)

흐름은 보통 Controller → Service → Repository → Database 순으로 내려간다.
(실무에서는 Repository와 DB를 하나로 묶어 3계층 구조로 설명하기도 한다)


📌 참고 GitHub: Spring Petclinic (spring-projects)
→ 전통적인 레이어드 아키텍처의 대표적인 예시


2. 헥사고날 아키텍처 (Ports & Adapters)

헥사고날 아키텍처는 2005년 Alistair Cockburn이 제안한 스타일로, 흔히 Ports & Adapters 패턴이라고 부른다.
핵심은 단순하다:
👉 애플리케이션 코어(비즈니스 로직)를 외부 기술(데이터베이스, UI, 메시지, API 등)로부터 완전히 분리한다.

구조

  • Core (도메인 로직, 애플리케이션 서비스)

    • 비즈니스 규칙과 도메인 모델을 담는다.
    • DB나 UI가 무엇인지 모른 채, 오직 로직에만 집중한다.
  • Ports (포트, 인터페이스)

    • 코어가 바깥과 대화하기 위한 규약.
    • Input Port: 코어를 호출하는 진입 규약 (구현은 Application Service)
    • Output Port: 코어가 외부 자원에 접근할 때 정의하는 규약 (구현은 Adapter)
  • Adapters (어댑터, 구현체)

    • 실제 기술 스택(DB, REST API, MQ 등)을 포트 규약에 맞게 구현.
    • 예: JpaOrderRepositoryAdapter, KakaoPayAdapter, RabbitMQAdapter
[ DB / REST API / Message Queue / UI ]
             ↕ (Adapters)
          [ Ports (Interfaces) ]
             ↕
       [ Application Core ]

장점

  • 코어는 외부 기술을 전혀 모른다. DB나 API가 바뀌어도 Adapter만 교체하면 된다.
  • Ports 덕분에 DB 없이도 단위 테스트가 가능하다.
  • 다양한 입출력 인터페이스(REST, CLI, MQ)를 유연하게 붙일 수 있다.

단점

  • 인터페이스/구현체 분리가 많아져 코드량이 늘고 복잡하다.
  • 작은 CRUD 애플리케이션에서는 오버엔지니어링이 될 수 있다.
  • 디버깅/흐름 추적이 단순 레이어드보다 어려울 수 있다.

카카오페이 기술 블로그에서도 이렇게 밝힌 바 있다.
“헥사고날 아키텍처를 도입했지만, 비즈니스가 단순한 상황에서는 오히려 추상화·계층이 과도해져 복잡성과 유지보수 부담이 커졌다. 결국 제거하는 선택을 했다.”
카카오페이 기술 블로그


📌 참고 GitHub:


3. 클린 아키텍처 (Clean Architecture)

클린 아키텍처는 Robert C. Martin(Uncle Bob)이 제안한 방식으로, 의존성이 항상 안쪽(도메인)으로만 흐르는 구조이다.
즉, 도메인은 프레임워크나 DB에 의존하지 않고 독립적으로 존재한다.

계층 구조

  1. Entities (도메인 모델)

    • 가장 안쪽 계층
    • 순수 비즈니스 규칙과 상태 (User, Order, Payment 등)
  2. Use Cases (애플리케이션 계층)

    • 엔티티를 활용해 구체적인 시나리오 실행
    • “주문 생성하기”, “결제 승인하기” 같은 유스케이스
  3. Interface Adapters

    • UseCase ↔ 외부 인터페이스(DB, 웹, UI)를 연결
    • DTO ↔ Entity 변환, Controller, Repository 구현체
  4. Frameworks & Drivers

    • 가장 바깥 계층
    • Spring, JPA, MySQL, 외부 API, UI 등 구체적 기술
[ Frameworks & Drivers ] 
        ↓
[ Interface Adapters ] 
        ↓
[ Use Cases ]
        ↓
[ Entities ]

장점

  • 도메인 모델이 외부 기술에 오염되지 않는다.
  • DB 없이도 UseCase/Entity만 단위 테스트 가능.
  • 프레임워크/DB 교체가 상대적으로 용이하다.

단점

  • 설계와 구현이 복잡하고 초기 비용이 크다.
  • 작은 프로젝트에는 불필요하게 과해질 수 있다.
  • 계층 분리가 잘못되면 오히려 의존성이 꼬여 복잡해진다.

📌 참고 GitHub:


+) DDD + 레이어드 아키텍처

현업에서 많이 쓰이는 건 사실 DDD(도메인 주도 설계) + 레이어드 아키텍처이다.

  • 전통적인 Controller–Service–Repository 구조를 유지하면서,
  • DB 스키마 중심이 아니라 도메인 모델(Entity, Value Object, Aggregate)을 먼저 정의하고 이를 코드와 DB에 반영한다.

DDD를 통해 **도메인 언어(Ubiquitous Language)**를 코드에 반영하면, 비즈니스 전문가와 개발자가 같은 언어로 소통할 수 있다는 장점이 있다.


📌 모바일 vs 스프링 아키텍처 차이

그렇다면 왜 모바일은 클린 아키텍처를 많이 쓰고, 스프링에서는 DDD+레이어드가 더 흔할까?

  • 모바일/프론트엔드

    • UI가 자주 바뀌고, 플랫폼 의존성이 많음 (iOS/Android 차이, 뷰모델·상태관리 등)
    • 따라서 도메인 로직을 UI 코드와 강하게 분리하는 클린 아키텍처가 적합
    • 구글 공식 문서에서도 “Guide to app architecture”에서 MVVM+Clean 구조를 권장
  • 스프링(Spring Boot)

    • 프레임워크 자체가 이미 IoC/DI, 레이어드 구조를 강력히 지원
    • @RestController, @Service, @Repository만으로 전형적인 계층 구조 완성
    • 도메인 복잡성이 낮은 서비스는 굳이 클린 아키텍처까지 들이지 않아도 충분히 관리 가능
    • 대신 **도메인 중심(DDD)**으로 사고하면서, 전통 레이어드 구조를 유지하는 것이 사실상의 표준처럼 자리 잡음

✅ 정리

  • 레이어드 아키텍처: 가장 단순·전통적인 구조
  • 헥사고날 아키텍처: 코어와 외부 기술을 강력히 분리 (Ports & Adapters)
  • 클린 아키텍처: 의존성 방향을 안쪽으로만, 도메인 완전 독립
  • DDD + 레이어드: 스프링 현업에서 가장 흔한 조합

profile
Kotlin, Flutter, AI | Computer Science

0개의 댓글