Skip to content

Commit

Permalink
feat: Add chapter30 ~ chapter34
Browse files Browse the repository at this point in the history
  • Loading branch information
bossm0n5t3r committed May 17, 2024
1 parent ac7b3eb commit 086ef8c
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 3 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,8 @@
- [27장. ‘크고 작은 모든’ 서비스들](./chapter27/)
- [28장. 테스트 경계](./chapter28/)
- [29장. 클린 임베디드 아키텍처](./chapter29/)
- [30장. 데이터베이스는 세부사항이다](./chapter30/)
- [31장. 웹은 세부사항이다](./chapter31/)
- [32장. 프레임워크는 세부사항이다](./chapter32/)
- [33장. 사례 연구: 비디오 판매](./chapter33/)
- [34장. 빠져 있는 장](./chapter34/)
3 changes: 2 additions & 1 deletion chapter30/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# 30장. 데이터베이스는 세부사항이다

- [yumin](./yumin/)
- [yumin](./yumin/)
- [zhoon](./zhoon/)
87 changes: 87 additions & 0 deletions chapter30/zhoon/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# 30장. 데이터베이스는 세부사항이다

## Introduction

- 아키텍처 관점에서 볼 때 데이터베이스는 엔티티가 아님
- 즉, 데이터베이스는 세부사항이라서 아키텍처의 구성요소 수준으로 끌어올릴 수 없음
- 명확히 짚고 가자면, 지금 데이터 모델을 말하는 건 아님
- 애플리케이션 내부 데이터의 구조는 시스템 아키텍처에서 대단히 중요함
- **하지만 데이터베이스는 데이터 모델이 아님**
- 데이터베이스는 일개 소프트웨어일 뿐
- 데이터베이스는 데이터에 접근할 방법을 제공하는 유틸리티
- 아키텍처 관점
- 이러한 유틸리티는 저수준의 세부사항 (메커니즘) 일 뿐, 아키텍처와는 관련이 없음
- 그리고 뛰어난 아키텍처라면 저수준의 메커니즘이 시스템 아키텍처를 오염시키는 일을 용납하지 않음

## 관계형 데이터베이스

- 에드거 커드는 1970년에 관계형 데이터베이스의 원칙을 정의함
- 관계형 모델은 계속 성장하여 1980년대 중반이 되자 데이터 저장소의 지배적인 형태가 됨
- 이 모델은 우아했고, 절제되었으며, 강건했음
- 관계형 데이터베이스는 데이터를 저장하고 접근하는 데 탁월한 기술이었음
- 하지만 관계형 데이터베이스의 기술이 어떻든 결국은 그저 기술일 뿐
- 그리고 이는 관계형 데이터베이스가 세부사항임을 뜻함
- 관계형 테이블은 특정한 형식의 데이터에 접근하는 경우에는 편리하지만, **데이터를 행 단위로 배치한다는 자체는 아키텍처적으로 볼 때 전혀 중요하지 않음**
- 데이터가 테이블 구조를 가진다는 사실은 오직 아키텍처의 외부 원에 위치한 최하위 수준의 유틸리티 함수만 알아야 함
- 많은 데이터 접근 프레임워크가 테이블과 행이 객체 형태로 시스템 여기 저기에서 돌아다니게 허용하는데, 아키텍처적으로 잘못된 설계

## 데이터베이스 시스템은 왜 이렇게 널리 사용되는가?

