빌드 날짜: 2026-08-29

참고 도서

도서 이미지
<도서 이미지>[원본 보기]
표제데이터 중심 애플리케이션 설계
저자마틴 클레프만
ISBN979-11-5839-098-3 (93000)
출판사위키북스
발행일2018.04.12
도서 이미지
<도서 이미지>[원본 보기]
표제클라우드 시스템을 관리하는 기술
저자토머스 리몬첼리, 스트래치 체일럽, 크리스티나 호건
ISBN978-89-6848-261-8 [93000]
출판사한빛미디어(주)
발행일2015년 02월 25일
도서 이미지
<도서 이미지>[원본 보기]
표제인프라 디자인 패턴
저자스기하라 타케오 외 4
ISBN978-89-94774-88-6 (93000)
출판사비제이퍼블릭
발행일2015.02.12
도서 이미지
<도서 이미지>[원본 보기]
표제클린 아키텍처
저자로버트 C. 마틴
ISBN978-89-6626-247-2 (14000)
출판사인사이트
발행일2019.08.20
도서 이미지
<도서 이미지>[원본 보기]
표제마이크로서비스 도입 이렇게 한다
저자샘 뉴먼
ISBN979-11-89909-25-3 (93000)
출판사책만
발행일2021.01.20

개요

사업 목표

잘 정의된 사업 목표들은 측정 가능하며, 측정치(KPI)를 자동으로 수집하여 현황판(dashboard)으로 만들 수 있어야 한다

이상적인 시스템 구조

SOA best practice

이상적인 릴리스 과정

이상적인 운영

운영을 위한 시스템 설계

설계와 아키텍처

설계 수준 구별

지연 시간

  1. 지연 시간이 적절한 지 평가하기 위해 p95, p99, p999 등의 분위수를 사용하며, SLA(서비스 수준 계약)의 기준이 된다
  2. 아마존은 p999를 기준으로 내부 서비스의 응답 시간 요구사항을 기술하는데, 이는 보통 응답 시간이 가장 느린 요청을 경험한 고객들은 많은 구매를 해 많은 데이터를 가진 가장 소중한 고객들이기 때문이다
  3. 특정 API 응답 지연은 다른 API 엔드포인트로 전파될 수 있다

    TCP에서 Head-of-line blocking 문제가 발생하듯, 클라이언트에 뷰를 구성하기 위해 여러 API 응답을 모두 기다려야 하는 상황이 존재하면 특정 1개 API로 인해 전체적으로 느린 경험을 하게 된다

시스템 탄력성을 위해 고려할 점

기술 부채

  1. 기술 부채

    개발자가 임시방편을 선택하면 기술은 부채를 지게 된다. 누적된 기술 부채가 너무 커서 제품을 포기해야 하는 상황을 기술 파산이라고 한다

  2. 기술 부채 요소

    코드 부채, 설계 부채, 테스트 부채, 문서 부채

패러다임 개요

SOLID 설계 원칙

Single Responsibility Principle; 단일 책임 원칙

각 모듈은 변경되어야 할 이유가 단 하나여야 한다
=> 각 모듈은 하나의 액터(사용자 또는 이해관계자)에 대해서만 책임을 져야 한다
=> 그렇지 않다면 모듈을 분리해야 한다

예: 우발적 중복

회계팀에서 사용하는 calculatePay() 메서드와 인사팀에서 사용하는 reportHours() 메서드가 정규 근로 시간을 계산하는 함수 regularHours()를 공유할 때, 인사팀에서 정규 근로 시간 정의를 변경하면 이는 회계팀에도 영향을 미쳐 잘못된 급여가 지불될 가능성이 있다

Open-Closed Principle; 개방-폐쇄 원칙

기존 코드를 수정하기보다, 새로운 코드를 추가하는 방식으로 행위를 변경하도록 설계해야 한다
=> 이를 위해 시스템은 컴포넌트 단위로 분리하고, 저수준 컴포넌트의 변경으로부터 고수준 컴포넌트를 보호할 수 있도록 계층구조가 만들어져야 한다

Liskov Substitution Principle; 리스코프 치환 원칙

상호 대체 가능한 구성요소를 이용해 소프트웨어 시스템을 만들 수 있으려면, 이들 구성요소는 반드시 서로 치환 가능해야 한다
=> 이들 구성요소는 클래스, 인터페이스에 국한되지 않는다. 예를 들어, 특정 REST API 군을 처리하는 서버도 치환 가능한 시스템의 구성요소가 될 수 있다

