Skip to content
Kang Log
Go back

MSA 기초

Updated:

Day 1. MSA 기초

1. 오늘의 학습 목표

2. 학습 전 생각해보기

질문 1

하나의 Spring Boot 애플리케이션에 상품, 주문, 재고, 결제 기능을 모두 두면 어떤 점이 편하고 어떤 점이 불편할까?

내 답변

  • 애플리케이션 내에서 repository나 service 를 통해 각 기능들을 한번에 제어할 수 있어서 개발에서의 효율성이 올라가고 유지보수에서 큰 장점을 가진다.
  • 어떤점이 불편하지.. , 알수 없는 에러가 발생했을 때 어느 단계에서 문제가 생겼는지 범위를 좁히기 어려운 경향이있다.
  • 개발자들이 전반적인 기능에대한 전반적 지식이 필요하다?
질문 1 정석 답변 보기 하나의 Spring Boot 애플리케이션에 모든 기능을 두면 같은 프로세스 안에서 Service나 Repository를 호출할 수 있어 개발이 단순하다. 여러 기능의 DB 변경을 하나의 트랜잭션으로 묶기 쉽고, 배포 대상과 로그가 하나라서 초기에는 테스트와 장애 추적도 비교적 편하다. 반면 애플리케이션이 커지면 작은 기능을 변경해도 전체를 테스트하고 배포해야 한다. 결제 트래픽만 증가해도 상품, 주문, 재고 기능이 포함된 애플리케이션 전체를 확장해야 하므로 자원이 낭비될 수 있다. 기능 간 경계가 무너지면 변경 영향 범위를 파악하기도 어려워진다.

질문 2

Order 서비스가 재고 수량을 알아야 할 때 Stock 테이블을 직접 조회하는 것이 왜 자연스럽게 느껴질까? 장기적으로는 어떤 문제가 생길까?

내 답변

사람입장에서 생각했을때 주문이 들어오면 주문이 들어온 상품이 남아있는지 직접 확인해보는것이 자연스러운 흐름이기때문에 직접 조회하는 것이 자연스럽게 느껴진다. 장기적으로 어떤 문제가 생길까 .. 뭔가 대규모 트래픽이 발생한다면 직접 확인하는 경우 트랜잭션의 라이프 사이클이 요청이 들어와서 직접 조회하고 처리하는 것까지 직접 담당하기때문에, 서버 부담이 커질 수도 있을 것 같다. 근데 두 서버를 쪼개두면 하나의 서버에서 요청이 발생하면 이벤트를 발행하여 큐의 형식으로 저장해놓고 다른 서버에서 consume할 때 실행을 하고 또 이벤트를 발행하는 방식으로 요청을 처리한다면, 좀 더 유기적으로 병렬 작업을 할수 있을 것이다.

질문 2 정석 답변 보기 Order가 Stock 테이블을 직접 조회하면 구현이 단순하고 빠르기 때문에 자연스럽게 느껴진다. 특히 모놀리식에서 Repository 호출이나 테이블 조인에 익숙하다면 더욱 그렇다. 하지만 MSA에서 Stock 데이터의 소유자는 Stock 서비스다. Order가 Stock 테이블 구조를 직접 알게 되면 Stock의 스키마 변경이 Order에도 영향을 준다. 직접 수정까지 한다면 재고 부족 검증이나 동시성 제어 같은 Stock의 규칙을 우회할 수도 있다. 따라서 Order는 Stock DB에 직접 접근하지 않고 Stock 서비스가 제공하는 명시적인 통신 경로를 사용해야 한다. 이 프로젝트에서는 Kafka 이벤트를 통해 재고 처리를 진행한다.

질문 3

트래픽이 결제 기능에만 몰린다면 애플리케이션 전체를 늘리는 것과 Payment 서비스만 늘리는 것은 무엇이 다를까?

내 답변

애플리케이션 전체를 늘린다는 의미가 무슨 말인지는 모르겠지만,, 서버를 확장한다는건가? 느낌적인 느낌으로는 애플리케이션 전체를 늘리는것은 결제기능과는 다소 상관없는 부분들까지 추가비용이 발생하면서 커지는 느낌이고, Payment 서비스만 늘리는 것은 트래픽이 결제기능에 몰리는 것에 대한 유기적인 대처가 가능한 것처럼 들린다.