- 어떻게 데이터베이스 시스템이 소프트웨어 시스템과 소프트웨어 기업을 장악할 수 있었을까?
- 한마디로 답하자면, 바로 ‘디스크’ 때문
- 디스크가 반세기동안 회전식 자기 디스크부터 엄청나게 발전할 동안, 프로그래머는 디스크 기술이 가진 치명적인 한 가지 특성으로 인해 괴롭힘을 당함, 바로 **느리다는 특성**
- 디스크 때문에 피해갈 수 없는 시간 지연이라는 짐을 완화하기 위해, 색인, 캐시, 쿼리 계획 최적화가 필요해짐
- 그리고 데이터를 표현하는 일종의 표준적인 방식도 필요했는데, 이러한 색인, 캐시, 쿼리 계획에서 작업중인 대상이 어떤 데이터인지 알 수 있어야 했기 때문
- **간단히 말해서 데이터 접근 및 관리 시스템이 필요**
- 시간이 지나면서 이러한 시스템은 뚜렷이 구분되는 두 가지 유형으로 구분됨
- 파일 시스템
- 관계형 데이터베이스 관리 시스템, RDBMS
- 파일 시스템
- 문서 기반, document
- 문서 자체를 자연스럽고 편리하게 저장하는 방법을 제공
- 일련의 문서를 이름을 기준으로 저장하거나 조회할 때는 잘 동작하지만, 내용을 기준으로 검색할 때는 그리 크게 도움되지 않음
- 관계형 데이터베이스 관리 시스템, RDBMS
- 내용 기반
- 내용을 기반으로 레코드를 자연스럽고 편리하게 찾는 방법을 제공함
- 레코드가 서로 공유하는 일부 내용에 기반해서 다수의 레코드를 연관 짓는 데 매우 탁월
- 하지만 안타깝게도 정형화되지 않은 문서를 저장하고 검색하는 데는 대체로 부적합
- 두 시스템 모두 데이터를 빠르게 조작할 수 있도록 결국에는 관련 있는 데이터를 RAM 으로 가져옴

## 디스크가 없다면 어떻게 될까?

- 디스크는 현재 소멸 중인 부품
- 디스크는 RAM 으로 대체되고 있음
- 디스크가 모두 사라진다면, 그래서 모든 데이터가 RAM에 저장된다면 데이터를 어떻게 체계화할 것인가?
- 데이터를 테이블 구조로 만들어 SQL을 이용해 접근할 것인가?
- 파일 구조로 만들어 디렉터리를 통해 접근할 것인가?
- 당연히 아니다
- 이 데이터들을 연결 리스트, 트리, 해시 테이블, 스택, 큐 혹은 여타 무수히 많은 데이터 구조로 체계화할 것이며, 데이터에 접근할 때는 포인터나 참조를 사용할 것
- 이것이 프로그래머가 하는 일이기 때문
- 사실 이미 그렇게 하고 있음

## 세부사항

- 데이터베이스가 세부사항이라고 말하는 이유는 바로 이러한 현실 때문
- 데이터베이스는 그저 메커니즘에 불과함
- 따라서 아키텍처 관점에서 본다면, 데이터가 어떤 형태인지는 절대로 신경 써서는 안 됨
- 정말로 우리는 디스크 자체가 존재한다는 사실조차도 인식해서는 안 됨

## 하지만 성능은?

- 성능은 당연히 아키텍처적인 관심사
- 하지만 데이터 저장소의 측면에서 성능은 완전히 캡슐화하여 업무 규칙과는 분리할 수 있는 관심사임
- 데이터 저장소에서 데이터를 빠르게 넣고 뺄 수 있어야 하는 것은 맞지만, 이는 저수준의 관심사
- 이 관심사는 저수준의 데이터 접근 메커니즘 단에서 다룰 수 있음
- 성능은 시스템의 전반적인 아키텍처와는 아무련 관련이 없음

## 개인적인 일화

- RDBMS 도입과 관련해서 싸움
- 저자는 반대함
- 공학적인 부분에서는 저자가 옳았다고 말함
- 하지만 현실은 다름

## 결론

- 데이터는 중요
- 데이터베이스는 세부사항
3 changes: 2 additions & 1 deletion chapter31/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# 31장. 웹은 세부사항이다

- [yumin](./yumin/)
- [yumin](./yumin/)
- [zhoon](./zhoon/)
28 changes: 28 additions & 0 deletions chapter31/zhoon/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 31장. 웹은 세부사항이다

## Introduction

- 웹은 바꾼 것이 아무것도 없었고, 적어도 웹은 그렇게 해서는 안됐었음
- 우리 업계는 일련의 반복되는 진동을 겪어왔고, 웹은 그저 이러한 진동의 맨 끝에 있을 뿐
- **이 진동은 모든 연산 능력을 중앙 서버에 두는 방식과 모든 연산 능력을 단말에 두는 방식 사이에서 끊임없이 움직여 왔음**

## 끝없이 반복하는 추

