diff --git a/_posts/2023-05-03-Cursor-Paging.md b/_posts/2023-05-03-Cursor-Paging.md index 1e4fd8f..df5a41c 100644 --- a/_posts/2023-05-03-Cursor-Paging.md +++ b/_posts/2023-05-03-Cursor-Paging.md @@ -108,7 +108,7 @@ public Page findByCustom_cursorPaging(Pageable pageable, String sorting, L 데이터 삽입 시 중복키 제약 조건에 위배되면 ON DUPLICATE KEY UPDATE 구문에 지정한 내용이 실행된다. (즉, 중복된 키 값을 바탕으로 뭔가 삽입을 시도하면 삽입이 아닌 업데이트를 해주는 것) -![img_1.png](img_1.png) +![img_1.png](../images/flexible-architecture/msa1.png) 근데 사실 JPA를 사용할 땐 필요없다. 영속성 컨텍스트와 더티체킹이 있기 때문 diff --git a/_posts/2023-12-29-GoingToFlexibleArchitecture.md b/_posts/2023-12-29-GoingToFlexibleArchitecture.md new file mode 100644 index 0000000..daba1a6 --- /dev/null +++ b/_posts/2023-12-29-GoingToFlexibleArchitecture.md @@ -0,0 +1,215 @@ +--- + +title: 유연한 시스템을 위해 알아야할 내용들 +date: 2023-12-29 +categories: [MicroService] +tags: [MicroService] +layout: post +toc: true +math: true +mermaid: true + +--- + +# 참고 자료 + +[참고 자료](https://www.youtube.com/watch?v=3pybGLmTREw&list=PLwouWTPuIjUgr29uSrSkVo8PRmem6HRDE&index=12) + +--- + +# 유연한 시스템이 왜 필요한 것인가? + +사용자가 많아지게 되면 서비스를 제공할 수 있는 가용 서버를 늘려 트래픽에 대응할 수 있어야한다. + +하지만 어떤 조직이던간에 우리가 사용할 수 있는 자원은 필연적으로 한정되어있다. 따라서 자원을 효율적으로 사용하여 가용할 수 있는 서버를 늘리는 것이 우아하게 사용자의 요구를 처리할 수 있는 방법이다. + +그래서 등장한 개념이 `마이크로서비스 아키텍처`이다. 기존 모놀리틱 서버는 배정받은 역할이 너무나도 크기 때문에 기동시키기에는 사용하는 자원에 부담이 크다. + +또한 확장을 고려할 필요없는 내용을 포함해서도 확장되기 때문에 자원을 효율적으로 사용하지 못하게 된다. + +이 내용을 그림으로 표현할 수 있는데 아래와 같다. + +![img.png](https://github.com/K-Diger/K-Diger.github.io/blob/main/images/flexible-architecture/mono.png?raw=true) + +현재 어떤 이벤트로 인해서 결제에 대한 API 요청이 폭증했다고 가정해보자 + +모놀리틱의 구성이라면 한 대의 서버로 감당이 안되기 때문에 기존 서버와 똑같은 내용을 가진 서버를 가져와 기동시켜야한다. 저 많은 API를 처리하기 위한 모놀리틱 서버의 스펙 비용은 약 1000만원이라고 해보자 + +마이크로서비스의 개념을 적용하면 어떻게 될까? 결제에 대한 API 요청이 폭증했으니 결제를 담당하는 마이크로서버만 확장하면 되지 않을까? + +그림으로 표현하면 아래와 같다. + +![img_1.png](https://github.com/K-Diger/K-Diger.github.io/blob/main/images/flexible-architecture/msa1.png?raw=true) + +마이크로 서버의 스펙 비용은 각각 약 250만원이라고 하자 + +마이크로서비스로 시스템을 초기부터 운영하려면 초기 비용은 많이 들 수 있다. 또한 이를 유지보수하는 인적/기술적인 비용도 만만치않긴하다. + +하지만 지금 상황에서 결제 API에 대한 서버를 늘릴 때는 2대를 추가로 늘려도 모놀리틱의 절반 가격인 500만원으로 요청을 더 원활하게 받아낼 수 있게 된다. + +비용이 구체적이고 현실적인 예시는 아닐 수 있지만 이렇게 자원을 늘리고 줄이는 아키텍처가 한정된 자원을 효율적으로 쓰이는 것에 장점이 있다고 판단하여 많은 서비스들이 적용하고 있다. + +--- + +# 마이크로서비스 핵심 개념 6가지 + +## 1. 독립적으로 배포할 수 있어야한다. + +약 6가지 핵심 개념 중 가장 중요한 개념이다. 이 외의 개념이 이 개념을 충족시키기위해서 존재한다고 볼 수 있을 정도이다. + +**다른 마이크로서비스를 배포하지 않고 마이크로서비스를 배포/변경할 수 있어야한다.** + +이 개념을 충족시키기 위해 마이크로서비스간 결합도/의존도를 낮춰야한다. 서비스간에 잘 정의되고 안정된 명세가 필요하다. + +--- + +## 2. 비즈니스 도메인을 중심으로 모델링 해야한다. + +**도메인을 기준으로하여 서비스 경계를 정의해야한다.** + +- 즉, 한 마이크로서비스가 기능에 필요한 전체를 구현해야한다는 것이다. +- 이렇게 하면 새 기능 출시가 쉬워지고 다른 방식으로 마이크로서비스를 재조합하기 유용해진다. + +한 기능의 구현이 여러 마이크로서비스에 걸쳐있으면 기능 출시 시 비용이 올라간다. + +- 예를 들어 글쓰기 기능을 새로 만든다고 했을 때, 약 10개의 마이크로서비스와 상호작용을 해야한다고 가정해보자 + - 그렇다면 10개의 마이크로서비스와 통신하는 내용을 작성하게 된다. + - 각 마이크로서비스를 담당하는 팀과의 커뮤니케이션, 서비스 통신 순서 관리, 예외처리에 대한 내용 등 구현 비용이 크게 늘어나게 된다. + +따라서 여러 서비스에 걸친 변경을 최소화해야한다. + +--- + +## 3. 자신의 상태를 가져야한다. + +**마이크로서비스는 DB 혹은 데이터를 공유하지 않아야한다.** + +- 다른 마이크로서비스가 갖고 있는 데이터에 접근해야 하면 DB에 직접 접근하지 않고 API등을 통해서 접근해야한다. + - 데이터를 공유하지 않는다 --> 구현을 숨긴다 --> 결합도를 낮춘다. + +--- + +## 4. 마이크로서비스를 다룰 수 있는 역량을 고려해야한다. + +마이크로서비스를 설계할 때 주의할 점으로 아래와 같은 말이 있다고한다. + +```text +내 머리가 이해할 수 있을 정도의 크기를 가져야한다. (James Lewis) +``` + +하지만 위의 주의점은 상황에 따라 다를 수 밖에 없다. + +--> 오랫동안 해당 서비스에 몸을 담은 사람 vs 신규 입시자 + +--> 스타트업 vs 대기업 + +이렇게 마이크로서비스를 다루는 대상마다 적용되는 범위가 달라질 수 밖에 없다. + +따라서 **마이크로서비스의 크기라는 용어보다는** 다음 두 가지의 구체화에 대한 내용에 집중하는 것이 좋다. + +- 얼마나 많은 마이크로서비스를 다룰 수 있는가? + - 마이크로서비스가 증가하면 복잡도가 증가하며 새 기술을 습득해야하는 가능성이 크다. + +- 마이크로서비스 경계를 정의해야한다. + - 실타래가 복잡하게 얽히지 않도록 해야한다. + +--- + +## 5. 마이크로서비스는 유연해야한다. + +지금 더 비용을 들여 미래에 유연해질 수 있는 옵션을 구매해야한다. (여기서 옵션이란 하드웨어 스펙이 아닌 기술과 확장 가능성인 인적/기술적 비용을 가리킨다.) + +아직 벌어지지 않은 미래에 너무 많은 옵션을 구매하는 것은 오버 엔지니어링이 될 가능성이 크다. + +**따라서 점진적으로 마이크로서비스로 전환해야하며 이 과정에서도 과하지 않게 설계해야한다.** + +--- + +## 6. 아키텍처와 조직을 맞춰야한다. + +**조직 간 이관이나 사일로(부서 이기주의 현상)를 줄여야한다.** + +아키텍처의 구조는 조직의 구조를 따르게 되어있다. (조직도 생태계를 반영할 수 밖에 없음) + +기존 `프론트 팀, 백엔드 팀, DB 팀`과 같이 조직을 큰 단위로 구성했다면 `고객 팀, 구매 팀`등으로 세분화하여 여러 포지션을 한 조직에 모아 줄이는 것이 적절하다. + +이렇게하면 각 담당한 도메인에 대한 응집도를 높일 수 있어 비즈니스 도메인에 집중할 수 있는 장점이 있다. + +--- + +# 비즈니스 도메인을 중심으로 모델링 하기 + +[참고자료](https://www.youtube.com/watch?v=xf0kXMTFJm8&list=PLwouWTPuIjUgr29uSrSkVo8PRmem6HRDE&index=5) + +## 왜 도메인을 중심으로 모델링을 해야하는가? + +위에서 살펴본 마이크로서비스 핵심 개념 2번을 다시 떠올려보자 + +```text +**도메인을 기준으로하여 서비스 경계를 정의해야한다.** + +- 즉, 한 마이크로서비스가 기능에 필요한 전체를 구현해야한다는 것이다. +- 이렇게 하면 새 기능 출시가 쉬워지고 다른 방식으로 마이크로서비스를 재조합하기 유용해진다. + +한 기능의 구현이 여러 마이크로서비스에 걸쳐있으면 기능 출시 시 비용이 올라간다. + +- 예를 들어 글쓰기 기능을 새로 만든다고 했을 때, 약 10개의 마이크로서비스와 상호작용을 해야한다고 가정해보자 + - 그렇다면 10개의 마이크로서비스와 통신하는 내용을 작성하게 된다. + - 각 마이크로서비스를 담당하는 팀과의 커뮤니케이션, 서비스 통신 순서 관리, 예외처리에 대한 내용 등 구현 비용이 크게 늘어나게 된다. + +따라서 여러 서비스에 걸친 변경을 최소화해야한다. +``` + +도메인을 기준으로 설계를 한다면 유연한 시스템을 구축할 수 있다는 점이 있다고 했다. + +그렇다면 도메인을 중심으로 설계하는 방법을 알아보는게 좋겠다. + +## 1. CQRS 패턴 + +Command(Create, Update, Delete)와 Query(Read)를 분리하는 것이 도메인 중심 설계의 기초가 될 수도 있다. + +- Command는 시스템의 데이터를 변경하는 행위를 가리킨다. + - 주문 취소, 배송 완료 등 +- Query는 시스템의 데이터를 조회하는 행위를 가리킨다. + - 주문 목록 조회 등 + +CQRS는 `Responsibility Segregation (책임 분리)`라는 중요 개념에 의해 탄생했다. + +- **책임은 구성 요소의 역할을 의미한다.** + - 구성 요소(모델)는 아래 요소들을 가리킨다. + - 클래스, 함수, 모듈, 패키지, 웹서버, DB 등 + +이 요소들을 적절하게 분리하는 것이 권장된다. + +- Command 역할을 수행하는 구성요소 +- Query 역할을 수행하는 구성 요소를 나누는 것이 CQRS이다. + +코드만 나누는 것이 아니라 구현 방법, DB, 프로세스를 나누기도 한다. 중요한 점은 변경하는 구성요소, 조회하는 구성요소를 나누는 것이다. + +![img.png](https://github.com/K-Diger/K-Diger.github.io/blob/main/images/flexible-architecture/CQRS1.png?raw=true) + +위와 같이 표현할 수 있겠다. 그런데 이 방식이 굳이 필요한 이유가 무엇일까? + +`Command`에서 사용되는 `Member`와 `Query`에 사용되는 `MemberData`는 무슨 차이가 있을까? + +### 단일 책임 원칙 위반 + +![img.png](https://github.com/K-Diger/K-Diger.github.io/blob/main/images/flexible-architecture/CQRS2.png?raw=true) + +위 그림처럼 `마지막 로그인에 대한 기록`, `최근 주문 일자에 대한 기록`, `회원 이름 변경 기능 추가`가 추가되었다고 했을 때 유저 테이블에서 이 모든 내용을 담도록 했다. + +적절하게 속성을 부여한 것처럼 볼 수도 있지만 유저에 부여된 역할/책임이 모호해졌다. 즉, 유저 객체가 하는 일이 너무 많다는 것이다. + +이렇게 하나의 객체에 너무 많은 역할과 책임을 부여하면 유지보수성이 상당히 떨어지게 된다. + +기능에 따라 사용되는 필드가 달라진다. + +이름 변경 기능은 Member 테이블에 해당하는 내용만 참조하면 되지만 + +주문 목록 조회 기능을 구현하기 위해서 Member, LoginHistory, Order 총 세 가지의 테이블을 참조해야한다. + + + +--- + +## 2. 도메인 중심 설계 (DDD) diff --git a/images/flexible-architecture/CQRS1.png b/images/flexible-architecture/CQRS1.png new file mode 100644 index 0000000..d8c73bb Binary files /dev/null and b/images/flexible-architecture/CQRS1.png differ diff --git a/images/flexible-architecture/CQRS2.png b/images/flexible-architecture/CQRS2.png new file mode 100644 index 0000000..9c9f0c8 Binary files /dev/null and b/images/flexible-architecture/CQRS2.png differ diff --git a/images/flexible-architecture/mono.png b/images/flexible-architecture/mono.png new file mode 100644 index 0000000..74870f2 Binary files /dev/null and b/images/flexible-architecture/mono.png differ diff --git a/images/flexible-architecture/msa1.png b/images/flexible-architecture/msa1.png new file mode 100644 index 0000000..f00a152 Binary files /dev/null and b/images/flexible-architecture/msa1.png differ