핵심 사상은 기능 분해
잘게 쪼개보자?
여러 서비스로 구성하자!
어느정도 크기로 분해해야 될까..
소프트웨어 아키텍처가 뭔지부터...
아키텍처가 중요한 이유는 ~~ 성으로 끝나는 지표가 아키텍처에 의해 결졍됨
확장성, 신뢰성 보안... 이제는 신속 안전 소프트웨어 전달
어렵다 어려워!
소프트웨어 아키텍처란 소프트웨어의 뼈대!
큰 건물을 지을때 설계도 역할
정의: 소프트웨어 아키텍처는 시스템의 구성요소(엘리먼트)
이들 사이의 관계 그리고 특성을 포함하는 전체적인구조
핵심은 어플리케이션 여러 파트(엘리먼트) 분해
이러한 파트 간의 관계(연관성)
객체지향 개념이랑 비슷한건가?
업무 분담: 큰 프로젝트 여러팀이 분할해서 맡음
전문성 활용: 각 부분 전문가 배치 효율 높임
상호작용 이해: 각 시스템 부분이 어떻게 연결되고 동작 파악
소프트웨어 시스템을 4가지 다른 관점에서 봄
+1은 이 모든 뷰를 종합해서 보는 시나리오 관점
마치 집을 볼대 구조 전기 배관등 여러 측면을 보는 것과 비슷
뷰 모델은 애플리케이션 아키텍처를 명쾌하게 표현하는 수단 4뷰는 중요한 아키텍처 측면을, 시나리오는 뷰의 여러 엘리먼트가 협동하는 과정을 명시
4+1 뷰 모델은 애플리케이션 아키텍처를 명쾌하게 표현하는 수단?
보기쉽게 표현한다는건가.
개발자가 직접 작성한 코드를 보는 관점 (클래스 , 함수 ,객체 해당)
코드가 어떻게 패키지나 모듈로 묶이는지 보는 관점 (자바의 jar)
프로그램이 실제로 실행될 때 어떤 프로세스들이 동작하는지 보는 관점
프로그램이 어떤 컴퓨터나 서버에서 실행되는지
그리고 이들이 어떻게 연결되는지 보는 관점 .
IPC는 컴퓨터 내에서 실행되는 서로 다른 프로세스들이 데이터를 주고받는 방법
대규모 소프트웨어 시스템은 종종 여러 개의 독립적인 프로세스로 구성
이 프로세스들은 서로 정보교환 작업 조율 해야됨
파이프
소켓
공유메모리
메시지큐
세마포어
프로세스 뷰에서 ipc는 프로세스들이 어떻게 상호작용하는지 보여 줌
시스템의 전체적인 구조와 동작 방식 이해하는데 중요
프로그램이 어떻게 해야하는가
ex) 시스템은 초당 1000명의 사용자 처리해야됨 (확장성)
개발자가 쉽게 새로운 기능 추가해야됨(관리성)
여기서 아키텍처의 중요성은 주로 2번 즉 비기능적 요구사항 만족시키는데 있다.
아키텍처 스타일이란?
소프트웨어 설계하는 레시피 같은 것
각 스타일은 소프트웨어의 구성 요소와 이들 사이 관계 정리
마치 건축에서 빅토리안 스타일, 모던 스타일이 있는 것처럼, 소프트웨어에도 여러 스타일이 있음
예시 : 모놀리식 : 모든 기능이 하나의 큰 프로그램에 담겨있는 스타일
마이크로서비스 : 기능들이 작은 독립적인 서비스로 나뉘어진 스타일
소프트웨어를 여러 층 나눔
각 층 특정 역할
보통 위층은 아래층 의존
표현계층 : 사용자와 직접 상호작용 부분
비즈니스로직계층 : 실제 작업 처리
데이터 계층 : 데이터 저장 및 가져오는부분
여러 종류의 사용자 시스템 고려 x
(표현 계층이 하나뿐이다: 애플리케이션을 호출하는 시스템이 하나밖에 없을까?)
여러 데이터베이스 사용 고려 X
(영속화 계층이 하나뿐이다: 애플리케이션이 상호 작용하는 DB가 정말 하나뿐일까?)
비즈니스 로직이 데이터 계층에 의존함.
(이론적으로 이런 디펜던시 때문에 DB 없이 비즈니스 로직을 테스트하는 것은 불가능합니다.)
레이어드 계층의 문제점을 해소하기 위해 등장
비즈니스 로직에 중심 두는 설계
외부 상호작용은 어댑터라는 요소로 처리
비즈니스 로직은 외부요소에 의존 X
비즈니스 로직: 핵심 기능을 담당합니다.
포트: 비즈니스 로직과 외부 세계를 연결하는 인터페이스입니다.
인바운드 어댑터: 외부 요청을 받아 비즈니스 로직으로 전달합니다.
아웃바운드 어댑터: 비즈니스 로직의 요청을 외부 시스템에 전달합니다.
비즈니스 로직을 독립적으로 테스트하기 쉬움
다양한 외부 시스템과의 연결을 유연하게 처리
현대적인 애플리케이션 구조를 잘 반영
마이크로서비스 아키텍처란?
하나의 큰 애플리케이션을 여러개 의 작은 독립적인 서비스 나누는방식
각 서비스는 특정 비즈니스 기능 담당
모놀리식 아키텍처와의 차이
모놀리식: 모든 기능이 하나의 큰 프로그램 통합
마이크로서비스 : 여러 개의 작은 프로그램으로 나뉨
마이크로 서비스 특징
독립적 배포: 각 서비스 개별 업데이트 가능
자체 아키텍처: 각 서비스는 자신만의 내부(헥사고날) 가짐.
중요 개념
서비스 : 특정 비즈니스기능을 담당하는 독립적 프로그램 단위
느슨한 결합: 서비스간 의존성 최소화 설계 법칙
특정 기능을 수행하는 독립적 소프트웨어 조각
자체 api를 통해 외부와 소통
독립적 배포가능
특징
- API제공: 명령(데엍벼녁ㅇ) 조회(데이터 읽기) 기능 제공
이벤트(중요변화) 알림- 캡슐화: 내부 동작 숨김
외부에서는 API통해서 접근 가능- 독립성: 자체 기술 스택 선택가능
보통 헥사고날 사용- 다양한 구현방식: 독립 프로그램, 웹 ,애플리케이션 클라우드 기능 등 구현 가능
여러 프로그램에서 공통으로 사용하는 코드 모음
코드 중복을 줄이고 재사용성 높이는대 도움을 줌
장점: 코드 중복을 줄인다
단점: 서비스간 불필요한 의존성 만들수 있다
변경 가능성: 자주 바뀌는 기능은 공유 라이브러리보다 별도 서비스 만드는게 좋음
안정성: 거의 바뀌지 않는기능(ex:돈계산) 공유라이브러리 만들어도 좋음
예를 들어 Order라는 비즈니스 객체를 여러 서비스가 업데이트하는 상황을 생각해 봅시다. 필요한 공용 기능을 라이브러리 하나에 모두 패키징해 배포하면 될 테니…… 코드 중복은 안 해도 되겠지만 나중에 요건이 Order에 영향을 주는 방향으로 변경되면 어떻게 될까요? 관련 서비스를 일제히 다시 빌드해서 재배포해야겠죠. 이렇게 변경 가능성이 조금이라도 있는 기능이라면 별도의 서비스로 구현하는 것이 낫습니다.
- 작은 팀이 독립적으로 개발하는 크기
- 다른팀과 협업을 최소화 할 수 있는정도
- 개발과 테스트에 걸리는 시간
- 한 팀이 감당하기 어려울 정도로 클 경우
- 테스트 시간이 너무 길어지는 경우
- 다른 서비스와의 의존성이 높다면 느슨한 결합 되도록 재설계
- 분산 모놀리스 만들지 않도록 주의
서비스가 너무 밀접하게 연결되어 독립성 잃은 상태
- 핵심요청 파악하기
- 애플리케이션이 처리해야 할 주요 작업 파악 (주문생성, 주문조회)
- 서비스 나누기
- 비즈니스 기능을 기준으로 여러 개의 작은서비스로 나눈다
주문서비스 , 고객서비스, 배송서비스
- 각 서비스 api 정하기
- 각 서비스가 어떤 기능을 제공할지 결정
- 서비스 간 협력 방식 정의
- 네트워크 지연: 서비스간 통신이 너무많으면 속도가 느려짐
애플리케이션에서 다루는 주요 개념 파악 ( 주문, 고객, 상품)
2단계는 시스템 작업 식별 후 그 동작을 도메인 모델 관점에서 기술
애플리케이션이 수행해야 할 주요 작업을 파악
이 작업들이 도메인 모델과 어떻게 상호 작용하는지 설명
ex: 주문생성, 주문취소 , 상품검색
도메인 모델 만들기 팁
사용자 스토리에서 주로 명사를 찾아 도메인 모델만듬
이벤트 스토밍 기법 사용할 수 도 있다
시스템 작업 정의 팁
사용자 스토리에서 주로 동사를 찾아 시스템 작업 정의
각 작업이 도메인 모델을 어떻게 변경하는지 설명
고수준의 애플리케이션 도메인 모델을 대략 그려 보면. 최종적으로 구현할 모델보다는 훨씬 단순한 모습
각 서비스는 자체 도메인 모델을 소유하기 때문에 도메인 모델이 하나뿐인 애플리케이션은 없다
너무 지나치게 단순화한 감은 있지만, 고수준 도메인 모델은 시스템 작업의 동작을 기술하는 데 필요한 보케블러리를 정의하기 때문에 이 단계에서는 유용
사용자 스토리 분석
사용자의 스토리에서 명사 찾음
ex: 주문하기 , 스토리에서 소비자, 주문, 음식점 등 찾음
시나리오 확장
각 사용자 스토리를 구체적인 시나리오로 확장
전제 조건, 행동, 결과를 명확히 정의
클래스 도출
시나리오에서 발견된 명사들 클래스 변환
Consumer, Order 등
관계 설정
클래스 간의 관계 파악
ex: 소비자가 주문하고 주문은 음식점과 연관
모델 완성
도출된 클래스들을 모아 전체 도메인 모델 그림
의미 부여
각 클래스가 무엇을 의미하는지 설명
애플리케이션이 어떤 요청을 처리할지 식별하는 단계
애플리케이션 요청 처리 단계:
UI에서 백엔드 비즈니스 로직 요청 및 데이터 조회 수정
http요청 기반이지만 메시징도 고려, 추상적 시스템 작업 개념 도임
시스템 작업의 두종류
커맨드(cud) : 데이터 생성 수정 삭제
쿼리(R): 데이터 읽기
커맨드 식별 방법
사용자 스토리/시나리오 동사 분석
ex: createOrder(), acceptOrder(),noteOrderReadyForPickup
커맨드 명세
매개변수, 반환값 동작 방식의 명세를 도메인 모델 클래스로 정의
이 명세는 작업 호출시 충족되어야 할 선행조건 , 작업 호출후 충족되어야 할 후행 조건으로 구성 됨
ex: createOrder의 선행 조건과 후행 조건
사용자 의사 결졍에 필요한 정보 제공
findAvailableRestaurants()
findRestaurantMenu()
성능 고려 필요( 지리 검색 등 복잡한 쿼리)
서비스 식배려
qlwmsltm rosua wndtladmfh rntjd
고수준 도메인 모델과 시스템 작업을 보면 애플리케이션이 무슨 일을 하는지 알 수 있기 때문에 아키텍처를 정의하는 데 대단히 유용
애플리케이션의 기능 명확히 보여줌
아키텍처 정의에 매우 유용
각 시스템 작업은 도메인 모델 중심으로 기술됨
중요한 시스템 작업은 아키텍처적으로 중요한 시나리오를 나타냄
이러한 시나리오가 아키텍처를 기술하는 일부가 됨
시스템 작업 정의 후 진행
기계적인 식별 방법은 없음
다양한 분해 전략 존재
각 전략은 다른관점에서 문제에 접근
서로 다른 요엉 사용할 수 있다
그러나 최종 결과는 유사함
기술 개념이 아닌 비즈니스 개념 중심의 서비스 구성
비즈니스 능력에 따라 분해하기!
마이크로 서비스 아키텍처 구축의 첫 번째 전략
비즈니스가 가치를 생산하기 위해 하는일을 의미
업종마다 다름( 보험회사 , 온라인 쇼핑물)
조직의 본질을 나타냄
비즈니스 프로세스와 달리 상대적으로 안정적(크게 달라지지 않는다)
기술 변화에 영향을 덜 받음
ex ) 수표 예금이라는 비즈니스 능력은 거의 불변이지만, 처리하는 방법은 상당히 달라짐
조직의 목표 구조 비즈니스 프로세스 분석
비즈니스 능력 명세는 입력 출력 SLA등으로 다양한 컴포넌트로 구성
비즈니스 능력은 특정 비즈니스 객체에 집중 하위 능력으로 분해가능
ex ) 클레임이라는 비즈니스 객체는 클레임 관리 능력을 중심으로 클레임 정보 관리, 클레임 검토, 클레임 지불 관리 등의 하위 능력
공급자관리(배달원 관리,음식점 정보 관리)
소비자 관리
주문 접수 및 이행(주문관리 , 음식점 주문관리, 로지스틱스)
회계(소비자, 음식점, 배달원 회계)
DDD는 도메인을 구성하는 각 하위 도메인(애플리케이션의 문제 공간(problem space)을 가리키는 DDD 용어) 마다 도메인 모델을 따로 정의
하위 도메인: 애플리케이션의 문제 공간
하위 도메인은 비즈니스의 특정 부분 또는 영역
'문제 공간'이란 애플리케이션이 해결하려는 실제 비즈니스 문제들의 집합을 의미
예시: 온라인 쇼핑몰을 생각해 보자
이 쇼핑몰의 하위 도메인들은 다음과 같을 수 있음
상품 관리 (상품 등록, 재고 관리 등)
주문 처리 (장바구니, 결제 등)
배송 관리
고객 서비스
마이크로서비스와의 관계
- 각 하위 도메인은 종종 하나 또는 몇 개의 마이크로서비스로 구현
- 이를 통해 각 서비스가 특정 비즈니스 문제에 집중할 수 있게 됨.
- 경계 컨텍스트: 도메인 모델의 범위
-> 서비스 단순해지고 다른부분 변경해도 영향 X 각 서비스 독립적 개발 관리 쉬워짐
-> ex) 음식 주문 과정의 각 단계(주문 접수, 준비 , 배달)를 별도으 ㅣ서비스로 만듬
복잡한 시스템을 만들 때, 각 부분이 한 가지 일만 책임지도록 하면 전체 시스템을 더 쉽게 관리하고 변경할 수 있다는 것. 이는 마이크로서비스 아키텍처의 핵심 설계 원칙 중 하나
-> 변경이 필요할 대 영향 받는 서비스 수 줄 어듬
-> 한 팀이 관련된 변경 모두 처리 함
-> 시스템 유지보수 쉬워짐
-> 분산 모놀리스 문제해결
- 마이크로서비스를 설계할 때, 변경의 이유를 고려해야 합니다.
- 관련된 변경사항들을 한 서비스에 모아두면 시스템 관리가 더 쉬워집니다.
- SRP, CCP, 비즈니스 능력/하위 도메인 분해는 좋은 마이크로서비스 설계 지침입니다.
- 하지만 이런 원칙들을 적용할 때도 트랜잭션 관리, 서비스 간 통신 등의 문제를 고려해야 합니다.
ex: 가령 주문 서비스의 createOrder()는 타 서비스의 REST API를 동기 호출하는 것이 가장 쉬운 구현 방법이지만, 타 서비스 중 하나라도 불능일 경우 주문은 생성되지 않기 때문 가용성 떨어짐
실제로 이것은 거의 문제가 되지 않음
마이크로서비스 아키텍처를 구축할 때 여러 기술적 어려움이 있지만, 이를 해결할 방법들이 있다. 이러한 문제들을 이해하고 적절한 해결책을 적용하는 것이 중요
만능 클래스는 너무 많은 기능을 가진 클래스입니다.
예: 은행 시스템의 '계좌', 전자상거래의 '주문' 등
이런 클래스는 서비스를 나누기 어렵게 만듭니다.
주문, 음식점, 배달, 지불 등 모든 정보를 포함합니다.
이런 구조는 서비스 분리를 어렵게 합니다.
DDD(Domain-Driven Design) 적용
각 서비스마다 자신만의 Order 모델을 만듭니다.
예: 배달 서비스는 'Delivery', 주방 서비스는 'Ticket' 사용
서비스 간 데이터 일관성 유지 필요
해결책: 이벤트 주도 메커니즘, 사가(saga) 패턴 사용
UX 구현 시 여러 모델 간 변환 필요
해결책: API 게이트웨이 사용
만능 클래스는 마이크로서비스 아키텍처 구축의 큰 장애물이지만, DDD를 적용하여 각 서비스에 맞는 모델을 만들면 이 문제를 해결할 수 있다. 다만, 이로 인해 발생하는 새로운 문제들에 대한 해결책도 함께 고려해야 함
서비스 API를 정의하는 것은 마이크로서비스 아키텍처 설계의 핵심 단계입니다. 이를 통해 각 서비스의 역할과 서비스 간 협력 방식을 명확히 할 수 있으며, 이는 전체 시스템의 효율적인 운영을 위해 매우 중요합니다.