- 이 진동이 웹으로부터 시작되었다고 보는 일은 옳지 않음
- 웹이 있기 전에는 클라이언트-서버 아키텍처가 있었음
- 이 이야기는 계속 될 것이고, 앞으로도 우리는 연산 능력을 어디에 둘지 알 수 없을 것
- 연산 능력을 중앙에 집중하는 방식과 분산하는 방식 사이에서 우리는 끊임없이 움직임
- 그리고 저자 생각에 이러한 진동은 한동안 계속될 것
- 나도 마찬가지
- 아키텍트로서 우리는 멀리 내다봐야 함
- 이 진동은 그저 핵심 업무 규칙의 중심에서 밀어내고 싶은 단기적인 문제일 뿐

## 요약

- GUI 는 세부사항, 웹은 GUI, 따러서 웹은 세부사항
- 아키텍터라면 이러한 세부사항을 핵심 업무 로직에서 분리된 경계 바깥에 두어야 함

## 결론

- 이러한 종류의 추상화는 만들기 쉽지 않고, 제대로 만들려면 수차례의 반복 과정을 거쳐야 할 것
- 하지만 가능함
3 changes: 2 additions & 1 deletion chapter32/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# 32장. 프레임워크는 세부사항이다

- [yumin](./yumin/)
- [yumin](./yumin/)
- [zhoon](./zhoon/)
57 changes: 57 additions & 0 deletions chapter32/zhoon/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# 32장. 프레임워크는 세부사항이다

## Introduction

- 프레임워크는 상당히 인기를 끌고 있음
- 일반적으로 말하자면 좋은 현상
- 무료인 데다 강력하며 유용한 프레임워크가 많음
- **하지만 아무리 해도 프레임워크는 아키텍처가 될 수 없음**

## 프레임워크 제작자

- 프레임워크 제작자는 우리를 알지 못하며, 우리가 풀어야 할 문제도 알지 못함
- 프레임워크 제작자는 본인의 문제, 혹은 동료와 친구들의 문제를 해결하기 위해 만들 뿐이며, 이 문제가 많이 겹칠 수록 인기를 끌 것
- 겹치는 영역이 크면 클수록 프레임워크는 실제로 더 유용해짐

## 혼인 관계의 비대칭성

- 우리와 프레임워크 제작자 사이의 관계는 놀라울 정도로 비대칭적
- 우리는 프레임워크를 위해 대단히 큰 헌신을 해야 하지만, 프레임워크 제작자는 우리를 위해 아무런 헌신도 하지 않음
- 프레임워크 제작자는 프레임워크에 대해 장기간에 걸친 막대한 헌신을 요청하지만, 어떠한 경우에도 그에 상응하는 헌신을 해주지는 않음
- 이 혼인 관계는 일방적
- 모든 위험과 부담은 오롯이 당신이 감수할 뿐, 제작자가 감수하는 건 아무 것도 없음

## 위험 요인

- 프레임워크의 아키텍처는 그다지 깔끔하지 않은 경우가 많음
- 프레임워크는 의존성 규칙을 위반하는 경향이 있음
- 프레임워크는 애플리케이션 추기 기능을 만드는 데는 도움이 될 것
- 하지만 제품이 성숙해지면서 프레임워크가 제공하는 기능과 틀을 벗어나게 될 것
- 프레임워크는 우리에게 도움이 되지 않는 방향으로 진화할 수도 있음
- 도움이 되지 않는 신규 버전으로 업그레이드하느라 다른 일을 못할 수도 있음
- 심지어 사용 중이던 기능이 사라지거나 반영하기 힘든 형태로 변경될 수도 있음
- 새롭고 더 나은 프레임워크가 등장해서 갈아타고 싶을 수도 있음

## 해결책

> 프레임워크와 결혼하지 말라!
- 프레임워크를 사용할 수는 있지만, 결합해서는 안 됨
- 프록시를 만들고, 업무 규칙에 플러그인할 수 있는 컴포넌트에 이들 프록시를 위치시켜라
- 프레임워크가 핵심 코드 안으로 들어오지 못하게 하라
- 스프링의 경우
- 업무 객체는 절대로 스프링에 대해 알아서는 안됨
- 업무 객체보다는 메인 컴포넌트에서 스프링을 사용해서 의존성을 주입하는 편이 나음
- 메인은 아키텍처 내에서 가장 지저분한, 최저 수준의 컴포넌트이기 때문에 스프링을 알아도 상관 없음