질문 3 정석 답변 보기 “애플리케이션 전체를 늘린다”는 것은 모놀리식 애플리케이션의 서버 인스턴스를 추가한다는 뜻이다. 모놀리식에서는 결제 트래픽만 증가해도 Product, Order, Stock, Payment가 모두 포함된 인스턴스를 통째로 추가해야 한다. 트래픽이 증가하지 않은 기능도 함께 실행되므로 CPU와 메모리 같은 자원이 불필요하게 사용될 수 있다. MSA에서는 Payment가 독립된 실행 단위이므로 Payment 인스턴스만 추가할 수 있다. 이를 독립 확장이라고 하며, 필요한 기능에만 자원을 집중할 수 있다.

3. 핵심 개념 설명

3.1 모놀리식과 MSA

모놀리식 아키텍처는 상품, 주문, 재고, 결제 기능을 하나의 배포 단위로 만든다. 같은 프로세스 안에서 메서드를 호출하고 하나의 데이터베이스 트랜잭션으로 여러 테이블을 변경하기 쉬우므로 개발과 테스트, 배포가 단순하다. “모놀리식”은 코드가 반드시 엉켜 있다는 뜻이 아니다. 내부 모듈 경계를 잘 지킨 모놀리식도 가능하다.

MSA(Microservices Architecture)는 시스템을 비즈니스 책임별 서비스로 나누고 각 서비스를 별도로 실행·배포하는 방식이다. 이 프로젝트에서는 Product, Stock, Order, Payment가 각각 하나의 서비스다. 프로세스가 분리되므로 서비스 간 호출은 메서드 호출이 아니라 네트워크 통신이 된다.

핵심 차이는 프로젝트 폴더 개수가 아니라 독립적으로 변경하고 운영할 수 있는 경계다. 같은 저장소에 있어도 각 서비스가 자기 실행 단위와 데이터를 갖고 독립적으로 배포된다면 MSA일 수 있다. 반대로 폴더만 나누고 하나의 DB와 배포 주기에 강하게 묶여 있다면 실질적인 독립성은 낮다.

3.2 서비스를 나누는 이유와 서비스 경계

서비스를 나누는 주된 이유는 서로 다른 비즈니스 책임의 변경과 운영을 분리하기 위해서다. 상품 정보 변경과 결제 승인은 규칙, 장애 영향, 트래픽 특성이 다르다. 경계가 적절하면 상품 규칙을 바꿀 때 결제 서비스를 함께 배포할 필요가 없다.

서비스 경계는 “테이블 하나당 서비스 하나”처럼 기술 요소로 정하지 않는다. 함께 변경되고 같은 규칙으로 일관성을 지켜야 하는 업무를 묶는다. 예를 들어 재고 수량 차감과 복원은 Stock의 책임이고, 주문 상태 전이는 Order의 책임이다.

경계에는 비용도 있다. 두 서비스 사이의 작업은 네트워크 실패와 시간 차이를 고려해야 한다. 따라서 무조건 작게 쪼개기보다, 독립적으로 변경할 가치가 분리 비용보다 큰지를 판단해야 한다.

3.3 서비스별 데이터 소유권

데이터 소유권은 각 서비스만 자기 데이터를 직접 읽고 변경한다는 원칙이다. Stock 서비스가 재고 데이터의 소유자라면 Order 서비스는 Stock DB 테이블을 직접 조회하거나 수정하지 않는다. 필요한 결과를 Stock이 제공하는 통신 경로를 통해 얻는다.

다른 서비스가 테이블을 직접 사용하면 스키마 변경이 곧 여러 서비스의 장애 위험이 된다. 또한 “누가 재고 규칙을 지키는가”가 불분명해져 Stock의 검증을 우회한 변경도 가능해진다. 데이터베이스가 공유되면 코드만 분리했을 뿐 변경과 장애는 다시 결합된다.

