쿠팡의 MSA — Part 1

“행복을 찾기 위한 우리의 여정, 쿠팡의 MSA”에 대하여 2가지 주제를 가지고 설명한다.

  • Micro service architecture를 위한 쿠팡의 여정
  • Micro service architecture를 지탱하는 쿠팡 플랫폼 서비스
  1. Micro service architecture 를 위한 쿠팡의 여정

Background

2013년 쿠팡 서비스는 단 한 개의 서비스 안에 모든 컴포넌트가 존재하는 monolithic architecture로 구성되어 있었다. Monolithic architecture는 쿠팡의 빠른 성장을 뒷받침하기에는 한계를 가지고 있었을 뿐만 아니라 풀기 어려운 다양한 문제를 야기했다. 이를 해결하기 위하여 쿠팡은 monolithic architecture로 구성된 서비스를 micro service architecture로 전환하는 프로젝트를 진행하였다. 이러한 전환을 위하여 쿠팡이 취한 전략이 무엇이고, 그 과정에서 나타난 문제를 어떻게 풀어나갔는지에 대해 이야기 하고자 한다.

Coupang monolithic architecture

Monolithic architecture는 서비스의 모든 컴포넌트가 분리되지 않고, 한개의 서비스 안에서 동작하며, 각각의 컴포넌트는 강한 결합을 가지는 전통적인 아키텍처이다. 빠르고 쉽게 서비스를 구성할 수 있어 적은 비용으로 서비스를 출시할 수 있으며 고객의 피드백을 빠르게 받아 볼 수 있는 장점이 있다. 쿠팡 서비스의 시작도 monolithic architecture로 구성하여 성장하였다.

2013년 쿠팡은 Apache와 Tomcat으로 구성된 다수의 서버들로 구성된 단 하나의 서비스를 운영하고 있었다.

또한 아래와 같이 서비스를 구성하는 모든 component가 단 1개의 Git Repository에 존재하였다. 이는 monolithic architecture의 일반적인 모습이다.

이러한 monolithic architecture 에서는 서비스의 규모가 커지면서 발생하는 한계가 존재한다. 쿠팡의 사례를 통해 주요한 5가지 문제에 대하여 이야기하고자 한다.

Pain Point 1

부분의 장애가 전체의 서비스 장애로 확대되는 문제가 있다.

개발자가 잘못된 코드를 배포하거나, 트래픽 증가로 인하여 서비스 성능에 문제가 있을때, 서비스 전체의 장애로 확대되는 경우가 빈번히 발생하였다. 예를 들면, 아래와 같이 주문에서 메모리 누수를 일으키는 코드가 있다면 전체 서버의 메모리를 고갈시켜, 전면 장애로 이어진다.

Pain Point 2

monolithic architecture는 부분적인 Scale-out을 하기 어렵다.

이는 쿠팡 서비스가 하나의 서비스로 구성되어 있기 때문에 발생하는 문제로 반드시 서비스 전체에 대하여 scale-out을 해야만 했다. 비용이 발생하더라도 서버를 투입하여 scalability를 확보할 수 있다면 다행이지만, 어떤 병목 지점은 구조적인 문제로 전체적인 아키텍처를 개선하지 않는 한 해결하기 어려운 문제도 있다. 예를 들어 고객이 주문을 하게 되면 해당 상품의 재고와 가격을 확인해야 하고 이어서 결제와 배송 요청을 진행하는 등 매우 많은 일들이 한 개의 트랜잭션으로 진행된다. 이런 long transaction의 경우는 전체 서비스의 구조를 개선하지 않으면 scalability를 확보하기 어렵다.

Pain Point 3

여러 컴포넌트가 하나의 서비스에 강결합 형태로 되어 있어 서비스의 변경이 매우 어렵고, 수정시 장애 영향도를 파악하기 힘들다.

수십 개의 팀에서 공통적으로 사용하는 common-module이 있다면, 이 문제는 더욱 심각하다. 쿠팡은 다음과 같이 여러 컴포넌트에서 공통적으로 사용하는 모듈을 효과적으로 사용하기 관리하기 위하여 coupang-common module을 사용하였다. 시간이 흐르면서 coupang-common module은 점점 legacy화 되어, 특정 코드 블럭의 사용 여부를 확인하는 것이 점점 어려워져갔다. 한 개의 function을 수정하기 위하여 회사 전체로 메일을 보내 수정에 따른 영향도 여부를 판단해야 했고, 이 중 일부 팀들이 메일을 보지 않았다면, 해당 수정은 서비스 전체의 장애로 이어졌다. 이러한 이유로 기존의 function을 수정하지 않고, 그대로 복사하여 변경하는 경우가 빈번하여 기술 부채를 증가시켰다.