## 이제 선언합니다

- 정말로 결혼해야만 하는 프레임워크도 존재
- C++ <-> STL
- 자바 <-> 표준 라이브러리
- 이러한 관계는 정상, 하지만 선택적이어야 함
- 프레임워크와 결혼은 결코 가볍게 시작할 수 있는 관계가 아님

## 결론

- 프레임워크와의 첫 만남부터 바로 결혼하려 들지 말라
3 changes: 3 additions & 0 deletions chapter33/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 33장. 사례 연구: 비디오 판매

- [zhoon](./zhoon/)
16 changes: 16 additions & 0 deletions chapter33/zhoon/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 33장. 사례 연구: 비디오 판매

## Introduction

- 이 챕터는 따로 요약을 하지 않겠다.
- 책을 다시 살펴보자.

## 제품

## 유스케이스 분석

## 컴포넌트 아키텍처

## 의존성 관리

## 결론
3 changes: 3 additions & 0 deletions chapter34/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 34장. 빠져 있는 장

- [zhoon](./zhoon/)
83 changes: 83 additions & 0 deletions chapter34/zhoon/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 34장. 빠져 있는 장

## Introduction

- 설계나 코드 조직화와 관련된 몇 가지 접근법을 살펴보자

## 계층 기반 패키지

- 가장 단순한 첫 번째 설계 방식은 전통적인 수평 계층형 아키텍처
- 기술적인 관점에서 해당 코드가 하는 일에 기반해 그 코드를 분할함
- 흔히 우리는 이 방식을 ‘계층 기반 패키지’라고 부름
- 이 아키텍처는 엄청난 복잡함을 겪지 않고도 무언가를 작동시켜 주는 아주 빠른 방법
- 소프트웨어가 커지고 복잡해지기 시작하면, 머지 않아 큰 그릇 세 개만으로는 모든 코드를 담기엔 부족하다는 사실을 깨닫고, 더 잘게 모듈화해야 할지를 고민하게 될 것
- 계층형 아키텍처는 업무 도메인에 대해 아무것도 말해주지 않는다는 문제도 있음

## 기능 기반 패키지

- 서로 연관된 기능, 도메인 개념, 또는 Aggregate Root 에 기반하여 수직의 얇은 조각으로 코드를 나누는 방식
- 저자가 본 전형적인 구현에서는 모든 타입이 하나의 자바 패키지에 속하며, 패키지 이름은 그 안에 담긴 개념을 반영해 지음
- 저자는 소프트웨어 개발팀이 수평적 계층화(계층 기반 패키지)의 문제를 깨닫고, 수직적 계층화(기능 기반 패키지)로 전환하는 걸 자주 목격함
- 저자가 보기에 두 접근법은 모두 차선책

## 포트와 어댑터

- “포트와 어댑터 ports and adapters” 혹은 “육각형 아키텍처 hexagonal architecture”, “경계, 컨트롤러, 엔티티 BCE” 등의 방식으로 접근하는 이유는 업무/도메인에 초점을 둔 코드가 프레임워크가 데이터베이스 같은 기술적인 세부 구현과 독립적이며 분리된 아키텍처를 만들기 위해서임
- 그런 코드 베이스는 내부(도메인)와 외부(인프라)로 구성됨을 흔히 볼 수 있음
- 내부 영역
- 도메인 개념을 모두 포함
- 외부 영역
- 외부 세계와의 상호작용을 포함함
- 주요 규칙
- 외부가 내부에 의존하며, 절대 그 반대로는 안된다는 점
- 도메인 주도 설계에서는 내부에 존재하는 모든 것의 이름은 반드시 유비쿼터스 도메인 언어 관점에서 기술하라고 조언함

## 컴포넌트 기반 패키지

