올리브영 테크블로그 포스팅 올리브영 온라인몰의 전시, 그리고 백엔드 여정
Display

올리브영 온라인몰의 전시, 그리고 백엔드 여정

feat. 올리브영 온라인몰 Home 신규 아키텍처 전환기

2023.10.17

안녕하세요. 올리브영 스토어전시 스쿼드에서 백엔드 개발을 하고 있는 복스뮤직 입니다.

올리브영 전시에도 여러 스쿼드가 존재하지만, 스토어전시는 주로 메인, 홈, 오특 등 GNB(Global Navigation Bar) 영역을 담당하여 개발을 진행하고 있습니다.

그 중 스토어전시 백엔드는 어떤 일을 어떻게 하고 있는지 최근에 진행했던 올리브영 온라인몰 Home 신규 아키텍처 전환을 통해 간략히 소개하고자 합니다!


Step 1. Why Monolithic to MSA?

  • 올리브영 전시는 최근 Monolithic 구조에서 벗어나 MSA 로 전환하기 위해 계속해서 노력하고 있습니다.

Monolithic 구조에서 MSA 로 전환한 이유는 크게 두 가지가 있습니다.


1️⃣ 서비스 중 특정 부분에 대한 Scale-out 이 어렵다.

이런 앱 리뷰를 보신적 있으신가요?

image

기존 올리브영의 서비스는 On-premise 환경에 상당 부분이 Monolithic Architecture 로 구성되어 있었습니다.

또한, On-premise 환경에서 가용할 수 있는 서버 증설은 거의 MAX 상태로 세일을 맞이했습니다.

가용할 수 있는 자원은 한정되어 있는데, 이런 리뷰들을 볼 때마다 굉장히 마음이 아팠습니다.

특히, 세일 마지막 날 주문&결제에 몰리는 트래픽에 죄 없는 홈 등딱지가 터지는 모습을 보며 속이 아려왔습니다.


2️⃣ 전체 시스템에 대한 구조 파악이 어렵다.

과거 메인페이지 성능 개선기를 비롯하여 Home 을 개선하기 위해 여러 시도했고, 개선 결과를 가시적으로 볼 수 있을 만큼 성과도 있었습니다.

참고) 올리브영 메인페이지 성능 개선기

하지만, 기능 개발 또는 리팩토링 진행 시 영향도 파악부터 통합테스트까지 N개월 이상의 기간이 소요 되기도 했습니다.

Monolithic 구조에서 디펜던시들이 얽혀 있는 홈의 구조를 변경한다는 것은 큰 부담으로 다가왔고, 작은 기능 변경에도 매번 불필요한 공수를 쏟아야 했습니다.


Monolithic to MSA 전환 비용에 대한 Trade off 가 반드시 존재하기도 하고, 전환 이후 Monolithic 으로의 회귀가 그리워 질 수 있습니다.

그러나, 올영 세일을 필두로 올리브영이 가지고 있는 비지니스는 MSA 전환이 반드시 필요했고,

더 나은 개발 품질을 위해서 MSA 전환은 더 이상 선택이 아니게 되었습니다.


Step 2. 어떤 데이터를 Serving 할까?

  • '어떻게 해야 더 좋을까?' 를 항상 고민합니다.

image1

기존 Home 은 좌측 그림처럼 여러 비지니스 로직이 조합되어 한 화면을 그려주고 있었습니다.

따라서, 특정 로직에서 지연이 발생하는 경우 Home 전체를 그려주지 못하게 되고, 이는 곧 좋지 않은 유저 경험으로 이어졌습니다.


신규 Home 은 우측 그림처럼 빠르게 보여줄 수 있는 정적 영역(Static Data), 그 외 여러 비지니스 로직이 조합되는 영역은 개인화 영역(Personal Data) 으로 두 가지 영역을 나누어 고민했습니다.


1️⃣ Static Data

Static Data 는 ‘모든’ 유저에게 동일하게 제공되는 데이터들의 집합입니다. 해당 데이터는 캐싱 데이터 조회 후 바로 서빙 할 수 있는 데이터로 구성했습니다.

어떠한 디펜던시도 갖지 않고, 모든 유저에게 동일하게 제공할 수 있는 데이터를 하나로 묶어둠으로써 최초 화면에 노출되는 영역은 최대한 빠르게 제공하기 위해 Static Area 를 구분하여 사용하고 있습니다.

참고) 올리브영 전시영역 MongoDB 도입하기 의 내용을 바탕으로 Data 조회 → Validation check → Versioning 등의 단계를 거쳐 최종 캐싱 데이터를 생성합니다.


2️⃣ Personal Data

