-
더러운 방 정리하기 : 클린 아키텍처 (헥사고날 아키텍처)백엔드 : 서버공부/Spring 2025. 10. 28. 13:54728x90
들어가며
드디어 새로운 회사 입사 전까지 숨을돌릴 수 있게되어서 이태원에서 카공을 해보았는데요
하늘이 맛집이더라고요
가을이 들렸다 갔습니다.
본론으로
클린 아키텍처, 왜 중요할까?우리가 일에서 마주하게 되는 코드는 대부분 복잡하다.
특히 회사 실전 코드일수록 더 복잡하다.
이런 느낌
현실의 코드는 보통 이런 느낌이다.
이런 방에 공기청정기를 하나 두려고 생각해보자.
놓을 자리 찾는 것부터 스트레스일 거다.
자리를 만들려면 먼저 치우고, 선 정리하고, 기존 가구 위치도 바꿔야 한다.우리가 현업에서 “새 기능을 추가한다”는 건 사실 이 작업이랑 비슷하다.
이미 혼란스러운 공간에 뭘 하나 더 얹는 일.반대로 이런 방을 떠올려보자.

가구도 적고, 배치도 단순하고, 바닥도 깨끗하다.
여기에 공기청정기를 들고 와서 툭 놔두는 건 정말 쉬운 일이다.프로젝트도 마찬가지다.
기능이 많지 않고 구조가 단순한 서비스라면, 새로운 기능을 붙이는 건 금방 끝난다.하지만 현실은 이런 이상적인 상태가 아니다.
우리가 다루는 대부분의 서비스는 이미 많은 기능을 담고 있고,여러 팀과 여러 사람이 오랫동안 손댄 코드가 한데 얽혀 있다.
그러니까 실제로는 “깔끔하고 단순한 방”이라기보다는 이런 모습에 더 가깝다.

겉으로 보면 물건이 많다. 가구도 많고, 케이블도 많고, 이것저것 다 있다.
그런데 중요한 건 ‘어질러져 있지 않다’는 거다.
카테고리별로 정리돼 있고, 자리가 정해져 있고, 어떤 선이 어디로 연결되는지 보인다.이런 방에는 공기청정기 하나쯤 더 들여놓는 게 어렵지 않다.
왜냐면 “어디에 두면 되는지”가 이미 눈에 보이기 때문이다.우리가 추구해야 하는 프로젝트 구조가 바로 이거다.
깔끔해서 비어 있는 시스템이 아니라,
많은 기능을 갖고 있지만 그 복잡함이 정리돼 있는 시스템.이게 우리가 아키텍처를 고민하고 도입하려는 이유다.
우리는 결국 복잡해질 수밖에 없는 제품을 만들고 있다.
그 복잡함을 통제 가능한 방식으로 관리하는 구조그게 아키텍처다.
소프트웨어 아키텍처의 핵심 목표
소프트웨어 아키텍처는 “기능을 어디에, 어떤 형태로 담을 것인가?”에 대한 구조적 약속이다.
여기서 목표는 멋진 폴더 구조를 만드는 게 아니다. 진짜 목표는 비용이다.유지보수 과정은 항상 같은 순서를 반복한다.
- 코드를 읽고
- 이해하고
- 수정한다.
이 세 단계가 빠르면 유지보수 비용이 낮고, 느리면 비용이 올라간다.
문제는 기능이 멀쩡히 잘 돌아가도, 내부 구조가 엉망이면 이 비용이 기하급수적으로 올라간다는 거다.
누군가 한 군데만 바꿔도 옆 기능이 깨지고,
사이드 이펙트가 어디서 터질지 모르니까 테스트도 오래 걸리고,
결국 우리는 이렇게 말하게 된다."이럴 바엔 그냥 새 프로젝트 파는 게 낫지 않나...?"
이 말이 나오는 순간, 이미 그 서비스는 유지보수성이 한계에 온 거다.
좋은 아키텍처를 만들기 위한 재료
아키텍처를 설계한다는 건 그냥 "폴더 나누기"가 아니라,
몇 가지 재료(개념)를 동시에 관리하는 일이다.
- 패러다임
- 객체지향 / 함수형 / 절차적 / 이벤트 기반 등
- 코드가 어떤 방식으로 사고하고 흘러가는지에 대한 세계관
- 설계 원칙 (SOLID)
- SRP: 하나의 클래스는 하나의 이유로만 바뀌어야 한다
- OCP: 기존 코드를 최소한으로 건드리면서 확장 가능해야 한다
- LSP, ISP, DIP 등
- 결국 "수정보다 확장"에 유리한 구조를 만들자는 것
- 컴포넌트 응집성 원칙
- 서로 강하게 관련된 기능은 한 덩어리(컴포넌트) 안에 모아라
- 즉, 한 컴포넌트 안의 코드들은 같은 이유로 같이 존재해야 한다
- 컴포넌트 결합 원칙
- 덩어리끼리(컴포넌트끼리)는 느슨하게 연결돼야 한다
- 한 컴포넌트가 바뀌었다고 다른 컴포넌트까지 줄줄이 터지면 안 된다
하지만 이걸 매번 사람마다 “알아서 잘 지켜주세요~”라고 하는 식으로는 절대 유지되지 않는다.
이에 대한 해결책이 아키텍처 패턴이다.
아키텍처 패턴은 위 원칙들을 “실제로 지키게 만드는 틀”이다.
즉, 개발자가 실수하더라도 구조 자체가 어느 정도 안전하게 가이드해준다.대표적인 아키텍처 패턴들
- 계층형 아키텍처 (Layered Architecture)
- 클린 아키텍처 (Clean Architecture)
이런 패턴들을 따르면 앞서 말한 응집, 결합, 책임 분리 같은 원칙이 강제되기 쉬워진다.
패턴 후보 비교
계층형 아키텍처 (Layered Architecture)

