안녕하세요. 저는 배민서비스개발실에서 웹어플리케이션 서버를 개발하는 강홍구입니다.
이 글에서는 배달의민족 앱에서 사용되는 여러가지 설정값들을 관리하기 위한 리모트 컨피그 서버를 구축한 내용에 대해 공유 하고자 합니다.

왜 리모트 컨피그 서버가 필요했을까?

브라우저에서 동작하는 웹어플리케이션은 서비스를 사용하는 사용자들이 별도의 어플리케이션 설치가 필요하지 않기 때문에 배포에 대해 자유로운 편입니다.
그러나, 사용자들이 직접 설치를 하여 사용하는 어플리케이션(안드로이드앱, IOS앱)은 사용자가 업데이트를 하지 않으면 새로운 기능에 대한 업데이트가 되지 않으니 웹 어플리케이션보다 배포에 있어서 자유롭지 않습니다.

배달의민족 어플리케이션은 서비스를 사용하는 회원정보, 사장님들의 업소정보, 주문정보, 결제정보 등 여러가지 정보를 다양한 API의 호출을 통해서 동작됩니다. 따라서 API가 업데이트 되면, 새로운 기능을 사용하기 위해 어플리케이션의 업데이트가 필요하게 됩니다.

앞서 말씀드린것 처럼 안드로이드/IOS앱은 사용자가 업데이트를 하지 않으면, 새로운 버전의 어플리케이션을 사용할 수 없기 때문에 사용자에게 강제 업데이트를 하도록 유도해야합니다.
이러한 강제 업데이트는 사용자에게 좋지 않은 경험을 제공하고, 잦은 업데이트는 사용자로 하여금 해당 서비스가 불안정하다는 오해를 가지게 하기 쉽습니다.

이러한 이유로 안드로이드/IOS 진영에서는 외부의 설정값들을 앱배포(재설치) 없이 관리할 수 있는 서버를 구축하여 사용하는 방식을 많이 고민하고 있습니다. (파이어베이스-리모트컨피그)

이렇게 외부의 서버에서 별도로 설정값들을 관리하여, 앱에서 사용하는 API 정보 및 다양한 설정정보를 관리하는 서버를 리모트 컨피그 서버라고 합니다.

직접 리모트 컨피그 서버를 구축한 이유

외부에 설정 정보를 저장해두고 서빙해주는 여러 훌륭한 솔류션들이 이미 많이 존재하고 있습니다. 그러나 저희 배달의민족앱에서 사용하는 리모트 컨피그 서버는 아주 간단한 아키텍쳐 로 새롭게 구축하게 되었는데요. 이미 잘 되어있는 솔루션을 사용하지 않고 새롭게 서버를 구축한 이유에 대해서 설명하고자 합니다.(사실은 대단한 기술을 공유하는 것은 아니지만 이 글을 용기내어 쓰는 이유이기도 합니다.)

이미 유사한 성격으로 구축되어진 서버가 있었습니다.

리모트 컨피그 서버를 새롭게 구축하기로 결정한 가장 큰 이유는 이미 거의 유사한 성격으로 구축되어진 환경이 있었습니다. 주문시스템에서 토글링 기능을 관리하고자 DB에 토글링 값을 저장해두고, 클라이언트 모듈을 이용하여 저장된 데이터를 일정 주기로 폴링하여 자바 힙 메모리 영역에서 저장해두고 특정 기능에 대한 토글링을 하는 환경이 이미 구축되어 있었습니다.

이 환경을 조금만 고쳐서 배달의민족앱에서 사용하는 여러 설정 정보들을 모아 하나의 JSON으로 내려줄 수 만 있다면, 리모트 컨피그 환경을 빠르게 구축할 수 있다고 판단되었습니다.

관리 포인트를 단순화 하고 싶었습니다.

배달의민족앱 실행시 외부에 설정해둔 정보들을 기반으로 앱이 동작하기 때문에 리모트 컨피그 서버가 정상적으로 동작하지 않는다면, 배달의민족앱은 정상적으로 동작하지 않게 됩니다.(물론 이런상황에 대비해서 앱개발쪽에서는 상황에 맞는 대비를 하고 있습니다.)

배달의민족앱이 정상동작 되지 않는다면 배달의민족이 제공하는 어떠한 서비스도 정상적으로 이용이 불가능하기 때문에 장애상황이 발생했을때, 최대한 빠르게 이슈를 파악하고 대응을 할 수 있어야 합니다. 이러한 이유로 리모트 컨피그 서버는 최대한 저희들이 잘 사용할 수 있는 기술 로 구성되어 있고, 아주아주 간단한 아키텍쳐 로 구성하여 관리 포인트를 최대한 단순화 하고 싶었습니다.

