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