Personal Data 는 ‘특정’ 유저에게 차별되어 제공되는 데이터들의 집합입니다. 해당 데이터는 각 유저 마다 다르게 서빙 되어야 하는 데이터로 구성되어 있습니다.

Static Data 와 다르게 각 유저에 맞는 데이터를 서빙 하기 위해 비지니스 로직이 들어가거나, 여러 시스템간의 디펜던시를 가지고 있기 때문에 API 응답속도를 항상 보장하지 못할 수 있습니다. 따라서 이러한 영역은 별도의 API 로 관리하고 있습니다.

참고) 신규 전시 프로젝트에서 WebClient 사용하기 와 더불어 multiple call을 위한 zip, parallel 사용과 여러 fallback 로직들로 구성되어 있습니다.

image2

Personal Data & Static Data 의 평균 API 응답 속도입니다.

의도한 것처럼 올리브영 앱에서 Home 을 더 빠르게 고객에게 노출 할 수 있었습니다.


Step 3. Static Area 는 하나의 API 로 묶어야 할까?

  • 모든 의사결정은 데이터로 시작하고, 데이터로 판단합니다.

‘Static Area API 를 분리해야 할 이유는 없을까?’


Personal Data 는 성격에 맞게 API 를 분리하여 서빙하고 있습니다. 동일하게 ‘Static Data 는 API 분리를 할 필요가 없을까?’ 라는 의문을 가지게 되었습니다.

Static Data 는 하나의 API 로 제공 하더라도 응답속도를 보장할 수 있었기 때문에, 명확한 근거가 없다면 분리하지 않아도 무관했습니다.


저희가 목표로 하는 올영세일유저 패턴을 보면 아래와 같습니다.
(평시를 고려하면 어떤 방법으로 처리해도 문제가 발생하지 않습니다.)


  1. 세일 첫날 00시에 홈으로 유입되는 유저는 대량 트래픽을 유발하지만, 홈 하단으로 이동하지 않고, 대부분 쿠폰 발급을 위한 기획전 페이지로 이동한다.
  2. 세일 마지막 날 발생하는 대량 트래픽은 홈이 아닌 ‘구매’ 를 위한 상품 상세 또는 주문페이지이다.
  3. GNB 홈을 4등분 했을 때 하단 스크롤을 내리는 유저 비율은 생각했던 것 보다 저조하다.
    1. depth 50% > 74%,
    2. depth 75% > 18%
    3. depth 100% > 9%
  4. Static Area 데이터는 약 300kb로 구성되어 있다. 최초 고객에게 노출하는 영역만 분리했을 경우 약 3% 의 비용만 사용하면 된다. 또한, 불필요한 데이터로 인한 네트워크, 파싱 비용 등을 감소시킬 수 있다.

이를 정리하면 다음과 같은 결론을 얻을 수 있습니다.


  • 홈의 하단 영역을 보는 사용자는 충분히 적다.
  • 대량의 트래픽이 들어오는 시간에 홈은 Navigation 역할을 수행한다.

즉, 홈 하단을 유저가 탐색하지 않는다면 하단 영역은 불필요한 데이터가 되고, Static Data API 를 분리해야할 명확한 근거가 되었습니다. 저희는 즉시 개선을 진행했고, 개선 결과는 부하테스트를 통해 유의미한 개선임을 확인할 수 있었습니다.


네트워크, 외부 저장소, API call count 뿐만 아니라 유저의 패턴에 따라 더 좋은 서비스 제공을 위한 노력이기 때문에 더 기억에 남습니다. 이후에도 Json gzip 압축 등 여러 기능이 보완되어 더 나은 서비스를 위해 나아가고 있습니다.


Step 4. 장애 전파 방지(CircuitBreaker)

  • 언제라도 안정된 서비스를 제공하기 위해 노력합니다.

올리브영 홈은 Redis, Mongo DB, Oracle, 외부 서비스 등 여러가지 시스템이 조합되어 있습니다. 특정 시스템의 단순 지연은 Application 전체 Hang 을 유발 할 수 있습니다. 또한, 특정 저장소 또는 외부 서비스의 장애는 곧바로 고객에게 Home 을 노출하지 못하는 장애로 이어지게 됩니다.


‘어떠한 환경에서도 Home 은 노출되어야 한다’
(아직 Monolithic 이 곳곳에 존재하지만)


Home 은 어떠한 환경에서도 노출되어야 함을 원칙으로 가져가고 있습니다.