리모트 컨피그 서버 아키텍쳐

계속해서 굵은글씨 로 리모트 컨피그서버는 아주아주아주 간단한 아키텍쳐 로 구성되었다고 말씀을 드렸는데요. 리모트 컨피그 서버는 아래와 같은 간단한 폴링 구조를 선택하였습니다.

전체 구성도

리모트 컨피그 서버의 전체적인 아키텍쳐는 아래와 같이 구성되어 있습니다.

리모트 컨피그 전체 아키텍쳐

리모트 컨피그 전체 아키텍쳐


서버명 역할
운영툴 서버(baemin-config-admin) 설정정보 관리를 위한 값들을 조회 및 수정/등록
인터널 서버(baemin-config-server) 익스터널 서버가 URL 정보를 polling 해갈 수 있는 API를 제공
익스터널 서버(baemin-config-client-server, baemin-config-client) 인터널 서버로부터 URL 정보를 일정주기로 폴링 하여 인메모리에 저장


어드민 서버(baemin-config-admnin)를 통해 RDB에 데이터를 저장하게 되고, 인터널 서버(baemin-config-server)는 특정 그룹의 데이터를 조회할 수 있는 API END-POINT를 제공합니다. 클라이언트 모듈(baemin-config-client)은 일정 주기로 인터널 서버를 호출하여 자바 힙 메모리에 데이터를 저장하고 있고 익스터널 서버(baemin-config-client-server)는 설정 정보를 모아 JSON 형태로 응답하는 API END-POINT를 제공합니다.

모듈 구성도

위의 전체구성도에서 보시는것 처럼 리모트 컨피그 서버를 구성하는 서버는 총 3개의 서버군으로 구성이 되어 있으며 각각의 서버를 구성하는 모듈은 아래와 같이 5개로 이루어져 있습니다.

리모트 컨피그 모듈 아키텍쳐

리모트 컨피그 모듈 아키텍쳐


각 모듈들은 아래와 같은 역할을 담당하고 있습니다.

모듈명 역할
baemin-config-domain JPA 엔티티 관리 및 repository 레이어와 통신
baemin-config-admin 운영툴 모듈
baemin-config-server config-client 모듈과 통신하는 서버 (폴링 API 제공)
baemin-config-client config-server 와 통신하는 클라이언트 모듈
baemin-config-client-server config-client 모듈을 이용하여 앱에 정제된 데이터를 내려주는 서버


이러한 역할을 하는 모듈들은 아래와 같은 협력을 통해서 빌드가 되어 서버를 구성하게 됩니다.

  • 운영툴 빌드 : config-domain 모듈과 config-admin 모듈을 빌드
  • 인터널 서버 빌드 : config-domain 모듈과 config-server 모듈을 빌드
  • 익스터널 서버 빌드 : config-client 모듈과 config-client-sever 모듈을 빌드

이렇게 구축된 리포트 컨피그 서버를 이용해서 배달의민족앱에서 사용하는 다양한 설정 정보들을 모아서 내려주고 있습니다.

결론

리모트 컨피그 서버 구축은 제가 우아한형제들에 합류하고 거의 처음으로 담당하게된 프로젝트입니다.

처음 프로젝트를 이러한 방향으로 결정한 부분에 대해 의아한 부분들이 많았습니다. 이미 더 나은 솔루션이 있는데 이를 활용하는것이 좋지 않을까? 이벤트 기반으로 설계를 했다면 설정 정보들이 보다 빨리 반영되지 않을까? 등등 고전적인 폴링 구조를 선택한 이유가 의아했었습니다.

이러한 부분에 대해서 팀장님께서는 (돌이켜 생각해보면 아주 young한 명석한 결정이 었다고 생각되어 집니다.) 글의 서두에서 이미 말씀드린 부분(이미 구축된 환경의 재활용, 관리 포인트의 최소화)에 대해 말씀해주셨습니다.

설정값 변경이 즉시 반영되는 이벤트 기반의 구조도 아니고, 외부에 캐시를 두고 사용하는 것이 아닌 인메모리 캐시를 이용하는 아주 고전적인 폴링을 이용하는 아키텍쳐로 이루어진 환경이지만, 이렇게 단순한 환경으로 구축함으로써 환경구축 이후로 특별한 리소스가 투여되지 않고 잘 유지되고 있습니다.

대단한 기술적공유는 아니지만, 어떠한 시스템을 설계할때 이러한 부분(주어진 환경과 상황에 적합한 설계)들을 고려해보는 경험을 공유해드리면 좋지 않을까 하여 부족하지만 글을 쓰게 되었습니다.