데이터 소유권은 데이터 중복이 전혀 없어야 한다는 뜻은 아니다. Order가 주문 당시 상품명이나 가격을 주문 데이터로 보관할 수 있다. 중요한 것은 그 값이 어떤 업무 사실을 나타내며 누가 변경 권한을 갖는지 명확히 하는 것이다.

3.4 독립 배포와 독립 확장

독립 배포란 한 서비스 변경 때문에 전체 시스템을 한꺼번에 다시 배포하지 않는 것이다. Payment의 결제사 연동 코드만 바뀌었다면 Payment만 검증하고 배포할 수 있다. 배포 범위가 작아지는 대신 서비스 간 호환성을 관리해야 한다.

독립 확장은 부하가 큰 서비스의 인스턴스만 늘리는 것이다. 상품 조회가 많다면 Product를, 주문 이벤트 처리가 밀린다면 해당 소비 서비스를 집중적으로 확장할 수 있다. 모든 기능을 같은 크기로 늘리는 것보다 자원을 세밀하게 사용할 수 있다.

그러나 “독립”은 자동으로 얻어지지 않는다. 공유 DB, 공통 코드의 과도한 결합, 동시에 바꿔야만 하는 통신 규약이 있으면 독립 배포가 어려워진다.

3.5 MSA의 장점, 단점, 그리고 작은 시스템

MSA의 장점은 팀과 변경 범위를 서비스 책임에 맞출 수 있고, 장애를 격리하며, 필요한 부분만 확장할 수 있다는 점이다. 서비스마다 적합한 배포 주기를 선택할 수도 있다.

단점은 네트워크 실패, 배포 대상 증가, 로그 추적, 데이터 일관성, 테스트 환경 등 운영 문제가 늘어난다는 점이다. 모놀리식의 메서드 호출과 한 DB 트랜잭션으로 끝났던 작업이 여러 통신과 실패 처리로 바뀐다.

작은 팀과 작은 시스템에서는 이 비용이 이점보다 클 수 있다. 변경 충돌이나 확장 문제가 아직 없다면 잘 나눈 모놀리식이 더 단순할 수 있다. MSA는 목표가 아니라 특정 규모와 조직 문제를 해결하는 선택지다.

이후 학습: 서비스 간 이벤트 통신은 Day 2, 분산된 데이터 변경의 실패 처리는 Day 6에서 자세히 다룬다.

4. 흐름으로 이해하기

모놀리식
Client

[ Product | Order | Stock | Payment ]

[             하나의 DB              ]

MSA
Client
  ├──→ Product Service ──→ Product DB
  ├──→ Order Service   ──→ Order DB
  ├──→ Stock Service   ──→ Stock DB
  └──→ Payment Service ──→ Payment DB

모놀리식은 모든 기능이 하나의 실행·배포 단위에 있다. MSA에서는 각 서비스가 자기 책임과 데이터를 소유한다. 서비스 사이에 협력이 필요하면 명시적인 통신 경로를 사용해야 한다.

5. 직접 채우는 핵심 질문

질문 1. 모놀리식과 MSA를 “배포 단위”와 “통신 방식” 관점에서 비교하라.

내 답변

모놀리식은 전체 서비스가 하나의 배포단위이고, 통신은 클래스간 의존하여 직접 사용하는 방식으로 작동한다. MSA는 서비스 단위로 배포가 가능하여 독립배포가 가능하다, 통신은 HTTP 요청응답의 형식으로 통신하기 때문에 네트워크 지연, 실패가 단점이다.

질문 1 정석 답변 보기 모놀리식은 Product, Order, Stock, Payment 기능이 하나의 애플리케이션에 포함되며 전체가 하나의 배포 단위로 배포된다. 기능 간 통신은 같은 프로세스 안에서 Service 메서드 등을 직접 호출하는 방식으로 이루어진다. MSA에서는 각 서비스가 독립된 실행·배포 단위다. Payment만 변경했다면 Payment 서비스만 배포할 수 있다. 서비스가 서로 다른 프로세스에서 실행되므로 통신에는 HTTP API나 Kafka 이벤트 같은 네트워크 통신을 사용한다. 따라서 MSA에서는 네트워크 지연, 상대 서비스의 장애, 응답 유실 등을 추가로 고려해야 한다.

