Project

모놀리식 아키텍처 ERP 프로젝트에서 Kafka 도입하기 1편

readyoun 2025. 1. 20. 23:25

 

간략 소개는 이전 포스트를 참고.

 

클라우드 SaaS 기반 ERP 시스템 개발 프로젝트 정리

*수정 중 (2025-01-13) GitHub - ready-oun/ERPSystem: Final project overviewFinal project overview. Contribute to ready-oun/ERPSystem development by creating an account on GitHub.github.com 구현 영상 YouTube 참조: https://tinyurl.com/omz-erp-youtu

readyoun.tistory.com


ERP 프로젝트는 처음 모놀리식 아키텍처로 시작했다.
모든 서비스가 하나의 애플리케이션에 통합된 상태였다.
그런데 전체 기능이 크게 72가지 정도가 되면서 서비스 분리 필요성을 느꼈다.

예를 들어, 인사관리 서비스에서 장애가 발생하면 회계, 물류, 생산 서비스까지 영향을 미쳤다.
새로운 기능 추가나 기존 코드 수정 시 의도치 않은 충돌이 발생했고, 이는 전체 서비스를 다운시켰다.

설정한 기준에 따라 성능 부하 테스트를 하면서 MSA로 분리했다.


처음에는 REST Client로 시도

진정한 독립은 아니었다...

 

처음에는 서비스를 인사/회계, 물류/생산, 공통 서비스로 나눠 REST Client를 통해 통신하도록 구현했다.

아직까지 서비스를 나누기만 하면 MSA 단계에 돌입하는 거라고 생각했을 때다.
하지만, MSA는 그런 게 아니었다.

 

출처: Team O`MZ

 

 

REST Client의 문제점

 

1. 높은 결합도

서비스가 동기적으로 작동하면서 여전히 서로 강하게 얽혀 있었다. 한 서비스가 응답을 지연하면 다른 서비스도 기다려야 했다.

예를 들어, 인사 서비스에서 응답이 지연되면 물류 서비스가 처리할 데이터를 받을 수 없었다.


2. 응답 지연과 병목현상
REST Client는 서비스 간 데이터 요청 및 응답이 반드시 완료되어야 하기 때문에, 트래픽이 몰릴 때 병목현상이 발생했다.

특히, 요청 체인이 길어질수록 지연 시간이 더 길어졌다.

 

3. 확장성의 한계
새로운 기능을 추가하거나 서비스를 확장할 때 기존 서비스와의 통신 로직을 수정해야 했다. 이는 시스템의 확장성을 제한했다.

 

서비스 분리만으로는 부족하다

서비스를 나누기만 하는 것은 진정한 MSA가 아니었다.

REST Client는 여전히 서비스 간에 강한 의존성을 남겼고, 이는 모놀리식 환경에서 발생했던 문제를 완전히 해결하지 못했다.


REST Client로 서비스를 호출하는 것은 마치 “몸만 독립했지만 정신적으로 독립하지 못한 상태”와 같았다.

자취만 한다고 해서 어른이 되는 게 아니라, 경제적으로 독립해야 어른이 된다는 것처럼 말이다.

진정한 독립을 위해서는 각 서비스가 자율적으로 데이터를 처리하고, 장애가 발생해도 다른 서비스에 영향을 주지 않아야 했다.

동기 호출 방식은 호출된 서비스가 응답을 줄 때까지 호출한 서비스가 대기해야 한다.
REST Client는 동기적으로 작동했으므로 다른 서비스와도 여전히 의존적이었다. 

결과적으로, 서비스 간 장애 전파와 병목현상의 원인이 되었다.
이를 해결하려면 비동기 호출 방식으로 전환해야 한다는 결론에 도달했다.


Kafka 도입: 비동기 메시징 시스템 구현

그래서 kafka를 도입했다.

Kafka란?

Kafka는 비동기 이벤트 기반 메시지 브로커로, 서비스 간 통신 방식을 근본적으로 바꾸는 기술이다.

서비스 간 직접적인 호출을 제거하고, 데이터를 이벤트로 주고받음으로써 결합도를 낮추고 확장성을 확보할 수 있었다.

REST Client 방식에서 발생했던 서비스 간 결합도와 병목현상을 해소하기에 적합한 기술이었다.

 

참고: [번역] kafka 

Kafka의 핵심 개념

출처: Team O`MZ - Kafka 메시지 브로커의 데이터 흐름 및 파티션 관리

1. Producer: 데이터를 생성하고 Kafka의 특정 토픽(Topic)에 게시하는 서비스
2. Consumer: Kafka 토픽을 구독하여 데이터를 소비하는 서비스
3. Broker: Kafka의 핵심 컴포넌트로, 데이터를 저장하고 파티션으로 분산 처리
4. Offset: Consumer가 처리한 메시지 위치를 기록하여 데이터의 중복 처리와 손실 방지

 

더보기

그림 설명

 

1. Kafka Broker 요청

