👍 이 글은 NHN Dooray 협업서비스개발그린팀 김민중님의 강연 [NHN FORWARD 22] 클린 아키텍처 애매한 부분 정해 드립니다. 을 보고 정리한 내용입니다.
좋은 강연해주신 연사분께 감사드립니다. NHN 입사하면 커피 사겠습니다.
📣 소제목을 누르면 해당 발표 시간의 영상으로 이동합니다. 내용을 보다가 이해가지 않는 부분이 있다면 편하게 찾아보세요.
⚠️영상에서는 발표자께서 편의를 위해 로버트 마틴(클린 아키텍처의 저자)을 엉클 밥이라고 지칭하셨지만, 여기에서는 로버트 마틴이라고 표기하였습니다. ppt 제목의 경우에는 원본 그대로 놔두었습니다.
들어가기 전에
- 처음 클린 아키텍처를 공부해보려고 하시는 분
- 공부를 해보려다가 헷갈리는 부분이 많아서 중도에 포기하신 분
- 막상 조금씩 적용을 해보고 있는데 이게 맞나 싶은 초급자
- 소프트웨어 아키텍처의 중요성
- 좋은 아키텍처를 구성하는 방법
- 클린 아키텍처?
- 클린 아키텍처는 애매합니다
- 결론
- 처음 클린 아키텍처라는 개념을 제시한 '로버트 마틴'의 '클린 아키텍처'와
'톰 홈버그'의 '만들면서 배우는 클린 아키텍처'에 많이 기반한 발표
- '클린 아키텍처가 중요한가?' 이전에 '소프트웨어 아키텍처가 중요한가?'가 선행되어야하고, 그 이전에 '아키텍처'가 무엇인지 알아야함
- 아키텍처는 소프트웨어가 제공하는 가치,
기능과 구조
중에 구조
에 해당.
- 보통 기능에 대해서는 동의할텐데, 과연 소프트웨어가 제공하는 가치에 구조가 있는지 의문을 가질 수 있음.
- 보통 우리는 개발을 한다고 하면 기능에 집중함. 어떤 기능을 제공할건지 정하고, 그 기능이 잘 돌아가게 하는데 집중.
- 하지만 로버트 마틴은 기능보다 구조가 더 중요하다고 주장.
- 구조를 잘 만들면 개발하기 좀 수월하긴 하지만, 이게 제공하는 가치에 해당하는게 맞느냐는 의문이 생김.
기능
은 방에 들어있는 물건들, 가구들. 구조
는 어떤 식으로 배치가 되어 있는지로 비유.
- 방에 기능(물건)은 많지만, 배치(구조)는 엉망진창. 이 상황에서 새로운 기능인 가습기를 추가한다하면, 원래 있던 물건을 정리해야만 함
- 기능과 구조들이 정말 잘 배치 되어 있음
- 기능이 얼마 없는 상황에서는 이렇게 할 수도 있음
- 그러나 기능이 추가됨에 따라 이렇게 유지하는 것은 불가능.
- 이런 상황을 목표로 하면 안 됌.
- 물건들이나 가구들이 빼곡하게 있지만, 나름의 질서가 있음. 맨 처음(1.1.3)의 배치와는 다름
- 가습기(새 기능)를 놓기 어렵지 않음.
- 우리가 추구해야 할 코드는 뭔가 많이 들어있지만, 나름의 질서가 있어서 그 구조를 파악하기 어렵지 않은 상태.
- 즉 원하는 물건(기능)이 있기만 하면 전부가 아니라, 기능을 계속 더하고 뺄 때 구조가 굉장히 중요하다
- 즉, 소프트웨어 아키텍처는 기능과 구조 중, 구조에 대한 이야기다
- 방에 비유해서 설명을 했는데, 좋은 아키텍처가 그렇게까지 중요한가에 대한 의문은 여전할 수 있음
- 코딩을 처음 시작할 때 기능을 제공하기 위해 신규 프로젝트를 생성하고 코드를 작성.
- 이 때는 기능에 집중하고 구조는 조금 밀어놓을 수 있음.
- 그런데 실제로 회사에서 많이 하는 것은 유지보수.
- 유지보수란 컴퓨터에게 원하는 일(기능)을 더 정확히(버그 수정), 더 빠르게(성능 개선), 더 많이(기능 추가) 시키기 위해 코드를 읽고, 이해하고, 코드 수정/추가 하는 것.
- 우리는 처음 깨끗한 상태에서 시작하는 것 보다는, 이 행위들(유지보수)를 더 많이 함.
- 코드를 읽고 이해하고 수정하는 데 구조는 굉장히 큰 영향을 끼침.
- 구조가 잘 짜여있어야지 유지보수하기 수월.
- 즉, 기능 못지않게 구조가 중요하다.
- 구조가 기능을 뒷받침하고, 기능은 구조에 의지해서 더 안정적이고 더 수월하게 변경이 가능
"소프트웨어 아키텍처의 목표는 필요한 시스템을 만들고 유지보수하는 데 투입되는 인력을 최소화하는 것"
-로버트 마틴-
가정) 구조가 좋다 == 수정하기 쉽다 == 수정하는 데 비용(인건비 등)이 적게 든다.
- 기능 잘 동작 + 구조 엉망 : 지금은 좋지만, 수정하는데 비용이 너무 많이 든다. -> 곧 버려질 프로그램
- 기능 부족 + 구조 좋음 : 지금은 부족하지만, 수정하는 데 비용이 적게든다. 기능은 추가하면 됨.
- 논외) 기능 완성 후 변경사항이 없을 프로그램은 개발자가 투입될 이유가 없으므로 논외.
좋은 아키텍처가 굉장히 중요하다는데 동의를 했다면, 잘 구성하는 방법에 대한 의문이 들 것.
클린 아키텍처
책에서 우리가 많이 본 클린 아키텍처 다이어그램에 대해 이야기한 내용은 적다
- 책에서는 코드를 쉽게 파악하고, 변경할 수 있게 도와주는 규칙들을 나열함.
- 절반 이상이 각 규칙들이 왜 코드를 쉽게 변경하는데 좋은 구조에 도움이 되는지를 이야기함.
- 패러다임, 설계 원칙(SOLID), 컴포넌트 응집성 원칙, 컴포넌트 결합 원칙 등등
- 이런 것들을 잘 지켜서 코딩하면 좋은 아키텍처를 가진 소프트웨어를 만들 수 있음.
아키텍처 패턴
- 위 원칙들을 쉽게 적용하기 위한 것이
아키텍처 패턴
- 발표자께서는
아키텍처 패턴
이란 '좋은 아키텍처를 잡기 위한 레시피'라고 정의함.
- 따라하는 것 만으로 앞의 원칙들의 지켜지고, 그 원칙들에 대해 고민하기 쉬움.
- 복잡한 구조, 엉망인 구조에서는 그런 원칙들을 지키려해도 너무 많이 들어 엎어야함.
- 이 패턴이 모든 걸 가져다주는 건 아니지만, 원칙들을 지키기 쉽게 해주는 뼈대라고 보면 됌.
- 그런 뼈대에는 우리가 흔히 쓰는
계층형 아키텍처
가 있고, 클린 아키텍처
, 헥사고날 아키텍처
라는 것이 있음.
- 일단은 레시피를 따라해 보기
-> 요리를 처음부터 내 맘대로 변형해서 하려면 엉망이 될 수 있음
- 원칙들을 학습하고 이해한 후에 다시 레시피 대로 따라해 보기
- 각자의 프로젝트에 레시피를 적용해 보기
- 고민이 되는 지점들은 원칙에 맞게, 혹은 크게 벗어나지 않는 선에서 타협하며 적용해 보기
- 특징
- 장점
- 구조 단순
- 처음 시작할 때 적합
- 보편적이어서 모두가 익숙
- 단점
- 업무 도메인에 대해 아무 것도 말해 주지 않음
- 소프트웨어가 커지고 복잡해지면 조직화에 도움 안 됨
- 데이터베이스 주도 설계 유도
- 의존성이 웹-> 도메인 -> 영속성으로 흐르므로, 영속성부터 설계를 하게 됌.
- 특징
- 도메인이 중심(의존성 역전을 이용)
- 다형성을 이용해서, 의존성을 거꾸로 올라가게 함
- 장점
- 규칙 단순
- 계층적으로 나눈다
- 의존성은 핵심 가치인 도메인을 향한다
- 도메인이 세부 사항에 의존하지 않는다.
- 계층형에서는 도메인이 영속성이라는 세부사항에 의존
- DDD 적용 용이(도메인 주도 설계)
- 비즈니스 규칙에 집중 쉽다.
- 단점
- 패키지 구조가 계층형보다 복잡하다.
- 익숙하지 않아서 처음에 버벅일 수 있다.
- 레퍼런스가 적다.
- 로버트 마틴이 오랫동안 개발하면서 본 좋은 아키텍처들의 공통점을 통합하여 만든 것이
클린 아키텍처
- 차용한 아키텍처들에는
헥사고날 아키텍처
, 바운더리 컨트롤 엔티티
, 데이터,콘텍스트 앤 인터렉션
이 있음.
- 공통의 목표: 관심사의 분리
- 공통의 핵심 규칙: 관심사를 분리해 놓은 상태에서 의존성의 방향은 안쪽으로, 고 수준을 향함.
- 핵심 1. 중요도에 따라 계층을 나눔
- 핵심 2. 의존성의 방향은 항상 안쪽, 고수준을 향함
- 다형성을 이용하여 의존성은 어디서든 역전 가능
좋은 건 알겠는데 어떻게 학습해야하냐
클린 아키텍처
- 저자: 로버트 C. 마틴
- 유형: 바이블
- 특징: 수 많은 원칙
- 내용:
- 클린 아키텍처에 대해 설명하는 것이 아니라 아키텍처가 왜 중요하고, 좋은 아키텍처 만드려면 지켜야 하는 원칙들을 설명
- 원칙들에 대해 하나하나 설명하므로 처음 시작하기엔 어려울 순 있음.
- '쿡북'으로 접해볼 것을 권함
만들면서 배우는 클린 아키텍처
- 저자: 톰 홈버그 (스프링 컨퍼런스에서도 매번 발표)
- 유형: 쿡북
- 특징: 실제로는 한 개파인 헥사고날 아키텍처를 다룸
- 내용:
- 굉장히 얇음
- 이론적인 설명보다는 쭉 따라하면서 배울 수 있음
- 클린 아키텍처의 바이블, 좋은 아키텍처의 규범서
- 수 많은 원칙과 실천법
- 다이어그램 하나로 이루어져 있지 않음 (아래 다이어그램에 대해 설명하는 전체 406페이지 중에 16페이지 밖에 없음)

