티스토리 뷰
안녕하세요. Seller & SD Engineering 팀 박명훈입니다.
최근 개발자로서 직접 기안한 프로젝트를 완료했습니다. 팀에서는 Couchbase를 통해 인증 서비스의 데이터를 제공하고 있었는데, 낮은 사용성 이슈와 비즈니스 정책, 서비스 관리의 여러 이유로 인해 불편함이 많았고, 이로 인해 기획자들이 업무를 진행할 때 성능 이슈로 인해 거의 사용이 불가능할 정도로 문제가 많았습니다. 대표적인 예시로 검색을 하면 5분씩 걸렸습니다.
Couchbase는 MongoDB와 같이 Key-Document 구조를 가진 NoSQL 입니다.
이번 기회에 개선을 진행하며 기존의 문제를 해결하고, 성능적으로나 서비스적으로 아쉬웠던 부분을 개선했습니다. 그 과정과 결과에 대해서는 내용이 많아 크게 전략편과 실전 편으로 나눠서 서술할려고 합니다.
간략하게 서비스를 소개하면 저희 팀에서는 Couchbase를 통해, 외부에 제공하는 사내 API의 Gateway 인증 서비스를 관리하고 개발하고 있습니다. 이 서비스를 통해 인증된 외부에서 개발자들의 지마켓이나 옥션 등의 상품, 주문, 배송, 클레임, 정산 등의 API를 사용할 수 있게 됩니다. 즉, API 사용자가 인가된 사용자인지를 확인해 주는 인증 서버입니다.
기존 서비스의 문제.
기존의 서비스에서는 여러 문제가 있었습니다. 특히 가장 큰 문제는 사용자 입장에서가 아닌 관리자 측면에서는 설계가 부족했던 부분이었습니다. 과거에서는 문제가 안되었을 수 있으나, 데이터가 많아지면서 점점 더 드러난 문제입니다.
문제 1. 관리자 입장에서 최악의 구조
관리자 입장에서 특정 기준의 데이터를 조회해야 할 때 모든 document를 뒤져봐야 하는 단점이 있었습니다. couchbase에서도 indexing 을 지원하나, 저희 구조에서는 임시방편이라고 느끼기도 했고, 뒤에 나올 여러 가지 이유로 인해 비효율적이라고 판단했습니다.
해당 서비스는 사용자 입장에서 설게 된 서비스이고, 관리자 측면에 미흡하게 구성된 부분이 있습니다. 각 document는 판매자 id를 기반으로 돌아갑니다. 그러나 관리자가 사용을 할 때는 아이디 값보다는 상태 값을 기반으로 id를 찾는 경우가 더 많습니다. 대표적인 예시로 특정 계정들이 API를 사용할 수 있도록 승인해 주는 기능을 관리자에서 수행할 때, 성능이슈가 크게 발생했습니다.
따라서 이를 고려하면 다음과 같은 성능 차이가 있게 됩니다.
- 유저 기준 :
T(n) = O(1)
- 관리자 기준 :
T(n) = O(n)
그리고 특정 document의 값 자체를 히스토리로 저장함으로써 불필요한 공간을 차지하고 있었습니다. 관리자 측면에서의 설계 이슈와 불필요한 document의 데이터 적재로 인해 날이 가면 갈수록 큰 성능 저하가 발생했습니다.
문제 2. Couchbase에 대한 인프라 이슈
성능 이슈와 함께 이 작업을 진행하게 된 가장 큰 이슈였습니다.
데이터를 Couchbase 에서만 유지하고 있고 이를 다른 곳에서는 유지하지 않고 있기 때문에 자료 망실에 대한 위험성이 있었습니다. 수동으로 복구를 진행할 수도 있고, Couchbase에서 장애 발생 시 처리할 수 있는 방법(replication, XDCR 등)이 있으나 이 또한 저희의 입장에서는 학습 비용이 들어가고, 인프라 비용이 들어가는 듯 비효율적인 부분이 있었습니다.
DB Trending 등을 참고해 보면, 30위에 순위가 낮은 것을 알 수 있습니다. Couchbase 에 대한 커뮤니티가 부족한 것도 하나의 이슈였습니다.
그리고 Couchbase는 현재의 NoSQL 시장에서 많이 사용하지 않고, 저희 회사의 인프라 팀이나 데브옵스 팁에서도 지원이 어려운 NoSQL 서비스입니다. 이로 인해 네트워크 이슈나 보안 지원 등의 약점이 있고 장애가 발생 시 직접 해결을 해야 했습니다.
과거 이 친구 덕분에 주말에 비행기 표도 반납해 봤습니다…
물론 Couchbase 에는 N1QL 등의 쿼리나 성능적 장점도 있었고, 스타트업이나 빠른 서비스를 구축해야 하는 환경에서는 장점이 있다고 판단했습니다. 그러나 큰 서비스에서 성장해 가며 성능과 트래픽, 인프라 비용, 커뮤니티 등의 문제로 인해 Couchbase를 잘 사용하지 못하고 있다는 점을 느꼈습니다. 그래서 더 나은 해결책을 검토했습니다.
새로운 구조가 필요하다.
새로운 구조를 설계하면서 가져가는 방향은 기존에 Couchbase 인 NoSQL를 단독으로 사용하는 구조에서 RDB와 NoSQL로 역할을 분리하는 작업이었습니다. NoSQL은 MongoDB를 사용하고, RDB는 사내에서 사용자 정보를 들고 있는 MSSQL로 선정했습니다.
왜 Couchbase 대신 MongoDB 인가.
- 외부 커뮤니티가 잘 되어 있고, 내부적으로 잘 아는 사람이 많습니다.
- 사내 인프라 지원이 잘되어 있어 서버 관리가 필요가 없으며, 라이센스 지원이 가능했습니다.
- 같은 Key-Document NoSQL 이기에 기존 구조에서 큰 변경이 필요하지 않습니다.
- couchbase의 docType을 mongoDB의 collection으로 변경하기에 구조적으로 적합했습니다.
왜 RDB 을 같이 넣는가.
- 계정들의 정보들은 회사 회원 RDB에서 최신으로 유지되기에 이 부분에 대한 정합성 관리가 편합니다.
- NoSQL에서 불필요하게 생기는 히스토리 구조를 제거하여 불필요한 collection을 줄이고 RDB에서 효율적으로 관리할 수 있습니다.
- NoSQL의 데이터가 날아갔을 때, RDB를 통해 백업을 쉽게 할 수 있습니다
- 특정 조건 조회의 경우, NoSQL에서 찾는 것보다는 쿼리를 사용하는 것이 성능적으로 이점이 크다고 판단했습니다.
물론, NoSQL을 잘 쓰면 위의 단점 등을 상쇄할 수 있을 것이나 현재에 여러 가지 이유로 인해 관련 방향이 최적의 상황이라고 판단했습니다.
기존 구조를 유지하며 서비스 향상을 위한 새로운 과제
기존 서비스를 문제없이 전환하고, 기존의 잘못된 설계를 개선하려면 여러 가지 신경 쓸 부분이 존재했습니다.
과제 1. NoSQL 형태를 RDB에 적합하게 재설계 필요
일반적으로 RDB에서 NoSQL로 전환하는 구조로 설계하는 경우는 많으나, 반대 케이스는 별로 없습니다. 그러나 이번 기회에 이 작업을 통해서 여러 고민을 하게 되었습니다.
특히 document 구조에서 list와 map 형태를 RDB로는 어떻게 변경할 것인가에 대한 고민이 가장 큰 고민이었습니다.
- 1안 : 단일 string 형태로 처리하고 “,” 의 구분자를 중간에 두어서 처리
- 2안 : 신규 매칭 테이블을 생성
각자 장단점이 있습니다.
1안의 경우, 반드시 데이터를 다 들고 와서 구분자를 잘라서 써야 하는 단점이 있습니다. 그러나 데이터 양이 적고 접근이 많지 않은 경우 굳이 새로 테이블을 만들 필요가 없다는 장점이 있습니다.
2안의 경우에는 map 형태와 같이 일정 형태가 매칭되는 정보들이 많을수록 row 수가 기하급수적으로 늘어나는 단점이 있습니다. 예시를 들면, n개의 아이디에 m개의 업체를 연결하는데, k개의 업체 종류가 있는 경우, 컬럼 수는 n * m * k
개가 되는 문제가 발생합니다. (물론, k 업체의 개수에 제한이 있는 경우는 column을 늘려서 풀 방법은 존재합니다.) 이러한 이슈 등을 설계할 때 고려해야 합니다.
1안을 쓰거나 2안을 쓸 때 판단은, 다 꺼내서 다시 데이터를 만들어야 하는 상황이 나오면 2안의 방향으로 가는 것이 낫다고 판단했습니다. 그리고 둘 다 적합하지 않다고 판단되면 다시 설계를 하는 것도 좋은 방법이라고 생각합니다.
과제 2. Couchbase N1QL 쿼리를 대체하는 시스템
Couchbase 에서는 RDB와 같은 트랜잭션을 지원합니다. 물론 MongoDB에서도 최근에는 query document 등을 지원하나 이 부분을 효율적으로 사용하는 것이, 저희의 서비스에 비약적인 성능 향상이 어렵고 복잡한 조회 기준을 가져갈 경우 MongoDB에서 적합하지 않다고 판단했습니다.
그래서, 이 부분은 RDB에서 쿼리를 직접 짜기로 했습니다. 즉, 관리자 쪽에서는 최대한 RDB를 사용하는 방향으로 고려를 했습니다.
과제 3. 기존의 영향이 없는 무중단 서비스 전략
해당 데이터는 Gateway 서비스의 인증 데이터이기에, 외부에서 사용하는 API 들은 해당 서버를 거치게 됩니다. 그러한 상황에서 이 서비스의 DB를 교체하고 데이터를 마이그레이션하는 상황에서 장애가 발생하면 전사적인 장애로 퍼지게 되고, 큰 손실을 입게 됩니다.
또한, 인증 Gateway 서버와 이를 관리하는 ESMPLUS와 관리 페이지 등이 같은 데이터를 보기 때문에, 여러 서비스가 동시적으로 배포해야 하는데, 동시에 모든 서버를 배포하게 되면 서비스적으로 리스크가 커집니다.
그래서, 이를 영향을 해결할 방법으로 점차적으로 변경하는 전략 등을 고려했습니다.
과제 4. 작업 스케줄의 간소화
개발자는 비즈니스 적으로 좀 더 우선적인 작업을 처리할 필요가 있습니다. 관련 작업이 비즈니스 적으로 의미가 있는 작업이고 같이 업무를 하는 기획자 입장에서는 편리해지지만, 비용적인 측면에서 더 큰 이점이 없기 때문에 가성비 있게 끝내야하는 부분이 필요했습니다.
그래서 최대한 있는 기능으로 가성비있게 끝내는 것을 목표로 잡았습니다.
마무리.
위에서는 저희 서비스에서 직면한 문제와 그로 인해 해결방법을 제안하고 이를 설계하는 부분을 정리했습니다. 그리고 그 과정에서 신경을 써야 하는 부분을 검토했습니다.
다음에는 이 문제를 실질적으로 서비스로 녹여내는 과정, 배포 전략과 상세한 설계, 그 결과로써 얻은 부분과 결론에 대해서 작성하겠습니다.
글 읽어주셔서 감사합니다.
'Backend' 카테고리의 다른 글
docker-compose를 이용하여 다수의 spring boot 프로젝트 연결하기 (Part 2) (0) | 2023.05.24 |
---|---|
달리는 인증 서비스의 NoSQL을 바꾸자. - 실전편 (0) | 2023.05.10 |
Testcontainers로 통합테스트 만들기 (0) | 2023.04.26 |
BigDecimal A to Z: 정확한 계산을 위한 숫자 처리 클래스 (0) | 2023.04.19 |
docker-compose를 이용하여 로컬 개발환경 구성하기(Part1) (2) | 2023.04.12 |