구조
- 보통 수평 레이어 형태로 나눈다.
- 웹/프레젠테이션 레이어 (Controller, View)
- 도메인/서비스 레이어 (비즈니스 로직)
- 영속성/인프라 레이어 (DB 접근)
특징
- 요청은 바깥에서 안쪽으로 흐른다. (웹 → 도메인 → 영속성)
- 대부분의 전통적인 웹 서비스가 이 형태로 시작한다.
장점
- 단순하고 이해하기 쉽다.
- 업계에서 너무 익숙하다. 온보딩이 빠르다.
- 작은/초기 프로젝트에 적합하다.
단점
- 시간이 지나면 도메인 로직이 컨트롤러나 서비스 레이어 이곳저곳에 흩어지기 쉽다.
- 규모가 커질수록 레이어 간 경계가 무너지고 “서비스 덩어리 God Object”가 생긴다.
- 조직이 커지면 누가 어디까지 책임지는지 불분명해지기 쉽다 (팀 단위로 나누기 어려움).
클린 아키텍처 (Clean Architecture)

핵심 아이디어
- “도메인이 중심이다.”
- 의존성은 바깥에서 안쪽으로만 흐른다.
- UI, DB, 외부 시스템 등이 도메인에 의존할 수는 있지만
- 도메인 로직이 그 반대로 의존해서는 안 된다.
- 이것을 구현할 때 의존성 역전 원칙(DIP, Dependency Inversion Principle)을 적극적으로 쓴다.
장점
- 규칙이 명확하다: 안쪽(도메인 규칙)이 가장 중요하고, 바깥(입출력)은 교체 가능하다.
- 비즈니스 로직(핵심 규칙)에 집중할 수 있다.
- DDD(Domain-Driven Design) 같은 도메인 중심 설계 방식과 잘 맞는다.
단점
- 구조가 계층형보다 한 단계 더 복잡하게 느껴질 수 있다 (특히 처음 접하는 팀에게).
- 팀이 합의된 규칙 없이 쓰면 “추상화 과다”로 보일 수 있다.
- 현업 예제나 레퍼런스가 계층형에 비해 상대적으로 적다 (익숙한 사람이 적다).
클린 아키텍처란?
클린 아키텍처는 완전히 새로운 발명이 아니라
기존에 제안된 여러 아키텍처 스타일(계층형, 헥사고날, BCE 등)에서 좋은 부분을 통합해 정리한 개념에 가깝다.철학은 한 줄로 요약된다.
의존성은 항상 안쪽(고수준 정책, 핵심 도메인 규칙)을 향한다.
즉,
- 바깥 세계(웹 프레임워크, DB, 외부 API)는 교체 가능한 디테일일 뿐이다.
- 안쪽의 비즈니스 룰은 바깥에 묶이지 않고 오래 살아야 한다.
- 결과적으로 “비즈니스가 코드의 주인”이 되고 “기술은 플러그인”이 된다.
이 방향성의 다른 표현이 바로 관심사 분리(Separation of Concerns)다.
UI는 UI 역할만, 인프라는 인프라 역할만, 핵심 규칙은 핵심 규칙만 가진다.
이 경계를 깨지 않도록 강제로 잡아주는 틀이 곧 아키텍처다.연관된/유사한 철학을 가진 패턴들
- 헥사고날 아키텍처 (Hexagonal Architecture, Ports & Adapters)
- BCE (Boundary-Control-Entity)
- DCI (Data-Context-Interaction)
이 패턴들의 공통된 지향점은 모두 같다.
- 핵심 규칙(도메인)을 보호하라
- 바깥세상(I/O, UI, DB)은 교체 가능한 어댑터로 취급하라
- 의존성 방향을 섞지 마라
헥사고날 아키텍처
클린 아키텍처를 실용적으로 구현한 형태에 가장 가깝다.
스프링 백엔드에서 특히 널리 사용된다.