- 클린 아키텍처를 위한 실천서
- 실제로는 헥사고날 아키텍처를 다룸
- 애매하지 않고 단정적인 말투 -> 따라가기 쉬움
- 처음에 쭉 따라하며 기본 개념 익히기 좋음
- 잘 모르겠을 땐 헥사고날 아키텍처
- 클린 아키텍처 기본 다이어그램과 가장 비슷
- 클린 아키텍처의 확장이라고 보면 됌
- 클린 아키텍처가 헥사고날과 다른 아키텍처의 공통점을 뽑아 놓은 것이므로
- 따라할 수 있는 쿡북이나 레퍼런스가 가장 많음 (번역된 쿡북 3권)
테스트 주도 개발로 배우는 객체지향 설계와 실천
만들면서 배우는 클린 아키텍처
만들면서 배우는 헥사고날 아키텍처 설계와 구현

엔티티
가 중심에 있고, 유즈 케이스
가 엔티티
를 감싸고 있음
Input Port
나 Output Port
도 유즈 케이스
에 들어간다고 보면 됌
- 초록색 컨트롤러, 게이트웨이, 프레젠터스가 바깥쪽 어뎁터에 해당
- 즉 헥사고날 아키텍처는 클린 아키텍처라고 생각하고 적용해도 무방

