![logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/framework_logo/mongodb.png&w=150&q=90)
데이터베이스
MongoDB
강력하고 유연하며 확장성이 높은 Document-based NOSQL 데이터베이스
StackOverflow 질문 수: 176264
Github Stars : ★ 25998
사용 기업
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/406.png&w=720&q=90)
렌딧
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/64.png&w=720&q=90)
토스랩
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/3542.png&w=720&q=90)
파운트
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/808.png&w=720&q=90)
식스샵
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/4411.png&w=720&q=90)
드림어스컴퍼니
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/1810.png&w=720&q=90)
스푼
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/3257.png&w=720&q=90)
클래스101
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/436.png&w=720&q=90)
바로고
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/15.png&w=720&q=90)
마이리얼트립
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/1213.png&w=720&q=90)
비브로스
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/57.png&w=720&q=90)
다노
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/8.png&w=720&q=90)
채널코퍼레이션
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/178.png&w=720&q=90)
오피지지
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/1529.png&w=720&q=90)
카카오페이
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/1362.png&w=720&q=90)
위메프
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/137.png&w=720&q=90)
여기어때컴퍼니
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/187.png&w=720&q=90)
카카오엔터테인먼트
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/company-logo/506.png&w=720&q=90)
카카오스타일
더 보기
라인
Kafka와 ETL을 활용해 대용량 데이터 마이그레이션하기
안녕하세요. LINE Plus에서 Global E-Commerce Platform 개발을 맡고 있는 장효택입니다.LINE Brand Catalog와 통합 커머스 검색 서비스(이하 통합 커머스 검색으로 통칭)에는 다양한 위치에 수많은 이미지가 사용되고 있습니다. 가장 흔하게 접할 수 있는 상품, 카탈로그 이미지부터 브랜드와 카테고리 영역 등에서도 이미지가 사용됩니다.통합 커머스 검색에서는 외부 상점의 상품 이미지를 OBS라는 사내 미디어 플랫폼에 저장해서 사용자에게 보여줍니다. 이 과정에서 불필요한 이미지 중복 저장 방지와 성인 이미지 검출, 이미지 사용처 확인 등 다양한 기능을 최적화해 사용하기 위해 이미지의 고유 ID와 크기, 색상 정보, 성인 이미지 점수 등 여러 정보를 MySQL에 저장해 관리하고 있습니다.현재 통합 커머스 검색에 존재하는 상품 수는 10억 개를 상회하고 각 상품은 여러 장의 이미지를 사용할 수 있기 때문에 결과적으로 26억 개가 넘는 이미지가 저장 및 관리되고 있는데요. 통합 커머스 검색 서비스의 규모가 계속 커지면서 DB 마이그레이션을 진행할 수밖에 없었습니다.저희 팀은 DB 마이그레이션을 진행하면서 독특하게 Kafka 생태계와 ETL 데이터를 적극 활용하는 방법을 사용해서 MySQL에서 MongoDB로의 마이그레이션을 성공적으로 완료할 수 있었습니다. 이번 글에서는 마이그레이션을 결정한 순간부터 마이그레이션 성공 후 MongoDB로 운영하는 현재에 이르기까지의 경험을 공유하겠습니다.마이그레이션이 필요하다는 신호통합 커머스 검색에 새로운 상점이 입점하고 등록되는 상품이 계속 증가하면서 자연스레 저장하고 관리하는 이미지가 더욱 많아졌습니다. 새로 추가되는 이미지의 개수를 살펴보면 한 달에 적게는 4,000만 건에서 많게는 2억 건이 넘는 이미지가 새로 추가되고 있습니다.신규 이미지가 증가하면서 이미지의 정보를 저장하는 테이블(이하 이미지 테이블)과 이미지 사용처의 정보를 저장하는 테이블(이하 참조 테이블)이 빠르게 커졌습니다.이와 같이 두 테이블의 크기가 빠르게 증가하면서 다음 두 가지 문제에 대한 우려가 커졌습니다.MySQL 디스크가 가득찰 것으로 예상MySQL에서는 이미지 관련 테이블뿐 아니라 통합 커머스 검색 서비스 운영에 필요한 다른 여러 테이블도 함께 존재하는데요. 이미지 관련 테이블이 빠르게 커지면서 MySQL의 디스크 사용량이 90%를 초과했고, 그중 이미지 관련 테이블의 비율이 70%을 초과했습니다. 한 달에 약 1%씩 크기가 증가하고 있었고, 이 추세라면 일 년 내에 이미지 테이블은 물론 다른 테이블에도 영향을 미칠 수 있는 상황이었습니다. 타 테이블들은 서로 연관성이 깊고, 안정성을 확보하기 위한 트랜잭션 작업과 스키마 정의가 필수라서 마이그레이션하기가 어려웠습니다.데이터가 너무 많아 스키마 변경 어려움서비스를 운영하다 보면 필드를 변경하거나 새로 추가해야 하는 일이 발생하는데요. 이미지 테이블의 경우 데이터가 워낙 많다 보니 스키마를 변경하면 시스템이 느려지거나 멈추는 현상(hang up)이 발
hive
kafka
mongodb
mysql
spark
비바리퍼블리카
KsqlDB를 활용한 증권사의 실시간 데이터 처리하기
안녕하세요. 토스증권 실시간 데이터 팀 리더 강병수입니다.토스증권 실시간 데이터 팀에서는 Kafka, Kafka Connect, Clickhouse, KsqlDB와 같은 서비스에서 발생하는 실시간 이벤트를 다루는 플랫폼을 운영하고 있는데요. 이번 글에서 토스증권 실시간 데이터 프로세싱에 활용 중인 KsqlDB에 대해서 소개하려고 합니다.데이터 처리는 처음에는 대부분 배치(Batch) 작업으로 시작하지만, 서비스가 고도화되면서 주기적인 배치 성격보다 더 빠른 결과를 원하게 됩니다. 그 시점이 되면 실시간 데이터 처리에 대한 요구가 시작되는데요.토스증권은 서비스 오픈 전부터 토스에서 쌓아온 플랫폼 구성 및 운영 노하우를 이어받아 시작했습니다. 그 이유로 초기부터 빅데이터 플랫폼이 잘 갖춰져 있었고, 실시간 처리도 충분히 할 수 있었습니다. 다만 플랫폼을 운영하는 사람은 저 한 명이었다는 게 문제였는데요. 이러한 배경에서 실시간 데이터 프로세싱 플랫폼 도입을 고민하던 중 KsqlDB를 선택하게 됐습니다.토스증권은 서비스 오픈부터 계좌개설 이벤트가 크게 성공하면서 다양한 문제들을 동반했는데요. KsqlDB를 적극적으로 활용해서 문제를 해결해 나간 이야기를 해보려고 합니다.어떤 플랫폼을 고를까?처음 실시간 데이터 프로세싱 플랫폼을 도입할 때 어떤 것을 사용할지 고민을 많이 했습니다. 토스에서 사용하던 Spark Streaming, 대중적으로 많이 활용되는 Flink, 그리고 당시 국내에서는 레퍼런스가 거의 없던 KsqlDB가 후보였습니다. Spark Streaming, Flink 모두 좋고 대중적인 플랫폼이지만 세 가지 이유로 KsqlDB를 선택했습니다.• None 소스코드 개발 없이 SQL만 이용해서 프로그램을 만들 수 있다는 점 혼자서 많은 실시간 프로세싱 애플리케이션을 개발하기에는 무리였다보니, '생산성'이 가장 중요했어요. 소스코드를 직접 짜는 것과 KsqlDB에서 SQL 기반으로 Job을 만드는 건 생산성에서 10배 이상 차이가 났습니다.• None 토스에서 Spark Streaming Job을 개발 및 배포할 때 Job이 많아지면 운영에 리소스가 굉장히 많이 들어갔던 경험이 있었습니다. 개발은 끝이 아니라 시작이라는 점 때문에 배포 및 관리가 단순한 플랫폼이 필요했어요.• None Kafka Ecosystem에 어울리는 아키텍처 Kafka만 있으면 쉽게 활용이 가능했고, Offset 관리나 H/A 부분을 Kafka에 적극 위임하도록 구현돼 있어서 KsqlDB는 굉장히 Kafka스러운 시스템이라는 생각이 들었습니다. Kafka 운영도 하고 있었다 보니 Kafka에 대한 이해를 바탕으로 잘 운영 해볼 수 있는 장점이 있었어요.토스증권은 Kafka Ecosystem을 Confluent Platform을 사용하고 있지 않고 오픈소스를 활용하고 있습니다. 그 이유로 KsqlDB를 사용하기 위해서 Confluent에서 Confluent Community 라이선스를 따르는 KsqlDB 소스코드를 활용했는데요. 해당 소스코드를 빌드해서 토스증권의 O
kafka
mongodb
비바리퍼블리카
우리는 어떻게 해외주식 서비스 안정화를 이뤘는가
안녕하세요, 토스증권 Server Developer 김광훈입니다. 제가 근무하고 있는 해외주식 플랫폼 팀은 미국 주식을 중심으로 해외 주식 원장을 담당하고 있어요. 원장이란 증권 서비스에서 가장 주요한 영역 중 하나이며, 금융거래를 기록하는 장부를 말해요. 저희 팀에서는 고객의 주문, 자산, 권리 그리고 종목 정보 관리와 환전까지 해외주식 서비스 제공에 필요한 모든 거래와 정보들을 원장에 기록하는 개발과 운영을 하고 있어요.이번 글에서는 저희 팀이 외부 브로커와 통신하고 있는 해외 주식 서비스를 안전하게 운영하기 위해 고민했던 내용을 공유하려고 합니다.먼저, 미국 주식 매매 아키텍처를 같이 살펴볼게요. 사용자가 토스증권에서 매매 요청을 하면 현지 브로커로 요청을 보내고 브로커는 현지 미국 거래소에서 매매를 체결하고 응답을 보내는 구조입니다. 브로커라는 용어가 생소할 수 있는데요, 이름 그대로 주식 매매를 현지에서 처리를 해주는 역할을 하는 회사에요. 미국에서 직구를 할 때 중간에 상품을 현지에서 구매하고 한국으로 배송해주는 대행사와 비슷한 것이죠.브로커와 통신은 HTTP, FIX 두 가지 프로토콜을 사용하고 있어요. 메인으로는 FIX 프로토콜을 사용하고 있고, 브로커 요구사항에 따라 HTTP 를 부분적으로 사용하여 요청 보내고 있어요. 요청에 대한 응답은 최종적으로 Kafka나 SQS와 같은 큐를 사용하여 비동기로 처리하고 있어요.그럼 이제 토스증권에서 브로커와 통신하는 과정에서 어떤 문제가 왜 일어났는지 설명드릴게요. 아래 그림은 브로커 이슈로 문제가 된 상황 당시의 핀포인트 그래프입니다. 그래프를 보면 브로커 응답 시간이 조금씩 지연이 발생하였고, 지연된 주문들은 계속 대기하면서 쌓이게 되고 결국에는 5000ms 이상 응답이 걸리게 되면서 이슈가 발생한 것을 볼 수 있어요.문제의 원인은 크게 두 가지였어요.먼저 정규장 시작에 크게 뛰는 트래픽이었는데요. 아래 그래프는 주문 API 호출 건 수를 시간대별로 나타내고 있어요. 미국의 정규장 시작(22시30분)부터 호출 건 수가 급격히 증가하는 것을 볼 수 있어요. 해외주식 서비스 특성상 정규장 초반에 트래픽이 급격히 증가하고 최소 두 시간 정도는 지속돼요. TPS 를 정규장 시간과 아닌 시간을 비교해보면 20배 이상 차이가 나기에, 대부분의 운영 이슈는 정규장 오픈 초반에 발생할 수밖에 없어요.토스증권 사용자가 늘어나는 것도 문제의 원인이었어요.해외주식 주문 증가 추세를 보기 위해 주문 접수 API 요청을 월 별로 집계를 해보았어요. 아래 그래프를 보면 계속 주문 수는 증가하고 있는 추세를 볼 수 있어요. 오픈 초기 주문 요청량 대비 현재 요청량을 비교해보면 약 30배 넘게 증가한 것을 볼 수 있었습니다.서비스가 오픈하고 폭발적인 성장을 하게 되었고, 동시에 브로커도 함께 처리해야 하는 주문도 증가했어요. 그로 인하여 보이지 않았던 이슈들이 점차 수면 위로 올라왔고, 크고 작은 이슈들을 겪게 되었습니다.브로커와 통신 과정에서 이슈를 겪고 나서 팀에서는 통신 구간에 엔지니어링을 시작을 했고
grafana
kafka
mongodb
oracledb
SK텔레콤
mongoDB Session 사용하기
RDB같은 경우에는 atomic성이 항상 보존되기 때문에 이에 대한 생각을 할 필요가 없지만,mongoDB는 그렇지 않기 때문에 일련의 과정으로 처리해야할 경우 session을 사용해서 이를 보장해야 한다. (mongodb 4.0 version 부터 사용 가능하다.)session 기능은 standalone에서는 동작하지 않기 때문에 replica set 구성을 해 주어야 한다.예시를 작성할 때 nestjs를 사용하여 작성하였고 동작 방법에 대해 간단히 요약해서 말하자면 아래와 같은 순서로 동작한다고 볼 수 있다.• None DB에 접근할 때 session 정보를 같이 전달한다.• None 모든 session이 정상적으로 완료되었으면 commit을 한다.• None 만약 중간에 에러가 발생하면 commit을 하지 않고 session을 abort 시킨다.우선 session기능을 사용하기 위해서는 replica set 구조가 되어있어야 하기 때문에 이를 먼저 적용한다.docker는 이미 사용하고 있다고 가정하고 docker-compose를 이용해서 replica set을 구성하도록 하겠다.본인의 경우 27017,27018,27019 port로 3개의 db를 띄워서 사용하였다.이제 docker-compose up -d를 하면 mongodb 5.0 version을 다운로드하고 실행한 모습을 볼 수 있다.이처럼 docker app에서 잘 보인다면 cmd 창에서 제대로 동작하는지를 확인해보자docker ps 명령어를 이용한다.이제 replica set으로 잘 동작하고 있는지 확인해 보자.위 명령어를 통해서 container 안으로 접근한다.을 통해서 mongo app을 접근한다. 라고 보이면 정상적으로 실행 중임을 확인할 수 있다.rs.status() 명령어를 통해서도 확인할 수 있다.이제 mongoDB는 켜져있으나 실제로 접근은 알 될 것이다.왜냐하면 아래의 members 정보로 initialize 가 되어 있는데 mongo1, mongo2, mongo3의 host 정보를 모르기 때문이다.이를 해결하기 위해서 /etc/hosts 파일을 수정해주자.이렇게 mongo1, mongo2, mongo3에 대한 host를 정의해준다. 이제 제대로 연결이 된다.nestjs를 사용해서 작성했고 아마 다른 언어를 쓴다고 해도 크게 차이가 없을 거라고 생각한다.예시 코드는 예시 git 에 올려놓았다. stock인 이유는 복기하기 위한 저장소를 만드려고 했는데 그냥 예시로 쓰려고 한다.위와 같이 사용하였다. 이제 create는 두개의 collection을 atomic하게 사용할 수 있다. 실제로 error를 주입하여 사용해 보면 abort 발생 시 다 롤백되는 것을 확인할 수 있다.이제 mongoDB 사용 시 유지 보수를 훨씬 더 간편하게 해주고 DB 정합성을 신경쓰지 않아도 된다.• None 같은 DB를 사용해야 session 사용이 가능하다. replica set으로 묶여있는 DB는 괜찮지만, 아예 다른 mongoDB 두개를 상용하려고 하면 DB가 관리하는 session 정보가 맞지 않기 때문에 에러가 발생한다.
docker
mongodb
연관 기술 스택
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/framework_logo/awsdocumentdb.png&w=720&q=90)
AWS DocumentDB
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/framework_logo/awsdynamodb.png&w=720&q=90)
AWS DynamoDB
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/framework_logo/couchbase.png&w=720&q=90)
Couchbase
![techstack-logo](https://image.wanted.co.kr/optimize?src=https://static.codenary.co.kr/framework_logo/elasticsearch.png&w=720&q=90)
ElasticSearch