Producer는 Kafka Broker에 연결하기 위해 Broker ID를 요청한다. Zookeeper가 Broker ID를 반환하여, Producer가 메시지를 보낼 대상 브로커를 알 수 있도록 한다. 

 

2. 메시지 전송 및 파티션 관리:

Producer는 특정 토픽(Topic)에 메시지를 전송하며, 메시지는 하나 이상의 파티션으로 분산된다.

 

Topic 1에는 Partition 1과 Partition 2가 있다. Partition 내에서 메시지는 순차적으로 저장되며, 각 메시지에는 고유한 Offset이 부여된다. 

예: Topic 1 → Partition 1 → Message 8

 

3. Offset 관리 및 소비:

Consumer는 특정 Topic과 Partition을 구독하며, Offset 정보를 사용해 어떤 메시지가 이미 처리되었는지 추적한다. Offset 업데이트를 통해 메시지 중복 소비를 방지하고, 장애 복구 시 마지막 처리된 메시지부터 다시 처리할 수 있다. 

 

중요 포인트

1. 파티션 구조는 Kafka의 핵심으로, 데이터 병렬 처리를 가능하게 하여 높은 처리량과 확장성을 제공한다. 

2. Offset 관리는 메시지의 신뢰성과 일관성을 보장하는 메커니즘이다. 

 

Kafka의 주요 장점

1. 서비스 간 결합도 감소

REST Client의 동기 호출 대신, Kafka는 데이터를 이벤트(Event)로 게시(Publish)하고, 필요한 서비스가 이를 구독(Subscribe)하도록 했다. 각 서비스는 데이터를 주고받으면서도 완전히 독립적으로 작동할 수 있었다.

 

2. 확장성 확보

Kafka는 데이터를 파티션 단위로 분산 처리하여 대규모 트래픽을 효율적으로 처리할 수 있었다.

또한, 리더-팔로워 복제 구조를 통해 데이터의 안정성과 가용성을 보장했다.

 

3. 데이터 손실 방지

Kafka는 Offset을 통해 Consumer가 데이터를 어디까지 처리했는지 추적하고, 중복 처리나 데이터 손실을 방지했다.

 


Kafka 적용

서비스 간 데이터 흐름 설계

출처: Team O`MZ - ERP 시스템에서 Kafka와 Change Data Capture(CDC) 기술을 활용한 데이터 흐름

 

Kafka 도입 후 서비스는 다음과 같이 설계된다.

 

1. Producer와 Consumer로 역할 분리
각 서비스는 데이터를 발행하거나 소비하는 독립적인 역할을 가지게 되었다.
예로, 인사 서비스가 직원 데이터 수정 이벤트를 발행하면, 물류 서비스와 공통 서비스가 이를 구독하여 필요한 데이터를 처리한다.


2. Broker를 통한 비동기 데이터 처리
Kafka Broker는 데이터를 여러 파티션으로 분산 저장해 병렬 처리를 가능하게 했다. 이는 트래픽 증가에도 안정적인 데이터 처리를 보장했다.

 

3. 장애 전파 방지
Kafka의 비동기 통신으로 인해 한 서비스의 장애가 다른 서비스로 전파되지 않았다.

 

더보기

그림 자세한 설명

 

1. RDS Aurora Serverless에서의 CDC

RDS Aurora에서 데이터 변경 사항(Change Data)이 감지되면, Kafka로 변경 이벤트가 전송된다. CDC를 통해 실시간 데이터 동기화가 이루어진다. 

 

2. Kafka와 서비스 간 데이터 흐름 

Kafka는 중앙 메시징 허브 역할을 하며, 각 서비스에 변경 데이터를 전달한다.

1) 회계 & 인사 서비스: 변경된 데이터를 수신(Consume)하여 데이터베이스를 업데이트한다. 

2) 물류 & 생산 서비스: 동일한 데이터를 수신하고 필요한 비즈니스 로직을 실행한다. 

3) 공통 서비스: 데이터 변경 내용을 반영하여 공통 데이터베이스를 최신 상태로 유지한다. 

 

3. API 및 Front-End:

모든 서비스는 API를 통해 데이터를 중앙 시스템과 동기화하며, 최종 데이터는 Front-End로 제공된다. 

 


Kafka가 가져온 변화

Kafka 도입은 단순히 기술적인 개선을 넘어, 시스템 아키텍처의 철학을 바꾸는 중요한 전환점이었다.

 

모놀리식 아키텍처의 한계를 극복하고, MSA의 본질인 독립적이고 자율적인 서비스 간 통신을 구현할 수 있었다.

REST Client 방식에서 발생했던 병목현상과 장애 전파 문제를 해결하며, 더 확장 가능하고 안정적인 시스템을 구축할 수 있었다.


2편에서는 Kafka를 기반으로 데이터를 처리하면서 발생했던 정합성 문제를 어떻게 해결했는지, Saga 패턴을 중심으로 살펴보겠다.