Pain Point 4

작은 변경에도 높은 수준의 테스트 비용이 발생한다.

쿠팡은 서비스의 안정성을 위해서 일부의 기능을 수정하고 배포할 때마다, Unit Test, Regression Test를 진행하는 프로세스를 가지고 있었다. 매우 작은 변경에도 이 프로세스는 항상 동일하게 적용이 되었는데 서비스의 코드가 많아지고, 테스트의 종류가 많아지면서 배포시 테스트의 비용도 매우 높은 수준으로 증가하였다.

Pain Point 5

Monolithic architecture에서 조직(개발자/팀)이 성장할수록, 배포의 대기 시간이 비약적으로 증가한다.

다수의 팀이 같은 git repository를 사용하는 상황에서, 배포 과정에서 의도하지 않은 코드 또는 테스트되지 않은 코드가 유입되는 것을 막기 위하여 아래와 같이 배포 깃발을 이용하였다. 오직 이 배포 깃발을 가진 팀만 코드를 수정하고, 배포를 진행할 수 있었다.

이러한 프로세스는 100명 미만의 개발자로 구성된 조직안에서는 잘 동작하였다. 그러나 그 당시 회사가 빠르게 성장함에 따라 우수한 개발자들을 많이 채용하였고, 수많은 feature들이 빠르게 개발되기 시작하자 배포 대기 시간이 폭발적으로 증가하였다. 하나의 서비스로 구성된 아키텍처로 인하여 한번에 배포를 할 수 있는 feature는 제한적일 수 밖에 없었다. 5분 정도 수정한 코드를 배포하기 위해 2~3일 정도 대기하는 경우도 종종 발생하였다.

다시 정리하면, 5년전 쿠팡은 monolithic architecture에서 다음과 같은 문제를 심각하게 겪고 있었다.

  1. 부분의 장애가 서비스 전체의 장애로 이어지는 경우가 종종 발생한다.
  2. 서비스가 부분적으로 scale-out을 하기가 매우 힘든 구조이다.
  3. 여러 컴포넌트가 하나의 서비스에 강결합 형태로 되어 있어 서비스의 변경이 매우 어렵고, 수정시 장애 영향도를 파악하기 힘들다.
  4. 작은 변경에도 높은 수준의 테스트 비용이 발생한다.
  5. 조직이 성장할수록 배포의 대기 시간이 비약적으로 증가한다.

빠르게 서비스가 성장하는 상황에서 기존의 monolithic architecture는 서비스의 성장을 막는 가장 큰 blocker로 작용하였다.

Coupang Micro-service Architecture

2013년 10월 쿠팡은 위에서 나열한 문제들을 해결하고, 서비스의 성장을 가속화하기 위하여 monolithic architecture를 micro service architecture로 전환하는 프로젝트를 진행하기로 결정하였다. 우리는 이 프로젝트를 Vitamin Project라 부른다. 이미 거대한 legacy system을 서비스 중단없이 빠르게 전환하기 위해 Coupang의 Platform 팀에서 다음과 같은 전략을 수립하였다.

Strategy 1 — Vitamin Framework의 개발

Vitamin Framework은 micro service architecture를 위한 Java 기반의 framework이다. Vitamin Framework은 쿠팡에서 개발한 다양한 표준 라이브러리와 함께, micro service architecture를 위한 표준 skeleton code template을 포함한다. 이 표준 skeleton code template에는 작은 도메인 단위의 front / api / batch / back-office 서비스를 쉽게 개발하기 위한 기본 코드들이 포함되어 있으며, 쿠팡에서 개발한 다양한 표준 라이브러리들도 쉽게 사용할 수 있도록 되어 있었다. 이렇게 구성된 서비스는 도메인팀에서 별다른 노력없이 테스트, 배포, 모니터링, 자동 복구가 가능하며, Message Queue, Cache 등 모든 platform 서비스와 쉽게 연동이 되었다. 즉 micro service architecture를 위하여 모든 도메인팀에서 공통적으로 발생하는 행위들을 기본으로 제공하여 자신의 Business Logic에만 집중할 수 있도록 하였다

이런 방식을 통하여 monolithic architecture로 구성된 legacy service를 빠르게 micro service architecture로 전환하는 작업을 시작하였다.

