Architecture

    Domain 모델에 Domain 로직을 담아야 하는 이유

    최근 DDD 와 관련된 공부들을 꾸준히 해나가고 있는데, 사실 이건 DDD 에 해당하는 것이 아니라 객체지향에서도 당연한 일이기도 하다. 객체가 자신의 행위(Behavior) 에 대한 인터페이스를 제공하는 것은 당연하기 때문이다. 함수형 프로그래밍에서는 객체를 모델로 만들어 두고, 행위를 정의하는 곳을 분리하여 두는 것으로 알고 있다. 하여튼 각각의 프로그래밍 패러다임으로 어떻게 구현하든 도메인 모델에 그와 관련된 행위가 정의되어 있는 것이 좋은 이유에 대해 설명해보려고 한다. 이건 사실 좋은 코드를 작성하는 가장 원칙적인 기준인 응집도에 관한 문제이기도 하다. 응집도에 대한 것을 모른다면 내가 적은 아래 글을 읽어보길 바란다. 나는 좋은 코드를 작성하는 원칙은 전부 응집도와 결합도 부터 시작한다고 생각..

    왜 계층간의 모델을 형성해야 하는가?

    최근 읽었던 책 만들면서 배우는 클린 아키텍쳐와 그리고 리뷰를 하면서 받았던 질문들 중 "언제 DTO 를 사용해야 하나요? 혹은 왜 계층간 DTO 를 사용해야 하나요?" 라는 질문을 받은 적이 있다. 예전부터 한번쯤 정리해야지 했었는데, 이제는 글로 적어두는게 나을거 같아서 해당 내용을 글로 적어보려고 한다. 일반적인 우리의 서버 아키텍쳐는 아래와 같은 구조를 가지고 있을 것 이다. 우리는 보통 Repository 는 특정 외부 저장소 혹은 내부 저장소에 질의 하는 방법을 구현하고 있을 것이고, Service 는 우리가 수행해야 할 도메인(비즈니스) 로직을 구현하고 있을 것이다. Controller 계층은 외부세계에서의 요청을 받고, 내부세계에서 쓰기 좋게 외부세계로 부터 받아온 데이터 모델을 변환(Co..

    Web 계층에 Port 를 통해 더 자유로운 코드 짜기

    아래 코드를 한번 보자. Cotroller 에서 Service 계층을 바로 참조하고 있다. 이건 보통 일반적인 비즈니스 로직을 작성할때 많이 작성되는 코드이다. @RestController class UserJoinController( private val userJoinService: UserJoinService ) { @GetMapping("/users") fun hello() { userJoinService.join() } } 이건 보통 일반적인 코드인데 한가지 문제점이라면 문제점이 있을 수 있다. 만약 User 가 회원가입하는 부분이 MSA 환경으로 분리된다면 어떻게 대응할 수 있을까? 아마도, 기존의 UserService 를 지워야 하거나 수정하는 현상이 발생할 것이다. 우리가 클린코드 / 클린..

    클린 아키텍쳐와 Domain Layer

    계층형 아키텍쳐 보통의 3 계층 아키텍쳐는 아래와 같다. 이렇게 되면 표현계층에서는 요청을 받아서 서비스 계층으로 넘긴뒤 도메인 로직을 수행하게 된다. 잘 작성한다면 도메인 로직에 영향을 주지않고, 표현 계층과 영속성 계층의 로직만 변경이 가능하다. 하지만 문제점이 생기는데 도메인 로직이 중점이 아닌 데이터베이스를 중점으로 설계하기 쉬워진다. 객체지향에서 기본적으로 협력에 의한 책임 주도 설계가 기본이 되는데 이때 기본적으로 객체가 가질 수 있는 state 에 의존하는 설계가 아니라 객체간의 협력에서 이룰 수 있는 행동을 기반으로 설계를 진행하는 것이 좋다. 이건 조영호님의 오브젝트 책을 보면 잘나와있는데 데이터를 중심으로 설계하게 되면 외부에서는 협력하는 객체에 대한 정보를 너무 많이 알게 된다. 대표..

    협력과 메세지

    앞선 포스팅들에서 책임에 관련된 이야기를 계속해서 해왔다. 객체지향에는 또 설명해야할 중요한 개념이 존재하는데 "협력" 과 "메세지" 이다. 이미 앞선 포스팅에서 지겹게 설명했다고 생각할 수도 있지만 이제는 이해를 하기 위해서 현실세계로 잠깐 저 내용을 끌고 와볼까 한다. 이 포스팅은 대부분의 내용이 조영호님의 "오브젝트" 를 읽고 느낀점을 생각으로 정리한 글입니다. 본문 제일 아래에 책 링크가 달려있습니다. 협력과 메시지 개인적으로 이 둘은 떼놓고 설명하기가 힘들다고 생각한다. 과연 이 추상적인 개념은 객체지향 세계에서 어떻게 설명할 수 있을까? 가장 쉽게 설명할 수 있는건 Client - Server Model 로 설명하는 것이다. Client 는 Server 에 Request(요청) 을 보내고 Se..

    응집도와 결합도

    응집도와 결합도는 소프트웨어 품질을 결정 짓는 요소이다. 대다수의 사람들은 코드를 작성할때 "응집도" 와 "결합도" 를 생각하지 않은채 관성적으로 코드를 적고는 한다. 응집도와 결합도는 무슨 뜻일까? 일단, 이 개념을 이해하기 위해서 알고 있어야 할 선행지식이 있다. 불안정한 부분과 안전한 부분의 분리 바로 "불안정한 부분" 과 "더 안전한 부분" 을 분리해 내는 능력이 필요하다. 예를 들어 아래와 같은 객체가 존재한다고 해보자. Address 는 모든 변수가 public 하게 열려있다. 우리는 앞으로 Public 하다는건 자신의 내부 속사정을 공개한 객체 취급을 할 것이다. 외부에서 이를 어떻게 사용할까? 위와 같이 사용할 수 있을 것이다. 위와 같이 사용했을때 어떤 문제가 발생할 수 있을까? 아니 "..

    컴포넌트

    컴포넌트는 배포 단위다. 자바의 경우 .jar 파일이 컴포넌트가 되고, 루비의 경우 gem 파일이 컴포넌트가 된다. 개발 초창기에는 프로그래머가 메모리에서 프로그램이 어느 곳에 위치할지 정의해야 했다. 아래의 코드를 간단하게 보자. *200 TLS START, CLA TAD BUFR 위에서 설명한대로 예전에는 프로그래머가 메모리에 어느 곳에 위치할지 적어줘야 하므로 Origin 이 필요했다. 프로그램 시작부의 *200 을 주목해보자. 과연 어떤 의미일까? 이는 메모리 주소 200에 로드할 코드를 생성하라고 알려주는 것이다. 내 단순한 추측인데 메모리의 코드영역이 이 영역이 아닐까? 라는 생각이 들게 되었다. 여하튼 현재 우리는 이런 고민을 할 필요가 없었지만, 그 당시에는 아주 큰 고민이였다. 왜냐하면 ..

    SOLID

    좋은 소프트웨어는 Clean-Code 로 부터 시작한다. 좋은 재료를 사용하지 않으면 건물의 아키텍쳐가 좋고 나쁨에 의미가 없다. 반대로 좋은 재료를 사용하더라도 아키텍쳐가 엉망이라면 나쁜 품질의 소프트웨어가 될 수 있다. 그래서 프로그래밍 세상에는 좋은 아키텍쳐를 정의하는 원칙이 필요한데 그것이 SOLID 원칙이다. SOLID 원칙의 목적 SOLID 원칙은 아래와 같은 목적을 지니고 있다. - 변경에 유연하다. - 이해하기 쉽다. - 많은 소프트웨어 시스템에 사용될 수 있는 컴포넌트의 기반이 된다. SOLID 종류 SRP: 단일 책임 원칙(Single Responsibility Principle) 소프트웨어 시스템이 가질 수 있는 최적의 구조는 시스템을 만드는 조직의 사회적 구조에 커다란 영향을 받는다..