- 코드를 조직화하는 방법에 대해 또 다른 선택지
- 지금까지 우리가 본 모든 것들을 혼합한 것
- 큰 단위의 단일 컴포넌트와 관련된 모든 책임을 하나의 자바 패키지로 묶는 데 주안점을 둠
- 이 접근법은 서비스 중심적인 시각으로 소프트웨어 시스템을 바라보며, 마이크로서비스 아키텍처가 가진 시각과도 동일함
- 사용자 인터페이스를 큰 단위의 컴포넌트로부터 분리해서 유지함
- 본질적으로 이 접근법에서는 ‘업무 로직’과 영속성 관련 코드를 하나로 묶는데, 이 묶음을 저자는 ‘컴포넌트’라고 부름
- 컴포넌트에 대한 엉클 밥의 정의
- 컴포넌트는 배포 단위다. 컴포넌트는 시스템의 구성 요소로, 배포할 수 있는 가장 작은 단위다. 자바의 경우 jar 파일이 컴포넌트다.
- 컴포넌트에 대한 저자의 정의
- 컴포넌트는 멋지고 깔끔한 인터페이스로 감싸진 연관된 기능들의 묶음으로, 애플리케이션과 같은 실행 환경 내부에 존재한다.
- 이 방법론에서 소프트웨어 시스템은 하나 이상의 컨테이너로 구성되며, 각 컨테이너는 하나 이상의 컴포넌트를 포함함
- 또한 각 컴포넌트는 하나 이상의 클래스 (또는 코드) 로 구현됨
- 이때 각 컴포넌트가 개별 jar 파일로 분리될지 여부는 직교적인 관심사 orthogonal concern
- 컴퍼넌트 기반 패키지 접근법의 주된 이점
- 도메인과 관련된 무언가를 코딩할 때 오직 한 곳, 컴포넌트만 둘러보면 된다는 점
- 이 컴포넌트 내부에서 관심사의 분리는 여전히 유효하며, 따라서 업무 로직은 데이터 영속성과 분리되어 있음
- 하지만 이는 컴포넌트 구현과 관련된 세부사항으로, 사용자는 알 필요가 없음
- 이는 마이크로서비스나 서비스 지향 아키텍처를 적용했을 때 얻는 이점과도 유사함

## 구현 세부사항엔 항상 문제가 있다

## 조직화 vs. 캡슐화

- 계층 기반 패키지, 기능 기반 패키지, 포트와 어댑터, 컴포넌트 기반 패키지 각각의 접근법에서 다이어그램이 인상적으로 변함

## 다른 결합 분리 모드

- 프로그래밍 언어가 제공하는 방법 외에도 소스 코드 의존성을 분리하는 방법이 존재할 수 있음
- 다른 선택지로는 소스 코드 수준에서 의존성을 분리하는 방법도 있음
- 정확하게는 서로 다른 소스 코드 트리로 분리하는 방법
- 소스 코드 트리로 분리하는 방법은 빌드 도구를 사용해서 모듈이나 프로젝트가 서로 분리되도록 구성해야 함
- 이는 너무 이상적인 해결책
- 포트와 어댑터 접근법을 적용할 때는 이보다 더 간단한 방법을 사용하기도 함
- 단순히 소스 코드 트리를 두 개만 만드는 것
- 도메인 코드 (내부)
- 인프라 코드 (외부)
- 이 방법은 잠재적으로 절충해야 할 부분이 있음을 알고 있어야만 함
- 저자는 이를 “포트와 어댑터에 대한 페리페리크 안티 패턴” 이라 부름

## 결론: 빠져 있는 조언

- 이 장은 최적의 설계를 꾀했더라도, 구현 전략에 얽힌 복잡함을 고려하지 않았으면 설계가 순식간에 망가질 수 있다는 사실을 강조하는 데 그 목적이 있음
- 설계를 어떻게 해야만 원하는 코드 구조로 매핑할 수 있을지, 그 코드를 어떻게 조직화할지, 런타임과 컴파일타임에 어떤 결합 분리 모드를 적용할지를 고민하라
- 가능하다면 선택사항을 열어두되, 실용주의적으로 행하라
- 그리고 팀의 규모, 기술 수준, 해결책의 복잡성을 일정과 예산이라는 제약과 동시에 고려하라
- 또한 선택된 아키텍처 스타일을 강제하는 데 컴파일러의 도움을 받을 수 있을지를 고민하며, 데이터 모델과 같은 다른 영역에 결합되지 않도록 주의하라
- 구현 세부사항에는 항상 문제가 있는 법이다

0 comments on commit 086ef8c

Please sign in to comment.