4/20(월) 설계, SA 문서 작성, SA 문서 항목의 구분 (서비스 구성도)

dev_joo·2026년 4월 20일

질문

질문 1

독후감이 개인 독후감, 모임활동에서 독후감으로 나뉘는데
단일 테이블로 구성할 경우 모임활동과 관련된 모임 ID와 회차는 nullable 한 필드가 된다.

Null 이 있는 필드의 관리

null이 있는 필드라고 하더라도 운영하는 데는 크게 어려움이 없긴 함
null이 있는 필드가 계속 늘어날 여지가 있다 할 땐 정규화해서 쪼개서 처음부터 관리를 해야 나중에 마이그레이션 작업도 따로 발생을 안 하고 쿼리도 복잡하지 않음

테이블의 분리

테이블을 분리를 하든 합친 테이블을 쓰든 정합성만 지키면 딱히 성능적으로는 문제가 없음
데이터가 많을 때를 가정하는 거라 커서가 잘못된 가정이 있을 수 있음
조인에 대한 부하가 많아서일 경우도 있으니까 이럴 때는 풀어나가는 방법이 데이터가 단순히 많아서 인덱스를 걸어서 풀어야겠다는 적합하지 않을 수 있을 것 같음


질문 2

도메인 계층의 스테이터스 코드

도메인 계층에 있는 HTTP 스테이터스 코드가 원칙적으로는 안 되지만 허용

도메인 계층에 관심을 가지는 계층은 애플리케이션 계층만 있는 게 아니라 내부에서 외부로 들어오는 것도 아니고 외부에서 내부로 나갈 때도 관심을 표현할 수 있음
도메인에 웹 표현 계층에 종속되는 스테이터스 코드는 들어와도 되냐 들어와도 되지 않느냐를 따져보는 게 애매

표현계층 예외처리를 애플리케이션~도메인 계층과 분리해야 맞지만 헥사고날을 바로 도입하기보단 시간 상 초록색 부분의 구현에 집중하기로


바운디드 컨텍스트 문서 작성


SA 문서 항목의 구분

주어진 SA 문서 템플릿에는 인프라 구성도와 시스템 구조도(서비스 구성도) 항목이 모두 포함되어 있었는데,

둘 다 “구성요소를 그린다”는 점 때문에 처음에는 차이가 모호하게 느껴져 어떻게 그려야 할지 고민되었다.

그리고 시스템 구조도는 또 컨텍스트 맵과 비슷해보였는데,
둘 다 "서비스 간 관계"를 그리기 때문이었다.

1. 인프라 구성도 (리소스 중심)

인프라 구성도는 서비스가 어떤 인프라(자원) 위에 배치되는지를 나타낸다.

“어디에서, 어떤 자원으로 돌아가는가” (물리/클라우드 레이어)
AWS VPC, 서브넷, ALB, EKS, RDS, S3 같은 인프라 리소스와 네트워크 구성

2. 바운디드 컨텍스트 / 컨텍스트 맵

컨텍스트 맵은 시스템을 구성하는 도메인을 나누고, 그 사이의 관계를 정의한다.
주요 관심사는 기술이 아니라 ‘개념과 책임’이다.

"어떤 도메인이 있고 어떻게 엮이는가" (도메인 레이어, DDD 관점)
User, Meeting, Book, Trade 같은 논리적 도메인 경계와 그 사이의 관계(업스트림/다운스트림, ACL 등)

업스트림(Upstream) / 다운스트림(Downstream)

두 컨텍스트가 의존 관계일 때, 누가 누구의 영향을 받는지를 나타내는 표현 (강물에 비유)

  • 업스트림: 상류. 변경의 원천이 되는 쪽. 먼저 결정하고, 자기 사정대로 바꿀 수 있는 쪽.

  • 다운스트림: 하류. 업스트림의 변경을 받아서 맞춰야 하는 쪽.

바운디드 컨텍스트컨텍스트 맵

ACL (Anti-Corruption Layer, 부패 방지 계층)

  • 외부 컨텍스트의 모델이 다른 컨텍스트로 그대로 흘러들어오지 못하게 막는 번역 계층
  • 업스트림 서비스의 데이터 구조를 다른 쪽에서 그대로 가져다 쓰면, 업스트림이 바뀔 때마다 내 도메인 로직이 전부 깨진다.
  • 업스트림의 용어·개념이 내 컨텍스트의 용어·개념과 안 맞는 경우도 많다.
  • 그래서 중간에 "번역기"를 둬서, 외부 모델 → 내부 모델로 변환한 뒤에만 내 도메인이 사용하게 한다.

ex) 중고거래 컨텍스트유저 컨텍스트에서 판매자 정보를 가져올 때,
유저 쪽의 UserDto(이름, 이메일, 전화번호, 평점, 가입일…)를 그대로 받지 않고, 거래에서 필요한 Seller(판매자ID, 닉네임, 평점)로 변환해서 쓰기