답변에 포함해야 할 키워드

질문 2. 서비스를 비즈니스 책임으로 나누어야 하는 이유는 무엇인가?

내 답변

잘 모르겠는데, 일단 현실적으로 조직간 책임 소재 파악도 가능할 수 있고, 너무 많이 나누게 되면 불필요하게 유지보수 요소가 늘어날수도 있다

질문 2 정석 답변 보기 서비스를 비즈니스 책임에 따라 나누면 서로 다른 규칙과 변경을 분리할 수 있다. 예를 들어 재고 차감과 복원 규칙은 함께 변경될 가능성이 높으므로 Stock 서비스가 담당한다. 결제 승인과 환불 규칙은 Payment 서비스가 담당한다. 이렇게 나누면 재고 규칙을 변경할 때 Payment까지 함께 수정하거나 배포할 가능성이 줄어든다. 또한 어떤 서비스가 특정 데이터와 규칙을 책임지는지 명확해진다. 다만 서비스를 지나치게 작게 나누면 서비스 간 통신과 배포 대상이 늘어나므로, 독립적으로 변경할 가치가 있는 책임을 기준으로 경계를 정해야 한다.

답변에 포함해야 할 키워드

질문 3. Order가 Stock DB를 직접 수정하는 설계의 문제를 세 가지 적어라.

내 답변

msa 설계 원칙을 어긋난다? 명확히 어떤 이유인지 잘 모르겠긴 하다. 책임분리를 위함도 있을 것이고 흠 ..

질문 3 정석 답변 보기 Order가 Stock DB를 직접 수정하면 다음과 같은 문제가 발생한다. 1. 데이터 소유권이 깨진다.
재고 데이터의 소유자는 Stock인데 Order도 재고를 변경할 수 있게 된다. 결국 재고의 정확성을 누가 책임지는지 불분명해진다. 2. Stock의 업무 규칙을 우회할 수 있다.
Stock에는 재고가 0보다 작아지지 않아야 한다는 규칙이나 동시성 처리 규칙이 있을 수 있다. Order가 SQL로 직접 수정하면 이러한 검증을 거치지 않을 수 있다. 3. DB 스키마에 강하게 결합된다.
Order가 Stock의 테이블명과 컬럼을 알고 있기 때문에 Stock이 스키마를 변경하면 Order도 함께 변경해야 한다. 따라서 두 서비스를 독립적으로 변경하고 배포하기 어려워진다. 그러므로 Order는 Stock DB를 직접 변경하지 않고 Stock 서비스의 API나 Kafka 이벤트를 통해 재고 처리를 요청해야 한다.

답변에 포함해야 할 키워드

질문 4. 주문 데이터에 주문 당시 상품 가격을 저장하는 것이 Product의 데이터 소유권을 반드시 침해하는가?

내 답변

해치지 않는다고 생각한다. 기술적인 애기는 잘 모르겠지만, 현실적으로 파악할때 특정 상품이 할인할때 구매하였고, 이를 환불하고자 한다면 이에 대한 데이터 관리를 product에서 모두 한다는것은 너무 불필요하게 복잡도가 늘어난다. 하지만 주문데이터에 로그형태로 그 당시 가격을 저장한다면, 복잡도가 불필요하게 증가하지 않고 환불과 같은 문제를 해결할 수 있다. 데이터소유권? 은 정확히 뭔지 모르겠다

질문 4 정석 답변 보기 주문 데이터에 주문 당시 상품 가격을 저장하는 것은 Product의 데이터 소유권을 반드시 침해하지 않는다. Product 서비스가 소유하는 현재 상품 가격과 Order가 소유하는 주문 당시 가격은 서로 다른 업무 사실이기 때문이다. 상품의 현재 가격이 나중에 변경되더라도 이미 완료된 주문의 결제 금액과 환불 금액은 주문 당시 가격을 기준으로 계산해야 한다. 따라서 Order는 주문이 생성되는 시점의 상품명과 가격을 스냅샷으로 저장할 수 있다. 이 값은 Product의 현재 가격을 대신 수정하기 위한 데이터가 아니라, 해당 주문이 성립했을 때의 사실을 보존하는 Order 데이터다. 데이터 소유권은 “어떤 서비스가 특정 데이터의 정확성과 변경 규칙을 책임지는가”를 의미한다. Product의 현재 가격을 변경할 권한은 Product에 있고, 주문 당시 가격을 관리할 권한은 Order에 있다.