- 특징
- 장점
- 구조 단순
- 처음 시작할 때 적합
- 보편적이라서 모두가 익숙함
- 단점
- 업무 도메인에 대해 아무것도 말해 주지 않음
- 소프트웨어가 커지고 복잡해지면 조직화에 도움 안됨

- 특징
- 서로 연관된 기능, 도메인 개념에 따라 수직의 얇은 조각으로 나눔
- 수평적 계층화의 문제를 깨닫고 수직적 계층화로 넘어 오는 경우 많음
- 수평적 계층화는 패키지 안에 여러가지 도메인이 섞여있게 됌
- 장점
- 코드의 상위 수준 구조가 업무 도메인에 대해 무언가를 알려줌
- 유스케이스가 변경될 경우 변경해야 할 코드를 모두 찾는 작업이 더 쉬워짐
- 단점

- 특징
- 수직, 수평으로 나눔
- DB 계층에 대한 의존성 역전
- 장점
- 도메인이 다른 세부 사항에 의존하지 않음
- 모든 것들의 의존성이 도메인을 향함 (클린 아키텍처의 핵심)
- 수직, 수평형 계층 구조의 장점을 모두 가짐
- 단점
- 쿡북 같은 것을 따라해보다 보면 애매한 부분이 많음
- 클린 아키텍처는 애매 그 잡채
- 규칙이 너무 단순
- 핵심 규칙 2가지 외에는 case by case라 애매한 지점이 많을 수 밖에 없다
- '핵심 2가지 외에는 너의 프로젝트에 맞게 적용을 해라'라고 하니까
1. 필요한 시스템을 만들고 유지보수하는 데 투입되는 인력 최소화에 유리한가?
2. 소스 코드 의존성이 안쪽으로, 고수준의 정책을 향하고 있는가?
3. 세부 사항이 변경되어도 도메인(핵심 규칙)에 변경이 없을 것인가?
4. 테스트하기 쉬운가?
5. 각각의 아키텍처 원칙들을 잘 지키고 있는가?
2번을 어기면 클린 아키텍처가 아님. 그냥 그 프로젝트에 맞는 아키텍처를 선택한 것.
이럴 땐 쓰지 마세요
- 소규모의 프로젝트를 진행할 때
- 프로젝트 개발자 모두가 클린 아키텍처를 이해하고 있지 않을 때 혹은 모두가 사용하기로 합의하지 않았을 때
- 클린 아키텍처는 프로젝트 전체 구조에 관여하는 것이기 때문에 혼자 맘대로 할 수 있는 것이 아님

