요약: 카카오페이는 서비스 안정성 향상을 위해 오픈소스 MockServer 기반의 사내 공통 목 서버를 개발했습니다. 이 목 서버는 독립적인 테스트 환경 제공, 외부 서비스 의존성 최소화 등의 기능을 통해 개발 및 테스트 효율성을 높였으며, 현재 29개 조직에서 72개의 목 서버를 사용 중입니다.
💡 리뷰어 한줄평
edward.lim 카카오 페이에서 개발하는 서비스를 쉽게 테스트하기 위해 공용 목서버를 어떻게 제공했는지 잘 정리한 글입니다. 재밌게 읽어주세요! :)
katfun.joy 개발자로서 공용 목서버 덕분에 편리하게 서비스를 테스트하고 있습니다. 목 서버에 대해 잘 모르셨다면, 아리의 글을 추천드립니다!
시작하며
안녕하세요, 카카오페이 SRE팀 RE파트 아리입니다.
오늘은 카카오페이에서 사내 공통 목서버를 만들고 제공한 경험을 공유하려고 합니다. 구체적인 경험을 공유하기에 앞서 어떠한 배경과 목표로 사내 공통 목서버를 만들게 됐는지 말씀드리겠습니다. 소프트웨어를 개발할 때 우리는 테스트가 중요하다고 항상 강조합니다. 특히 마이크로서비스 아키텍처를 기반으로 하는 대규모 플랫폼에서는 더욱 그렇습니다. 카카오페이도 마찬가지입니다.
카카오페이는 수많은 마이크로서비스와 외부 서비스에 의존하고 있으며, 서비스 안정성을 높이려면 효율적인 테스트 환경을 구축해야 합니다. 이러한 중요성을 인지하여 지난해 카카오페이는 서비스 안정성 향상을 최우선 과제로 삼았습니다. 이 과정에서 테스트의 중요성을 다시 한번 인식했고, 특히 목 테스트를 편리하게 할 수 있는 방법을 고민하게 됐습니다. 이를 위해 사내 공통 목서버 개발을 목표로 설정했습니다. 현재 환경에서 개발자가 느끼는 불편함을 해소하고, 목 테스트를 보다 효율적으로 수행할 수 있게 돕고자 했습니다.
목 서버(Mock Server)란 실제 서비스를 모방하여 미리 정의된 응답을 제공하는 가상의 서버를 말합니다. 이는 실제 서비스와의 의존성을 제거하고 독립적인 테스트 환경을 구축하는 데 도움이 됩니다.
개발자 인터뷰
프로젝트를 시작하기 앞서, 개발자들과의 인터뷰를 통해 현재 상황과 필요한 기능을 파악했습니다. 다음은 개발자들과의 인터뷰 내용입니다.
- 🙋♀️ 개발자 A: 우리 회사는 여러 마이크로서비스들이 서로 의존성을 가지고 있어요. 만약 A라는 서비스의 테스트용 서버가 점검 등의 이유로 내려가면, 그 서비스를 바라보고 있는 다른 서비스들은 테스트를 진행할 수 없어 마냥 기다려야 해요.
- 🙍♂️ 개발자 B: 다양한 외부 서비스들과 연동하는 기능을 개발하고 있어요. 그런데 테스트를 하려고 할 때마다 항상 그쪽의 협조가 필요해요. 커뮤니케이션에만 며칠이 소요되는 경우도 있죠. 서비스 특성상 어쩔 수 없지만, 그 외부 서비스들의 목이 있으면 좋겠어요.
- 💁 개발자 C: 지금까지 목 테스트라고 하면 대부분 로컬 환경에서 진행했어요. 예를 들어 Postman이나 테스트 코드 등을 사용해서요. 하지만 별도의 목 서버가 있어서 테스트용 애플리케이션 등에서 연동해 전체 플로우를 볼 수 있으면 좋겠어요.
이러한 개발자들의 의견을 바탕으로, 아래와 같이 공통 목 서버 프로젝트의 방향성을 결정했습니다.
- 독립적인 테스트 환경 제공: 공통 목 서버는 외부 서비스의 점검 여부와 관계없이 독립적인 테스트 환경을 제공하여 개발자들이 테스트를 지속할 수 있게 합니다.
- 외부 서비스 의존성 최소화: 공통 목 서버를 통해 외부 서비스의 의존성을 줄이고, 개발자들이 자체적으로 목 서버를 생성하여 필요한 테스트를 수행할 수 있도록 지원합니다.
- 전체 플로우 테스트 가능: API를 통합적으로 관리하며 전체 플로우를 테스트할 수 있는 환경을 제공하여 로컬 환경에서의 제약을 해소합니다.
- 사용자 맞춤형 개발 지원: API 추가 및 관리, 동적 응답 생성 등의 기능을 통해 개발자들이 필요에 맞게 목 서버를 설정하고 활용할 수 있도록 지원합니다.
사내 공통 목서버 소개
Don’t reinvent the wheel
바퀴를 다시 발명하지 말라는 유명한 격언이 있습니다. 이미 잘 작동하고 검증된 해결책이 존재할 때, 그 문제를 처음부터 다시 해결하려고 하지 말라는 의미인데요. 저희도 제한된 리소스와 시간 속에서 효율적으로 개발을 하기 위해, 이미 잘 만들어진 솔루션을 활용하기로 결정했습니다.
여러 가지 조사와 테스트 끝에 MockServer라는 오픈소스를 선택했습니다. MockServer를 선택한 이유는 다음과 같습니다.
- 안정성: 수많은 사용자에 의해 검증된 솔루션으로, 안정성과 신뢰성이 보장됐습니다.
- 기능성: 사내에서 요구로 하는 기능을 대부분 충족하고 있었습니다.
- 확장성: 오픈소스이기 때문에 필요에 따라 커스터마이징이 가능하고, 다양한 REST API가 제공되고 있었습니다.
추가로 사용자 편의성을 높이고, 안정적인 운영을 위한 아래와 같은 기능들을 개발했습니다:
- 사용자 친화적인 UI 개발: 직관적이고 사용하기 쉬운 UI를 추가하여 누구나 쉽게 사용할 수 있도록 했습니다. 목 API, 목 서비스별로 메모를 남길 수 있고, Postman처럼 UI로 쉽게 API를 추가, 편집, 삭제할 수 있는 기능을 포함했습니다.
- 모니터링 기능: API 호출 로그와 서버 상태를 실시간으로 모니터링할 수 있는 기능을 추가했습니다. 이를 통해 사용자가 언제 많이 사용하는지, 어떤 기능을 가장 많이 사용하는지, 어떤 부서에서 가장 많이 사용하는지 등을 파악할 수 있었습니다. 또한 모니터링 결과를 바탕으로 개발 방향성을 정하여, 사용자 요구에 맞춘 기능을 우선적으로 개발할 수 있었습니다.
- 백업 및 복구 정책: 목서버에 변경이 일어날 때마다 자동으로 백업하고, 필요시 쉽게 복구할 수 있는 구조를 마련했습니다.
아키텍처
사내 공통 목서버는 크게 웹 서버, API 서버, 데이터베이스(MySQL), ELK, 목서버, 백업 이벤트로 구성되어 있습니다.
먼저 웹 서버와 API 서버는 사용자가 접근하는 웹 인터페이스와 API 엔드포인트를 제공합니다. 이 서버들은 데이터베이스와 ELK에 연결되어 있습니다. 데이터베이스는 주로 사용 팀, 서비스, 메모 등의 데이터 저장에 사용되며, ELK는 사용자 로그를 저장하고 검색, 분석하는 데 사용하고 있습니다.
목서버는 서비스의 안정성을 강화하고 성능 테스트로 인한 영향을 최소화하기 위해 공용 목서버와 성능 테스트용 목서버를 분리하여 운영하고 있습니다. 자세한 이유는 다음과 같습니다.
- 서비스 안정성 유지: 공용 목서버는 다양한 팀이 공통으로 사용하는 목적으로 활용되며, 각 팀의 개발 및 테스트 활동을 지원합니다. 공용 목서버는 유저 로그를 상세히 남기도록 설정되어 있어, 사용자 행동 및 오류를 면밀히 추적하고 분석할 수 있습니다. 이를 통해 문제 발생 시 빠른 원인 파악과 해결이 가능하여, 서비스의 안정성을 높이는 데 큰 도움이 됩니다. 비록 실제 운영 환경과 완전히 동일하지는 않지만, 공용 목서버는 다양한 시나리오를 테스트할 수 있는 유연한 환경을 제공합니다.
- 성능 테스트로 인한 영향을 최소화: 성능 테스트용 목서버는 대규모 트래픽 시뮬레이션 및 부하 테스트에 집중하도록 최적화되어 있습니다. 성능 테스트의 목적에 맞춰 유저 로그 기록을 최소화하여, 로그로 인한 성능 저하를 방지하고 테스트 결과의 정확성을 높였습니다. 이러한 설정 차이를 통해 성능 테스트 과정에서 발생할 수 있는 과부하나 기타 장애가 공용 목서버에 미치는 영향을 최소화할 수 있었습니다. 성능 테스트용 목서버는 극한의 부하 상황을 시뮬레이션하고, 시스템의 최대 처리 능력을 측정하여, 서비스의 확장성과 신뢰성을 검증하는 데 중요한 역할을 합니다.
마지막으로 안정적으로 운영을 하기 위한 백업 배치와 모니터링 시스템이 구성되어 있습니다. 백업 배치는 이벤트에 의해 주기적으로 트리거 되어 데이터베이스와 목서버의 데이터를 백업하고 있습니다. 모니터링은 프로메테우스와 그라파나로하고 있습니다. 각 서버에 모니터링 에이전트를 설치하고, 그라파나로 모니터링하며 특정 수치들이 임계값을 넘어가면 자동으로 복구를 위한 액션을 하고 알림을 보내도록 구성되어 있습니다.
기능소개
1. 홈 화면
홈 화면에서는 목 서버를 사용하는 조직 수와 생성된 서비스 수를 한눈에 확인할 수 있습니다. 또한, 팀별로 목 서버 목록을 쉽게 확인하고 이동할 수 있습니다.
2. 용도 별 목서버 운영
기본적인 기능 확인을 위한 공용 목 서버와 성능 테스트를 위한 별도의 목 서버를 운영하여 안정성을 보장하고 있습니다. 데이터베이스 구조에 비유하자면, 공용 목 서버는 프라이머리 서버(읽기/쓰기), 성능 테스트용 목 서버는 레플리카(읽기 전용)와 유사한 역할을 하고 있습니다.
이 페이지에서는 쉽게 서비스를 추가하고 삭제할 수 있으며, 다른 팀이 생성해 둔 목 서버도 쉽게 찾아 사용할 수 있습니다.
3. API 관리
API를 쉽게 추가, 편집, 삭제할 수 있는 기능을 제공합니다. 개발자들의 요청에 따라 API 내보내기 기능과 메모 기능도 추가되었습니다. 메모 기능은 동일한 경로에서도 다른 응답이 필요하거나, 샘플 데이터를 넣을 때 유용하게 사용됩니다.
4. 친숙한 UI/UX
API 추가 페이지는 Postman과 유사한 UI로 설계되어, 개발자들이 쉽게 사용할 수 있습니다. 실제로 많은 개발자들이 이 UI를 통해 편리하게 API를 추가할 수 있다고 피드백을 주었습니다.
단순히 정해진 응답만을 제공하는 것이 아닌 다양한 기능을 지원합니다:
- 레이턴시 설정: 응답 지연 시간을 설정하여 실제 서비스와 유사한 환경을 시뮬레이션합니다.
- 동적 응답 생성: 요청에 따라 다양한 응답을 동적으로 생성할 수 있어, 더욱 실제적인 테스트 환경을 구현할 수 있습니다.
- 포워딩 지원: 필요한 경우 실제 서비스로 요청을 전달할 수 있어, 목 서버와 실제 서버를 유연하게 전환하며 테스트할 수 있습니다.
이러한 기능들은 개발자들이 다양한 시나리오를 테스트할 수 있게 해 주며, 실제 서비스 환경과 더욱 유사한 조건에서 테스트를 수행할 수 있도록 지원합니다.
또한, 개발자들의 편의성을 높이기 위해 다음과 같은 기능도 제공합니다:
- JSON 린터1: 응답 body를 작성할 때 JSON 형식의 오류를 즉시 확인하고 수정할 수 있습니다.
- VS Code 스타일 에디터: 웹 환경에서도 마치 VS Code를 사용하는 것처럼 편리하게 응답 body를 수정할 수 있습니다. 이 에디터는 구문 강조 등 개발자들에게 익숙한 기능들을 제공합니다.
5. 성능 테스트 지원
성능 테스트용 목 서버는 공용 목 서버에 생성해 둔 API를 바탕으로 동기화하여 사용할 수 있습니다. 성능 테스트용 목 서버는 최대 6,800 RPS(Requests per second)에서 7,000 RPS까지 지원하고 있습니다. 이를 통해 일관된 테스트 환경을 유지하면서도 고성능의 테스트를 수행할 수 있습니다.
사용 사례
현재 29개 조직에서 72개의 목 서버를 사용하고 있는데요. 실제 사용 공유드리겠습니다.
- 의존성 있는 서비스의 점검 시에도 개발 및 테스트
- 🙆♀️ 개발자 A: 의존성을 가지고 있는 서비스의 샌드박스 서버가 점검 중일 때, 목 서버에 필요한 API를 추가해서 개발을 계속 진행할 수 있었습니다. 이를 통해 다른 서비스의 상태와 관계없이 개발 생산성을 유지할 수 있었습니다.
- 프론트엔드 개발 지원
- 🙍♂️ 개발자 B: API 서버 환경 구성이 지연되어, 목 서버를 구성해서 프론트엔드 개발자들에게 제공한 경험이 있습니다. 실제 API가 준비되기 전에 목 서버로 임시 환경을 제공함으로써 프론트엔드 개발 일정에 차질이 생기지 않도록 했습니다.
-
외부 서비스 의존성 해결을 통한 성능 테스트
- 💁 개발자 C: 외부 서비스 목 서버를 구성해서, 외부 서비스에 영향을 주지 않고 성능 테스트를 수행할 수 있었습니다. 이를 통해 실제 외부 서비스에 부하를 주지 않으면서도 다양한 시나리오의 성능 테스트가 가능해졌습니다.
-
성능 테스트 및 내부 로직 최적화
- 🙋♀️ 개발자 D: 성능 테스트용 목 서버를 사용해 서비스의 성능을 개선할 수 있었습니다. 외부 서비스의 성능이 문제인 줄 알았는데, 목 서버로 외부 서비스를 모의 구현해 확인해 보니 외부 서비스가 문제가 아니라 내부 로직이 문제였던 것을 발견할 수 있었습니다. 이를 통해 실제 성능을 개선할 수 있었습니다.
한계
공통 목 서버가 많은 이점을 제공하고 있지만, 여러 가지 한계점도 존재합니다. 아래는 현재 인식하고 있는 주요 한계점입니다.
- 특정 서비스에 대한 깊이 있는 지원의 한계
- 공통 목 서버의 특성상, 특정 서비스에 특화된 기능을 깊이 있게 제공하기 어려운 점이 있습니다. 각 서비스마다 고유한 요구사항이 있을 수 있는데, 이를 모두 충족시키기는 어렵습니다. 이로 인해 일부 개발자들은 자신들의 서비스에 완벽하게 맞는 기능을 사용하지 못해 아쉬워하는 경우가 있습니다.
- 수기 입력에 따른 유지보수 부담
- 현재 목 서버는 Swagger와 같은 도구처럼 API를 자동으로 생성하지 않고, 개발자가 직접 하나하나 입력해야 합니다. 이는 초기 설정 시 시간이 많이 소요될 뿐만 아니라, 특히 자주 변경되는 서비스의 경우 목 서버를 최신 상태로 유지하는 데 상당한 노력이 필요합니다. 이로 인해 일부 개발자들은 변경이 잦은 서비스에 대해 목 서버를 만들고 유지하는 것을 부담스러워합니다.
이러한 한계점들을 인식하고 있기에, 지속적으로 개선 방안을 모색하고 있습니다. 예를 들어, 서비스별 커스터마이징 옵션을 확대하며, API 자동 생성 및 동기화 기능 도입을 검토하고 있습니다. 이를 통해 더욱 효율적이고 사용자 친화적인 목 서버를 제공하고자 합니다.
마치며
먼저, 긴 글을 끝까지 읽어주셔서 감사합니다.
이번 글에서는 공통 목 서버를 도입하게 된 배경과 기능, 실제 사용 사례를 소개했습니다. 공통 목 서버는 개발 과정에서 마주치는 테스트 환경 구축의 어려움을 해결하기 위해 시작되었으며, 현재는 개발 프로세스 전반의 효율성을 높이는 중요한 역할을 하고 있습니다.
직관적인 UI/UX, 레이턴시 설정, 동적 응답 생성, 포워딩 지원 등의 특징을 통해 성능 최적화, 프론트엔드 개발 지원, 외부 서비스 의존성 해결 등 다양한 영역에서 도움을 주고 있습니다. 물론 개선이 필요한 부분도 있지만, 이를 인식하고 지속적으로 발전시켜 나가고 있습니다.
이 글이 사내 테스트 진입 장벽을 낮추는 데 관심 있는 분들, 그리고 목 서버가 실제로 어떻게 사용되는지 궁금해하시는 분들에게 도움이 되었기를 바라겠습니다!
참고 자료
Footnotes
-
JSON 린터는 JSON 데이터의 형식이 올바른지 검사하고, 들여쓰기와 같은 스타일을 자동으로 정리해주는 도구입니다. 즉, JSON 데이터의 오류를 쉽게 찾고 가독성을 높여줍니다. ↩