답변에 포함해야 할 키워드

질문 5. 결제 트래픽만 급증한 상황에서 독립 확장의 이점을 설명하라.

내 답변

결제트래픽만 급증한다면 해당 인스턴스만 독립확장을 하여, 유기적이게 리소스를 관리할수 있다.

질문 5 정석 답변 보기 결제 트래픽만 급증했다면 Payment 서비스의 인스턴스만 추가할 수 있다. 모놀리식에서는 결제 트래픽만 증가해도 Product, Order, Stock, Payment가 모두 들어 있는 애플리케이션 전체를 복제해야 한다. 반면 MSA에서는 트래픽이 증가한 Payment만 부분적으로 확장할 수 있다. 따라서 트래픽이 증가하지 않은 서비스에 CPU와 메모리를 추가로 할당하지 않고, 필요한 곳에만 자원을 집중할 수 있다. 이것이 독립 확장의 이점이다.

답변에 포함해야 할 키워드

질문 6. 폴더와 모듈을 네 개로 나누었지만 하나의 DB를 모든 모듈이 자유롭게 사용한다. 왜 서비스 독립성이 낮은가?

내 답변

독립성이 낮은건 알겠는데 정확히 어떤이유라고 딱 잘라 말하기는 쉽지 않다. 흠 .. 일단 다시 등장하는 책임 관리.. 같은 DB를 공유한다면, 한 곳에서 문제가 생겼을떄 정확히 그부분이 문제라고 말하기 힘들수도 있을 것 같다.

질문 6 정석 답변 보기 폴더와 모듈을 네 개로 나누더라도 모든 모듈이 하나의 DB를 자유롭게 사용하면 각 모듈은 DB 구조를 통해 강하게 결합된다. 예를 들어 Order가 Stock 테이블을 직접 사용한다면 Stock이 테이블명이나 컬럼 구조를 변경할 때 Order도 함께 변경해야 한다. 하나의 기능을 배포하기 위해 여러 모듈의 코드를 동시에 수정하고 검증해야 할 수 있다. 또한 여러 모듈이 같은 데이터를 자유롭게 변경하면 해당 데이터의 규칙과 정확성을 누가 책임지는지 불분명해진다. 한 모듈이 다른 모듈의 검증 규칙을 우회하는 문제도 생길 수 있다. 따라서 폴더가 분리되었더라도 데이터, 변경 규칙, 배포 시점이 서로 묶여 있으므로 실질적인 서비스 독립성은 낮다.

답변에 포함해야 할 키워드

질문 7. 작은 쇼핑몰을 처음 만드는 2인 팀에 MSA가 과할 수 있는 이유를 설명하라.

내 답변

아무래도 대규모 트래픽에 유리한 구조인데 2인팀에 작은 쇼핑몰 정도 수준은 모놀리식 방식으로도 충분히 커버 가능하고, 특히 유지보수성에 있어서 2인팀은 굳이 복잡도를 늘려서 MSA 방식을 채택할이유는 없다.

질문 7 정석 답변 보기 작은 쇼핑몰을 만드는 2인 팀이라면 MSA가 해결해야 할 조직 규모나 트래픽 문제가 아직 크지 않을 가능성이 높다. 이 경우 잘 나눈 모놀리식으로도 충분히 개발하고 운영할 수 있다. MSA를 도입하면 여러 애플리케이션과 DB를 각각 배포하고 감시해야 한다. 서비스 간 네트워크 지연과 실패, 분산 로그 추적, 데이터 일관성, 이벤트 중복 처리 같은 문제도 추가된다. 따라서 얻을 수 있는 독립 배포와 확장의 이점보다 운영 비용과 분산 복잡성이 더 클 수 있다. MSA는 대규모 트래픽에만 사용하는 구조는 아니지만, 현재 문제 규모가 작다면 불필요하게 복잡한 선택이 될 수 있다.