Strategy 2 — Provider helper library (api-adapter)

micro service architecture에서는 일반적으로 작은 도메인들이 restful API를 이용하여 상호 통신한다.

즉 특정 API를 사용하기 위하여 모든 client들은 HTTP 통신하는 모듈을 만들고, json 형태의 API를 호출한 뒤 Object로 매핑하는 로직을 구현하여야 한다. 만약 상품 API를 사용하는 도메인 서비스가 10개 있다면, 10개의 팀이 각자 이를 구현해야만 한다. 이런 낭비를 줄이기 위하여 쿠팡은 Provider helper library (api-adapter)를 같이 제공하여 API를 쉽게 사용할 수 있는 전략을 취하였다.

이렇게 특정 API version에 종속된 api-adapter 는 micro service architecture 환경에서 서비스가 점점 성장하여 복잡성이 증가될 때, 또 다른 형태의 monolithic system을 구성하게 하는 단점이 있지만, 빠르게 micro service architecture로 전환해야만 하는 쿠팡에서는 많은 도움이 되었다.

Strategy 3 — Message Queue를 이용한 Transaction 의 분리

monolithic architecture에서는 모든 component들이 강결합 형태로 존재한다. 예를들면 주문이 발생하면, 결제를 하고, 배송 요청을 하게 되는데, 이는 하나의 트랜잭션에서 강하게 결합되어 함께 처리된다.

이렇게 강결합된 형태의 트랜잭션들을 별개로 서비스로 분리하기란 쉽지 않다. 쿠팡은 이를 해결하기 위하여 Message Queue를 이용하여 트랜잭션을 분리하는 전략을 선택하였다. 주문이 발생하면 해당 주문에 대한 메시지(event)를 생성하여 배송 요청을 지시하고, 상품이 등록되면 상품 메시지(event)를 생성하여 검색에 신규 상품이 반영될 수 있도록 트랜잭션들을 분리하였다.

쿠팡은 도메인팀들이 Message Queue에 대하여 보다 안전하고, 편리하게 사용하도록 하기 위하여, message 단위의 트랜잭션을 지원하고, 장애로부터 완벽하게 자유로운 PaaS 형태의 Vitamin MQ라는 시스템을 구성하였다. 이를 이용하여 도메인팀들은 Message Queue의 운영에서 벗어나 비즈니스 도메인에 집중할 수 있도록 함으로써 빠르게 micro service architecture로 분리해 나갈 수 있었다.

Message Queue를 사용함으로써 얻는 또 하나의 큰 장점은 서비스 장애가 발생하더라도 event message가 consumer로 전달되는 것을 보장한다. 만약 Delivery 서비스가 장애가 나면 트랜잭션의 무결성을 보장하기 위하여 해당 event message들은 자동으로 Dead Letter Queue 로 전달되고 서비스가 정상복구되면 실패된 event message들을 재처리할 수 있도록 구성하였다.

In conclusion

이번 포스팅에서 쿠팡의 monolithic architecture 에서 경험한 문제와 micro service architecture로 전환하는 과정의 경험을 공유하였다. 그 과정에서 쿠팡은 다음과 같은 3가지 전략을 통하여 monolithic architecture에서 micro service architecture로 전환할 수 있었다.

  • Vitamin Framework
  • Provider helper library (api-adapter)
  • Message Queue

이를 통하여 쿠팡은 작은 서비스 단위로 개발 / 테스트 / 배포를 할 수 있어 비즈니스의 성장을 가속화할 수 있었고, 서비스의 확장성과 안정성을 적은 비용으로 빠르게 확보할 수 있었다.

Monolithic architecture에서는 서비스의 성장에 한계가 존재한다. 쿠팡과 같이 급격하게 성장하는 서비스 상황에서 비슷한 문제를 경험하고 있다면 micro service architecture는 선택이 아니라 필수라고 생각한다.

정재훈, Sr. Principal, Software Engineering

쿠팡 기술블로그 — Coupang Technology Blog

쿠팡 기술블로그 입니다. 쿠팡의 기술을 통한 혁신 스토리와 개발자 문화를 공유합니다.

Coupang technology blog Team

Written by

쿠팡 기술블로그팀 입니다.

쿠팡 기술블로그 — Coupang Technology Blog

쿠팡 기술블로그 입니다. 쿠팡의 기술을 통한 혁신 스토리와 개발자 문화를 공유합니다.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade