본문 바로가기

Theory/Architecture11

의식적으로 지금길 사용하기 지름길이란 고민없이 있는 그대로 코딩해 OOP와 스프링의 장점을 다 날려버리는 것을 의미한다. 이 책을 보는 사람들은 이 지름길이 옳은 것인지 또는 기술부채를 쌓아가는 것인지 확인해봐야 한다. 왜 지름길은 깨진 창문 같을까? 깨진창문이론이란 "어떤 것이 멈춘 것처럼 보이고, 망가져 보이고, [부정적인 형용자를 넣어보자], 혹은 관리되지 않는다고 여겨지면 인간의 뇌는 이를 더 멈추고, 망가뜨리고, [부정적인 형용사를 넣어보자]해도 된다고 생각하게 된다."는 것을 뜻한다. 기물 파손이 흔한 동네에서는 방치된 차를 도둑질하거나 망가뜨리는 일이 더 쉽게 일어난다. '좋은' 동네라도 차의 창문이 깨져있다면 차를 망가뜨리는 일이 쉽게 일어난다. 침실이 정돈돼 있지 않으면 옷을 옷장에 넣는 대신 바닥에 아무렇게나 던.. 2022. 7. 12.
아키텍처 경계 강화하기 경계와 의존성 경계를 강화한다는 것은 어떤 의미일까? 의존성을 항상 안쪽으로 흐르게 하는 것이다. 빨간선으로 되어 있는 잘못된 방향을 없애 경계를 강화해야 한다. 접근 제한자 package-private 제한자는 상당히 중요하다. 다른 패키지에서 접근하지 못하게 하며 모듈의 진입점만 public으로 하여 의존성 규칙을 위반할 위험을 줄어들게 만든다. buckpal |--- account |--- adapter | |--- in | | |--- web | | |--- o AccountController | |--- out | | |--- persistence | | | |--- o AccountPersistenceAdapter | | | |--- o SpringDataAccountRepository |--.. 2022. 7. 11.
애플리케이션 조립하기 왜 조립까지 신경 써야 할까? 코드의 의존성이 올바른 방향(도메인 방향)을 가르키기 위해서 유스케이스와 어댑터를 필요할 때 인스턴스화 하면 안된다. 유스케이스가 영속성 어댑터를 호출해야 하고 스스로 인스턴스화한다면 코드 의존성이 잘못된 방향으로 만들어진 것이다. 이것이 바로 아웃고잉 포트 인터페이스를 생성한 이유다. 유스케이스는 인터페이스만 알아야하고, 런타임에 이 인터페이스의 구현을 제공 받아야 한다. 그렇다면 객체 인스턴스를 생성할 책임은 누구에게 있을까? 그리고 어떻게 의존성 규칙을 어기지 않으면서 그렇게 할 수 있을까? 위 그림처럼 아키텍처에 대해 중립적이고 인스턴스 생성을 위해 모든 클래스에 대한 의존성을 가지는 설정 컴포넌트가 있어야 한다. 설정 컴포넌트의 역할 · 웹 어댑터 인스턴스 생성 ·.. 2022. 7. 10.
경계 간 매핑하기 매핑에 따른 의견 매핑에 찬성하는 개발자 두 계층 간에 매핑을 하지 않으면 양 계층에서 같은 모델을 사용해야 하는데 이렇게 하면 두 계층이 강하게 결합된다. 매핑에 반대하는 개발자 두 계층 간에 매핑을 하게 되면 보일러 플레이트 코드를 너무 많이 만들게 된다. 많은 유스케이스들이 오직 CRUD만 수행하고 계층에 걸쳐 같은 모델을 사용하기 때문에 계층 사이의 매핑은 너무 과하다. 매핑하지 않기 매핑하지 않는 전략을 사용하게 된다면 그림은 위 처럼 된다. 송금하기 위한 모든 클래스들이 Account 클래스를 참조하고 있다. 도메인과 어플리케이션 계층은 웹이나 영속성과 관련된 특수한 요구사항에 관심이 없음에도 불구하고 Account 도메인 모델 클래스는 모든 요구사항을 다뤄야 한다. Account클래스는 웹,.. 2022. 7. 9.
아키텍처 요소 테스트하기 테스트 피라미드 테스트의 기본 전제는 만드는 비용이 적고, 유지보수하기 쉽고, 빨리 실행되고, 안정적인 작은 크기의 테스트들에 대해 높은 커버리지를 유지해야 한다는 것이다. 이 테스트는 하나의 '단위'가 제대로 동작하는지 확인 할 수 있는 단위 테스트들이다. 테스트 피라미드가 위로 올라갈수록 비용이 더 비싸지고 실행이 느리며 깨기지 쉽다. 또, 새로운 기능을 만드는 것보다 테스트를 만드는 시간을 더 쓰게 된다. 테스트 피라미드는 테스트의 커버리지 목표를 낮게 잡아야 한다는 것을 의미한다. 맥락에 따라 테스트 피라미드에 포함되는 계층은 달라질 수 있다. '단위 테스트', '통합테스트', '시스템 테스트'의 정의는 맥락에 따라 다를 수 있다. 단위 테스트는 하나의 클래스를 인스턴스화하고 클래스의 인터페이스를.. 2022. 7. 5.
영속성 어댑터 구현하기 의존성 역전 영속성 어댑터는 아웃고잉 어댑터이다. 어플리케이션에 의해 호출될 뿐, 어플리케이션을 호출하지는 않는다. 영속성 어댑터의 책임 1. 입력을 받는다. 2. 입력을 데이터베이스 포맷으로 매핑한다. 3. 입력을 데이터베이스로 보낸다. 4. 데이터베이스 출력을 어플리케이션 포맷으로 매핑한다. 5. 출력을 반환한다. 영속성 어댑터의 핵심은 영속성 어댑터 내부에 있는 것이 아니라 커플리케이션 코어에 있기 때문에 영속성 어댑터 내부를 변경하는 것이 코어에 영향을 미치지 않는다. 영속성 어댑터는 데이터베이스에 쿼리를 날리고 쿼리 결과를 받아온다. 데이터베이스 응답을 포트에 정의된 출력 모델로 매핑해서 반환한다. 포트 인터페이스 나누기 데이터베이스 연산에 의존하는 각 서비스는 단 하나의 메서드만 사용하는 것이.. 2022. 7. 2.
웹 어댑터 구현하기 의존성 역전 웹 컨트롤러에서 외부로부터 청을 받아 어플리케이션 코어를 호출하고 무슨 일을 해야 할지 알려준다. 이 중간에 웹 어댑터와 어플리케이션 계층이 통신 할 수 있는 포트를 제공한다. 이 포트를 통해 외부와 어떤 통신이 일어나고 있는지 알 수 있다. 위 그림은 컨트롤러에서 service로 아웃고잉 어댑터를 만들 수 있다. 하지만 한 어댑터에서 둘다 수행해도 상관없다. 웹 어댑터의 책임 웹 어댑터는 URL경로, HTTP 메서드, 콘텐츠 타입과 같은 특정 기준을 만족하는 HTTP요청을 수신 후 역직렬화 한다. 1. HTTP 요청을 자바 객체로 매핑 2. 권한 검사 3. 입력 유효성 검증 4. 입력을 유스케이스의 입력 모델로 매핑 5. 유스케이스 호출 6. 유스케이스의 출력을 HTTP로 매핑 7. HTT.. 2022. 6. 29.
유스케이스 작성하기 육각형 아키텍처는 도메인 주임의 아키텍에 적합하기 때문에 도메인 엔티티를 만드는 것으로 시작한 후 해당 도메인 엔티티 중심으로 유스케이스를 구현하겠다. 도메인 모델 구현하기 송금하는 유스케이스를 구현해보자. OOP의 관점으로 Account라는 객체를 만들어 현재 잔고를 스냅샷을 하도록 한다. 계좌에 대한 모든 입금과 출금은 Activity 엔티티에 포착하고 모든 Activity에 대해 메모리를 올리는 것은 낭비이기 때문에 ActivityWindow를 통해 일정 기간만 보유한다. @AllArgsConstructor(access = AccessLevel.PRIVATE) public class Account { /** * The unique ID of the account. */ @Getter private .. 2022. 6. 21.
코드 작성하기 계층으로 구성하기 코드를 구조화하는 첫 번째 접근법으로 계층을 이용하는 것으로서, 다음과 같이 코드를 구성할 수 있다. buckpal |--- domain | |--- Account | |--- Activity | |--- AccountRepository | |--- AccountService |--- persistence | |--- AccountRepositoryImpl |--- web |--- AccountController 웹 계층, 도메인 계층, 영속성 계층 각각에 대해 전용 패키지인 web, domain, persistence를 뒀다. 의존성 역전 원칙을 적용해서 의존성이 domain 패키지에 있는 도메인 코드만을 향하도록 했다. domain에 AccountRepository 인터페이스를 추가.. 2022. 6. 20.
의존성 역전하기 단위 책임 원칙 단위 책임 원칙은 "하나의 컴포넌트는 오로지 한 가지 일만 해야하고, 그것을 올바르게 수행해야 한다."고 알고 있지만 실제 의도는 "컴포넌트를 변경하는 이유는 오직 하나뿐이어야한다."이다. 변경할 이유가 한가지라면 수행해야 하는 일도 한가지이다. 만약 컴포넌트를 변경할 이유가 한 가지라면 우리가 어떤 다른 이유로 소프트웨어를 변경하더라도 이 컴포넌트에 대해서는 전혀 신경 쓸 필요가 없다. E의 경우에는 의존하고 있는 컴포넌트가 없기 때문에 자기 자신이 변경할 이유가 있을 경우에만 수정하면 된다. 반면 A는 너무 많은 컴포넌트를 의존하고 있기 때문에 다른 어떤 컴포넌트가 바뀌든지 같이 바뀌어야 한다. 의존성 역전 원칙 의존성 역전 원칙이란 "코드상의 어떤 의존성이든 그 방향을 바꿀 수(역전.. 2022. 6. 19.
계층형 아키텍쳐의 문제는 문제일까? 계층형 아키텍쳐란? 계층으로 구성된 어플리케이션은 일반적인 3계층 아키텍처를 포함한다. 웹 계층에서는 요청을 받아 도메인 혹은 비즈니스 계층에 있는 서비스로 요청을 보낸다. 서비스에서는 필요한 비즈니스 로직을 수행하고, 도메인 엔티티의 현재 상태를 조회하거나 변경하기 위해 영속성 계층의 컴포넌트를 호출한다. 계층형 아키텍처의 문제는 무엇일까? 1. 계층형 아키텍처는 데이터베이스 주도 설계를 유도한다. 전통적인 계층형 아키텍처의 토대는 데이터베이스이다. 웹 계층은 도메인 계층에 의존하고, 도메인 계층은 영속성 계층에 의존하기 때문에 자연스레 데이터베이스에 의존하게 된다. 하지만 대부분의 어플리케이션의 목적은 규칙이나 정책을 반영한 모델을 만들어서 사용자가 이러한 규칙과 정책을 더욱 편리하게 활용 할 수 있.. 2022. 6. 16.