올영 세일은 항상 경험하지 못한 새로운 문제를 발생 시킵니다. 하나의 혈이 뚫리면 다른 혈이 막혀버리는 재밌는 모습을 볼 수 있습니다. 따라서, 어떤 데이터 레이어가 죽을지, 외부 시스템의 지연 혹은 장애에 대해서도 항상 고려해야만 합니다. Home 은 발생 가능한 모든 시나리오를 고려하여 어떠한 서비스가 다운 되더라도 유저 레벨에서 인지할 수 없도록 fallback 로직이 2~3차 까지 준비 되어 있습니다. 또한, 스트레스 테스트 결과를 통해 CircuitBreaker 임계치도 시스템 상태에 맞게 가져가고 실제 검증까지 진행하고 있습니다.


  • CircuitBreaker 의 기본 플로우는 아래와 같습니다.

(자세한 설명은 Circuitbreaker를 사용한 장애 전파 방지 에서 확인할 수 있습니다!)

image3 alter
  • 홈에서 사용하고 있는 CircuitBreaker 로직 중 하나 입니다.

각 저장소가 fallback으로 묶여있고, 임계치 중 하나인 지연시간과 그에 맞는 Scale-out 은 모두 부하테스트를 근거로 적용되어 있습니다.


image4 alter
  • Circuit Breaker 에 대한 테스트 코드 중 하나 입니다.

주요 로직들에 대해서는 테스트 코드를 통해서 안정성을 지향하고 있습니다.


image5

또한, Circuit Status 변경 시 Slack 알람으로 받고, 대응할 수 있도록 구성해 두었습니다.


image6

Step 5. 세일을 대비 하기 위한 부하테스트

  • 발생할 수 있는 모든 예외를 생각하고 움직입니다.

목표는 단 한 순간 입니다.

‘올영 세일 1일차 23시 55분 ~ 00시 05분’

이 순간을 버틴다면, 올영 세일 기간을 모두 버틸 수 있다고 할 수 있습니다.

image

동네방네 광고를 하고 9월 세일을 맞이 하기 위한 Scale-out을 해야했기에 부하테스트를 진행합니다.


image7 alter

Env 를 구성하고, Goal 을 설정한 뒤, 각 자원들에 대해 Home이 ‘올영 세일 1일차 23시 55분 ~ 00시 05분’ 에 어떻게 버틸 수 있을지 아래의 케이스를 모두 정리하였습니다.


  • 공용으로 사용하는 Redis 에 대해 Home 영역 부하 시 발생 가능한 시나리오
  • fallback 로직들이 처리 될 때 Oracle Connection 처리량
  • Redis, Mongo, Oracle, 외부 시스템 관점에서의 Home 부하 및 대응 방법
  • CircuitBreaker 임계치 설정
  • fallback 로직들이 동작하기 위한 Scale-out 수치
  • …..

최초 부하 테스트로 시작했지만, 이 모든 것을 정리하니 성능, 부하, 스트레스 테스트로 마무리 되었습니다.

아키텍처 전환 이후 처음으로 맞이하는 세일이기 때문에 최선을 다해서 준비했습니다.

생각보다 만족할만큼의 결과를 얻을 수 있었고, 예상할 수 있는 예외 상황들에 대한 모든 준비를 끝냈습니다.


올영 세일 1일차 -

모든 케이스에 대한 시나리오를 정리해 대응할 수 있는 환경을 만들고, 스쿼드 내 개발자들이 모두 사무실에 남아 올영 세일 첫 날을 준비했습니다.

그러나 세상은 호락호락 하지 않았습니다.

하나의 혈이 뚫리니 뚫려있던 혈이 막혀버렸습니다..


마치며,

사실 많은 부분이 개선이 됐고, 의미있는 과정과 좋은 결과들이 많았던 신규 아키텍처 전환 및 9월 세일 이었습니다.
그 중 준비했던 Step 들을 통해 얻은 가장 두드러진 결과물인 6월과 9월의 응답 시간 비교입니다.


image8
  • 6월 대비 평균 응답 속도 시간
    • ((10380 + 10430) - (92.66 + 11.53)) / (10380 + 10430) = 99.5% 속도 향상
  • 6월 대비 최대 응답 속도 시간
    • ((33500 + 33600) - (105 + 15)) / (33500 + 33600) 로 = 99.8% 속도 향상

신규 아키텍처 전환기를 모두 다 쓰니 이 또한 legacy 가 되었습니다.

어제의 개발이 legacy가 되며 이 또한 작은 Monolithic이 되는 것을 방지하기 위해 항상 노력 중입니다.

올리브영 온라인몰은 고객에게 더 유익한 가치를 제공하기 위해 어제보다 더 나은 내일로 나아가고 있으니 많은 관심 부탁드립니다.

displayhomebackend
올리브영 테크 블로그 작성 올리브영 온라인몰의 전시, 그리고 백엔드 여정
🎵
복스뮤직 |
Back-end Engineer
안녕하세요!! 항상 흥얼흥얼거리는 백엔드 신입 개발자입니다.