핵심 요약
- 도메인: 비즈니스 중심
- 포트: 도메인과 외부 세계를 연결하는 규약
- 어댑터: 외부 기술 요소를 도메인에 맞게 변환하는 장치
- 의존성 방향: 항상 도메인 중심으로 inward (내부로 향함
계층형과 기능 기반, 헥사고날 비교
계층형 아키텍처
- 구조: 컨트롤러, 서비스, 레포지토리로 나누는 전통적인 구조
- 장점:
- 도메인 개념이 명확하게 구분된다.
- 직관적으로 이해할 수 있다.
- 단점:
- 수평 계층 간의 분리가 점차 느슨해지면서 복잡해질 수 있다.
- 규모가 커지면 관리가 어려워질 수 있다.
기능 기반 패키지 구조

- 구조: 각 기능별로 패키지를 나누는 방식
- 장점:
- 각 기능에 대한 책임을 명확히 할 수 있다.
- 단점:
- 코드의 의존성이 복잡해지기 쉽고, 특정 기능 변경이 다른 기능에 영향을 미칠 수 있다.
포트-어댑터 기반 구조 (헥사고날)

- 구조: 도메인 중심의 아키텍처. 외부 기술과의 의존성을 포트와 어댑터를 통해 분리.
- 장점:
- 도메인이 외부 기술에 의존하지 않음.
- 도메인을 변경하지 않고도 외부 시스템(예: DB, UI 등)을 쉽게 교체 가능.
- 테스트가 용이해짐.
- 단점:
- 패키지 수와 클래스 레이어가 많아질 수 있다.
- 처음 구현할 때 러닝 커브가 있다.
아키텍처 도입 판단 기준
- 개발 및 유지보수 인력을 줄일 수 있는가?
- 의존성이 도메인 쪽으로 향하고 있는가?
- 기술 변경이 도메인에 영향을 주지 않도록 안전하게 구성될 수 있는가?
- 테스트가 용이한가?
- 아키텍처 원칙이 구조 내에서 자연스럽게 지켜지는가?
주의할 점
- 소규모 프로젝트에서는 헥사고날 아키텍처가 오히려 과할 수 있다.
- 팀 전체의 이해와 합의가 필수적이다.
결론외부 기술은 언제든지 바뀔 수 있다.
하지만 비즈니스 규칙은 자주 바뀌지 않는다.그렇다면 우리가 보호해야 할 것은 무엇일까?
바로 도메인이다.클린 아키텍처와 헥사고날 아키텍처는 이러한 목적을 달성하기 위한 접근법 중 하나이지만,
사실 이 두 아키텍처도 절대적인 정답은 아니다.
어떤 아키텍처를 선택할지는 프로젝트의 특성, 팀의 경험, 그리고 상황에 따라 달라질 수 있다.클린 아키텍처는 실제로 많은 장점이 있지만, 그만큼 복잡성을 동반하고, 러닝 커브가 존재한다.
이 아키텍처들이 모든 상황에서 항상 가장 좋은 선택이 아닐 수 있다.예를 들어, 소규모 프로젝트나 초기 단계의 개발에서는 오히려 과할 수 있다.
그때는 더 단순한 계층형 아키텍처가 더 적합할 수도 있다.
결국 중요한 점은 우리가 지향하는 구조가 도메인을 잘 보호하면서도,
실제 구현 가능하고 유지보수하기 쉬운 시스템을 만들 수 있도록 선택하는 것이다.
클린 아키텍처와 헥사고날 아키텍처는 이를 위한 하나의 해결책일 뿐, 모든 상황에서 적용되는 절대적인 법칙은 아니다.
따라서 아키텍처를 선택할 때는 항상 프로젝트의 성격, 팀의 기술 수준, 유지보수 가능성 등을 고려해 신중히 선택해야 한다.
'백엔드 : 서버공부 > Spring' 카테고리의 다른 글
Java Virtual Threads: 개념, 등장 배경 (0) 2025.10.29 MVC에서 헥사고날 아키텍처로의 여정 - 1편: 구조의 재배열 (0) 2025.10.28 널 구축하겠어 : EC2, REDIS,Docker로 CI/CD 구축하기 (0) 2025.10.08 'MSA 하자고? ' : 인기 보관소 Top5 캐시 설계기 (0) 2025.08.09 '카페인 캐시 제 1형' : 인기 보관소 로컬 캐시 적용하기 (0) 2025.08.07