답변에 포함해야 할 키워드

질문 8. “서비스는 작을수록 좋다”는 주장에 반박해 보라.

내 답변

서비스 단위로 각각의 서버를 가져야하는 MSA 구조라면 불필요하게 복잡도가 늘어날수 있다.

질문 8 정석 답변 보기 서비스를 작게 나눌수록 무조건 좋은 것은 아니다. 서비스를 하나 분리할 때마다 별도의 배포, 모니터링, 네트워크 통신, 장애 처리와 데이터 일관성 관리가 필요해진다. 서로 항상 함께 변경되는 기능을 별도 서비스로 나누면 기능 하나를 수정할 때마다 여러 서비스를 동시에 변경하고 배포해야 한다. 이 경우 독립성은 얻지 못하면서 분산 복잡성만 증가한다. 따라서 서비스의 크기 자체보다 해당 책임을 독립적으로 변경하고 배포할 가치가 있는지가 중요하다. 서비스 분리로 얻는 독립 변경의 이점이 경계와 운영 비용보다 클 때 분리하는 것이 적절하다.

답변에 포함해야 할 키워드

6. 상황 판단 문제

상황 1

Order 팀이 빠른 개발을 위해 Stock 테이블의 수량을 SQL로 직접 감소시켰다.

  1. 어떤 경계가 깨졌는가?
  2. Stock의 검증 규칙이 추가되면 어떤 문제가 생기는가?
  3. 어떤 방향으로 변경해야 하는가?

내 답변

       

상황 2

Product의 조회 요청이 10배 늘었지만 Payment와 Stock의 트래픽은 그대로다. 현재 시스템은 하나의 애플리케이션이다.

  1. 모놀리식 전체 확장에는 어떤 낭비가 있는가?
  2. MSA라면 무엇을 독립적으로 조정할 수 있는가?

내 답변

       

상황 3

서비스가 30개지만 한 명이 모든 서비스를 운영하며, 기능 하나를 배포할 때 20개를 함께 배포해야 한다.

  1. 이 구조가 독립 배포의 이점을 얻고 있는가?
  2. 서비스 경계가 적절한지 확인할 질문을 두 개 적어라.

내 답변

전혀 독립배포의 이점을 얻고 있지 않다. 기능이 함께 의존되어있는 다른 서비스들이 많다는 뜻이고,

7. 오늘의 용어 정리

용어내가 작성하는 정의
모놀리식
MSA
서비스 경계
데이터 소유권
결합도
독립 배포
독립 확장
배포 단위

8. 프로젝트에 한 줄 연결

9. 오늘의 자기 점검

10. 이해하지 못한 부분

     

11. 3문장 요약

12. 복습 퀴즈

  1. 모놀리식은 반드시 코드 품질이 낮다는 뜻인가?
  2. Stock 데이터의 직접 변경 권한을 가져야 하는 서비스는 무엇인가?
  3. Payment만 따로 인스턴스를 늘리는 성질을 무엇이라 하는가?
  4. MSA에서 서비스 간 메서드 호출이 네트워크 통신으로 바뀌면 새로 고려해야 할 대표 문제는 무엇인가?
  5. 작은 시스템에서 MSA 도입 전 가장 먼저 비교해야 할 것은 무엇인가?
복습 퀴즈 정답과 해설 보기
  1. 아니다. 모놀리식은 하나의 배포 단위라는 구조를 뜻하며 내부 모듈 경계를 잘 지킬 수 있다.
  2. Stock 서비스다. 자기 데이터와 변경 규칙을 소유한다.
  3. 독립 확장이다. 부하가 큰 서비스만 선택해 확장한다.
  4. 네트워크 실패와 지연이다. 프로세스 내부 호출과 달리 상대 서비스나 네트워크가 실패할 수 있다.
  5. 분리로 얻는 독립성의 이점과 분산 시스템의 운영 비용 중 어느 쪽이 큰지 비교해야 한다.

Share this post on:

Previous Post
product-stock
Next Post
EDA 기초