라인 수나 파일 수보다 패키지 수가 많이 늘어남
- 방을 정리하려면 가구를 들여놔야 함
- 깔끔한 상태를 유지하려면 정리정돈을 해야 함.
=> 경계를 뚜렷하게 긋기 위해서는 패키지와 클래스가 더 필요
팀 구성원 전부 합의하고 진행해야 합니다
- 코드 일부가 아니라 패키지 구조가 바뀜
- 바뀐 패키지 구조를 다른 개발자가 이해하지 못할 수 있음
- (경험담)
알아서, 적당히, 잘, 조심스럽게
- 원칙도 100% 다 지킬수 없음. 원칙끼리 서로 간섭하고 충돌 나는 경우도 있기 때문.
- 하지만 처음부터 지름길로 가면 나중에 정석대로 못 함.
- 일단 학습 할 때는 정석대로 해서 체득하고 실전에서 지름길 사용
지름길 사용 시 반드시 클래스 상단 같은 곳에 주석으로 표시해 놔야함

- 화살표 시작하는 부분의 JPA Entity는 원래 데이터 베이스 계층의 어댑터
- 도메인 Entity랑 JPA Entity랑 굉장히 유사해서 그냥 써도 되는게 아닌가 하고 JPA Entity를 도메인 계층으로 가져와 쓸 수도 있음
=> 하지만 분리했을때 얻는 이득이 큼
- 하나로 쓰면
- 클래스, 패키지 구조는 단순화
- 영속성 계층과 도메인 계층 강결합
- Domain Entity를 다룰 때 업무 규칙 뿐만 아니라
- 연관 관계 매핑,
- 즉시 로딩/지연 로딩 등을 고려해야 함
- 분리하지 않으면 사실상 클린 아키텍처는 아닌…
- 분리하면
- 경험담
- 핵심 업무 규칙에 수정이 있을 때, DB 스키마 변경이나 데이터 마이그레이션을 먼저 고민

- 헥사고날 아키텍처에서는 의존성 역전을 위해 범용적인 인터페이스를 만들고, 어뎁터로 구현을 해서 jpa를 써라라고 말함
- 왜나면 출력 포트는 유즈 케이스가 필요로 하는 형태대로 유지가 되어야함
- 유즈 케이스가 db 세부사항에 의존하면 도메인이 영향을 받기 때문.

컴포넌트를 별도 코드 베이스로 분리하려는 게 아니라면 직접 호출
인터페이스로 뽑아야 함
- Controller가 Service의 구현에 대해 너무 많이 알지 못하도록 막기 위해 존재.
- 방향이 바뀌는 것은 아니지만, 도메인을 보호하는 것 만큼이나 컨트롤러도 도메인에 대해 보호를 받아야 함.
- 사고의 경계를 그어주는 역할
- 인터페이스는 api 스펙 같은 것.
- 우리가 뭔가를 논의 할 때 스펙부터 보는데, 스펙이 없고 구현체만 있으면 메소드를 따로 골라서 봐야함.
- 인터페이스를 따로 뽑는 게 구조를 잡기에는 유리
- 소프트웨어에서 아키텍처의 중요성
- 소프트웨어는 변화함
- 바꾸기 위해서는 읽고 이해해야 하는데, 읽기 좋고 수정하기 좋은 코드여야지 사용자에게도 더 빠르게 기능을 내보낼 수 있음
- 좋은 아키텍처를 구성하는 방법
- 많은 원칙들이 있는데, 그것들을 모두 다 따라하는 것은 어려우니 패턴을 추천
- 클린 아키텍처
- 계층을 나누고, 모든 계층은 더 중요한 쪽으로 의존성이 향해야 한다는 것이 핵심
- 클린 아키텍처는 애매합니다.
- 규칙이 단순하기 때문에 애매한데, 그것을 위한 기준들을 설명하였음
연사님 마무리 멘트
소프트웨어 아키텍처는 되게 중요한데 천시를 받고 있는 거 같다.
이 발표를 통해 중요하다는 걸 인지하고, 팀원들을 설득할 수 있을 정도가 되면 좋겠다.
클린 아키텍처가 태생적으로 애매한 부분이 있는데, 그 부분을 어떻게 결정하면 좋을지도 설명 드렸으니 클린 아키텍쳐 같이 했으면 좋겠다.