예. 높이와 너비를 각각 변경할 수 있는 직사각형은, 정사각형의 부모가 될 수 없다

Interface Segregation Principle; 인터페이스 분리 원칙

사용하지 않는 것에 의존하지 않아야 한다 -- 사용하는 것만 인터페이스로 분리하여 넘겨야 한다

Dependency Inversion Principle; 의존성 역전 원칙

고수준 정책을 구현하는 코드는 (자주 변경되는) 저수준 세부사항을 구현하는 코드에 의존해서는 안 된다. 세부사항이 정책에 의존해야 한다

코드 디자인 패턴

  1. Abstract Factory

    서로 관련 있는 여러 객체들에 대한 군집을 생성하는 인터페이스 제공
    AbstractFactory : 군집 인스턴스 생성 연산 정의 → 구현 : ConcreteFactory
    AbstractProduct : 군집을 구성하는 각 객체 정의 → 구현 : ConcreteProduct

  2. Builder

    복잡한 ─ 필드가 많지만, 인스턴스화에 모든 필드가 필요하지는 않은 ─ 객체 생성 로직을 별도 클래스로 분리

  3. Factory Method(Virtual Constructor)

    객체 생성 인터페이스를 정의. 구현을 어떻게 할 지는 각 서브클래스가 결정

  4. Prototype

    견본이 되는 인스턴스를 복사하여 새로운 객체 생성. Prototype은 복제 연산을 가져야 한다

  5. Singleton

    단 하나의 클래스 인스턴스만 존재하며, 이를 공유

  6. Adapter, Wrapper

    클래스의 인터페이스를 기대하는 다른 인터페이스로 변환

  7. Facade

    서브시스템을 사용하기 쉽도록 상위 수준의 인터페이스 정의

  8. Decorator

    동적으로 새로운 기능 추가

  9. Proxy

    다른 객체에 대한 접근을 제어하는 대리자

  10. Chain of Responsibility

    요청을 자신이 처리해야 한다면 처리, 아니라면 후속 처리자에게 전달

  11. Iterator

    내부를 노출하지 않고 원소를 차례대로 접근하는 방법 제공

  12. Mediator

    내부 객체들이 서로를 직접 참조하지 않고, Mediator를 통해 교류

  13. Observer

    감시하는 객체의 상태가 변하면 의존하는 객체들이 통지받도록 한다

  14. State

    객체 내부 상태에 따라 행동을 변경

  15. Template Method

    부모 클래스(abstract)는 공통 메서드를 정의하고, 각 leaf 클래스는 제각각의 구현을 갖는다

  16. Strategy

    동일한 계열의 알고리즘들을 캡슐화하여 상호 교환할 수 있도록 한다

  17. Scott Meyers

    All non-leaf classes should be abstract

코드 리팩터링

  1. 자주 쓰이지 않는 코드의 성능 향상에 얽매이지 말 것
  2. 주석을 적는 대신 주석이 설명하는 부분을 메서드로 추출
  3. Extract Method

    코드들을 그룹으로 묶어도 좋겠다고 판단된다면, 목적이 드러나는 직관적인 이름의 메서드로 추출

  4. Split Temporary Variable

    루프 변수나 누적용 임시 변수가 아닌 경우, 각 대입마다 새로운 임시변수를 사용하여 되도록 final 임시변수만 이용

  5. Remove Assignments to Parameters

    매개변수는 되도록 final이 되도록 한다

  6. Replace Method with Method Object

    지역변수로 메서드 추출이 어려운 아주 긴 메서드가 있을 때, 지역변수를 필드로 하는 객체를 만들고 메서드를 잘게 쪼갠다

  7. Move Method

    메서드가 다른 클래스의 기능을 더 많이 이용할 때, 해당 클래스에 비슷한 내용의 메서드를 작성. 기존 메서드는 대리자로 변경하거나 삭제

  8. Extract Class

    클래스가 2가지 이상의 책임을 가진 경우

  9. Pull Up Field/Method/Constructor Body

    두 하위클래스의 같은 필드/메서드/생성자 코드는 상위클래스로. 반대로 특정 서브클래스에서만 이용하는 것은 하위클래스로

  10. Replace Inheritance with Delegation

    상위클래스의 일부만 이용하는 경우, 상위클래스 인스턴스를 필드로 갖고 메서드에서는 호출을 위임. 반대로, 클래스 전반에 걸쳐 위임이 도배되는 경우엔 차라리 상속으로 전환

시스템 규모 확장

마이크로서비스

개요

CQRS(Command and Query Responsibility Segregation)