3. 서비스 구성도 (서비스/컴포넌트 중심)

시스템 구조도는 실제 실행 시점의 흐름을 표현한다.

"어떤 서비스들이 실제로 어떻게 통신하는가" (애플리케이션/런타임 서비스 레이어)
동기통신: API 호출 (REST, gRPC)
비동기 통신: 메시지 큐 (Kafka, RabbitMQ)
이벤트 흐름 서비스 간 의존 관계

서비스 구성도 vs 인프라 구성도

인프라는 리소스 중심, 시스템 구조도는 서비스/컴포넌트 중심이라는 점에서 차이를 가진다.

서비스 구성도 vs 컨텍스트 맵

컨텍스트 맵은 도메인 간 개념적 관계, 시스템 구조도는 런타임에 실제로 일어나는 호출/이벤트 흐름이라는 추상화 수준(관점)에서 차이가 있다. 컨텍스트 맵은 개발자가 아닌 비즈니스 이해관계자가 이해할 수 있다.

시스템 구성도(서비스 구성도)가 없으면?

1. 통신 방식(동기/비동기)의 혼란과 성능 병목

컨텍스트 맵은 "A 도메인이 B 도메인을 의존한다(다운스트림)" 정도만 보여준다. 하지만 실제 코드로 구현할 때 '어떻게' 통신할 것인지는 알려주지 않는다.

발생하는 문제: 예를 들어, 유저(User) 서비스, 주문(Order) 서비스, 배달(Delivery) 서비스가 있다고 가정해보자. 유저가 주문을 생성했을 때 배달 서비스로 정보가 넘어가야 한다.

시스템 구조도에서 이를 비동기 이벤트(Kafka 등)로 처리할지, 동기 호출(FeignClient, REST API)로 처리할지 명시하지 않으면, 개발자들은 가장 구현이 익숙한 동기 호출(REST)로 도배할 가능성이 높다. 결과적으로 한 서비스의 응답 지연이 전체 시스템의 타임아웃으로 이어지는 병목이 발생할 수 있다.

2. 분산 트랜잭션과 데이터 정합성 보장의 어려움

MSA 환경에서는 DB가 분리되어 있기 때문에, 여러 서비스에 걸친 작업이 중간에 실패했을 때 어떻게 롤백할 것인지(Saga 패턴 등)가 매우 중요하다.

발생하는 문제: 시스템 구성도에는 각 서비스 간의 API 호출 순서와 이벤트 발행 흐름이 나타나있는데, 이 흐름도가 없으면, 주문은 성공했는데 배달 생성 단계에서 에러가 났을 때, 어떤 보상 트랜잭션(이벤트)을 어느 서비스로 던져야 주문을 취소 상태로 되돌릴 수 있는지 아키텍처 레벨에서 파악하기 어렵다.

개발자 각자가 파편화된 로직으로 예외 처리를 하게 되어 데이터 정합성이 깨질 수 있다.

3. 장애 격리(Fault Tolerance) 설계 누락

인프라 구성도는 서버가 죽는 것(물리적/네트워크 장애)에 대한 대비책(이중화 등)은 보여주지만, 애플리케이션 레벨의 장애 전파는 보여주지 못한다.

발생하는 문제: 시스템 구조도에서 API Gateway를 거쳐 각 서비스로 흐르는 트래픽의 방향과 서비스 간 직접 호출(Point-to-Point)을 한눈에 볼 수 있어야, "어느 구간에 서킷 브레이커(Circuit Breaker)를 달아야 하는가?"를 결정할 수 있다.
(장애 발생 시 어느 서비스가 연쇄적으로 다운될지 예측)

4. API 엔드포인트 및 인터페이스 합의 부재

프론트엔드 개발자나 외부 클라이언트가 우리 시스템과 통신해야 할 때, 컨텍스트 맵은 너무 추상적이고 인프라 구성도에서 나타나는 계층은 너무 로우레벨이다.

발생하는 문제: 시스템 구조도가 없으면 클라이언트 요청이 API Gateway를 통해 라우팅되는지, 혹은 인증 서버(Keycloak 등)를 먼저 거쳐서 인가 토큰을 받아야 하는지, 실제 런타임의 Request/Response 흐름을 파악하기 어렵다.
다른 개발자에게 일일이 물어봐야만 연동 작업을 시작할 수 있게 된다.


정리

즉,
컨텍스트 맵은 “왜 나뉘고 어떻게 협력하는가”,

시스템 구조도는 “실제로 어떻게 호출되고 흐르는가”,

인프라 구성도는 “그 흐름이 어디에서 돌아가는가”를 설명한다.

profile
풀스택 연습생. 끈기있는 삽질로 무대에서 화려하게 데뷔할 예정 ❤️🔥

0개의 댓글