마이크로서비스가 적합하지 않은 경우

서비스는 적을수록 좋다

서비스 분리 과도기에서의 호출 패턴

CAP 정리와 PACELC 정리

참고 문헌 : Proving PACELC

CAP 정리 또는 브루어(Brewer)의 정리는 분산 시스템이 다음 3가지를 모두 보장할 수 없다는 것을 명시한다

분산 시스템은 필연적으로 여러 노드들이 서로 통신하며 운영되는데, 광역 네트워크 장애로 인해 시스템이 내부적으로는 통신이 가능하지만 서로 간에는 통신이 불가능한 파티션 현상이 발생하는 경우, 일관성과 가용성을 모두 만족시킬 수는 없다는 의미다.

어떤 시스템을 AP, CP, CA 중 하나로 분류할 수 있다는 오해를 불러 일으키는 점, 파티션이 발생하지 않은 경우에 대한 설명이 부족한 점을 보충하는 PACELC 정리가 이후 등장했다.

PACELC에서 설명하는 트레이드오프
<PACELC에서 설명하는 트레이드오프>[원본 보기]

구체적으로는

데이터베이스

데이터 모델

한편, 주요 관계형 데이터베이스에 JSON 지원이 추가되기도 하고, 문서 데이터베이스에서 집계 쿼리와 유사한 기능을 제공하기도 한다.

문서 데이터베이스는 스키마리스로 불리기도 하는데, 데이터를 읽는 코드는 어느 정도 구조를 가정하기 때문에 오해의 소지가 있다. 대신 아래와 같이 구분하는 것이 좋다

컬럼 지향 저장소

데이터베이스의 2가지 주요 사용 사례는 아래와 같다

특성OLTP(Online transaction processing)OLAP(Online analytic processing)
주요 요청자고객(엔드 유저)데이터 분석가(직원)
읽기 패턴질의 당 적은 수의 레코드, 키 기준많은 레코드의 적은 수의 컬럼에 대한 집계
쓰기 패턴사용자 요청에 따라 낮은 지연으로 임의 위치에 수행대규모 불러오기 또는 이벤트 스트림
데이터 표현데이터의 최신 상태시간에 따른 이벤트 이력
데이터셋 크기GB ~ TBTB ~ PB

비즈니스 의사 결정에 중요한 OLAP 시스템으로 컬럼 지향 저장소가 출시되어 활발히 이용되고 있다

메시지 큐

설계 전 제약사항

설계 요소

메시지 전달 보장 레벨

분산 데이터 시스템

설계 원칙

모든 상황에 맞는 확장 아키텍처는 없다 -- 1KB를 초당 10만건 처리하는 시스템과 2GB를 분당 3건 처리하는 시스템은 데이터 처리량이 같아도 설계는 매우 다르다.

특정 애플리케이션에 적합한 아키텍처는 주요 동작이 무엇인지, 잘 하지 않는 동작이 무엇인지에 대한 가정을 부하 매개변수로 하여 구축한다 -- 하지만 스타트업 초기 단계나 검증되지 않은 제품은 불확실한 가정에 대비하기보다, 유지보수에 초점을 맞추는 것이 좋다

복제

복제 방식에 따른 구분

동기식 복제

비동기식 복제

반동기식 복제

토폴로지에 따른 구분

단일 리더 복제

다중 리더 복제

리더 장애 복구

리더 없는 복제

선형성과 인과성

파티션

분산 트랜잭션과 합의

2단계 커밋(2PC)

  1. 코디네이터는 쓰기에 참여하는 모든 노드에게 트랜잭션의 내용이 유효한지 묻는다

    이 시점에 "네"라고 응답한 노드는 단독으로 롤백을 수행할 수 없다 -- 이후 어떤 장애가 도중에 발생하든 코디네이터로부터 커밋 또는 롤백 결정을 받은 뒤 반영해야 한다. 이러한 장애 상태의 트랜잭션은 의심스러운 또는 불확실한 상태에 있다고 한다

  2. 모든 노드가 유효하다고 응답했다면, 코디네이터는 모든 노드에게 커밋을 요구한다

    코디네이터 장애 복구를 위해, 코디네이터는 최종 요청을 노드들에게 보내기 전에 디스크에 기록해야 한다

XA 트랜잭션

합의

합의 알고리즘은 다음을 만족해야 한다

합의 알고리즘을 구현하는 것은 매우 어려우며, 주키퍼와 같은 성공적인 도구를 이용해 합의, 장애 감지, 분산 잠금, 멤버십 서비스 등을 위탁하는 것이 합리적이다