안녕하세요, 풀스택 개발자 햄치코치입니다.
제가 첫 번째로 개발을 한 플랫폼 (공연 티켓 판매 사이트) 를 만들면서 느낀점을 일기처럼 남겨보려합니다.
2021년 9월 1일날 공연관련 스타트업에 합류하였습니다.
입사한 지 1주일 만에 저에게 주어진 임무는, 한 달 반~두 달 안에 뮤지컬 티켓 판매 사이트를 완성하는 것이었습니다.
개발자는 저 혼자였고, 뮤지컬은 연말에 인기가 많기 때문에 최소한 11월 전에는 오픈해야 고객 반응을 확인할 수 있었습니다. 대표님께서는 저에게 화이팅을 외치며 응원해 주셨습니다.
혼자서 서비스를 전체적으로 만들어보고 싶다는 막연한 생각을 가지고 있었습니다.
당장은 힘들겠지만 내가 전체적으로 서비스 프로세스를 이해할수 있을 거라는 마음이였습니다.
먼저, 빠르게 결과물을 만들어야 하는 상황에서 기술 스택을 정해야 했습니다.
프론트엔드에서는 React와 Vue 중 고민했지만, React에 대한 지식이 좀 더 있는 만큼 React를 선택했습니다.
백엔드는 레퍼런스가 가장 많은 Node.js와 Fastfiy 조합을 선택하게 되었고요.
또 기존에 운영하던 공연 정보를 알려주는 서비스가 중단되면서,
그때 사용하던 MongoDB에 이미 공연 관련 스키마가 남아있었습니다.
이를 유지하고 활용하기로 했습니다.
기술스택
저의 회사의 유일한 개발자 였습니다.
2달동안 개발해야하는 목록은 크게 2가지 였습니다.
위에 처럼 좌석을 보여주고 관리자가 지정한 판매석만 오픈 해야했습니다.
공연 판매의 핵심인 좌석도를 만들어야 했습니다.
생각해보면 좌석도는 일반적으로 엑셀처럼 칸별로 있다는 생각에 엑셀로 만들어서 업로드하는 방식으로 만들 수 있었습니다.
🚨 서비스 중 발생한 문제와 해결 과정
서비스 런칭 이후, 3개 공연은 문제 없이 잘 진행되었습니다. 이후 유명한 공연을 진행하게 되어 30분간 충전금액이 말도안되게 충전되었습니다. 서비스가 점차 성장하고 있다는 걸 실감할 수 있는 순간이었죠.
하지만, 예상하지 못한 트래픽 폭주로 인해 한 번은 서버가 다운되는 상황이 발생했습니다. 이때는 임시방편으로 서버와 RDS 용량을 급격히 늘렸고, Redis를 활용해 공연 정보와 같은 실시간 변동되지 않는 데이터를 캐싱하는 방법을 도입했습니다. 이를 통해 공연 소개, 포스터, 공연장 정보 등은 캐시 처리하여 서버 부하를 줄였고, 서버가 터지는 문제는 해결할 수 있었습니다.
그럼에도 불구하고, 두 번째 문제가 발생하게 되었습니다. 동일한 좌석을 2명이 구매한 경우가 발생한 것입니다. 이 문제는 서비스에서 가장 중요한 좌석 예매 시스템에서 발생한 동시성 문제였고, 공연을 좋아하는 고객들에게는 큰 불편을 주는 상황이었습니다. 결국, 고객에게 좌석이 잘못 판매된 점에 대해 설명하고, 직접 전화로 사과와 버그 설명을 해야 했습니다. 이때는 개발자로서 고객 서비스를 직접 경험할 수 있었고, 고객의 입장에서 이해할 수 있는 서비스 개선의 필요성을 절실히 느꼈습니다.
이 문제를 해결하기 위해, 처음에는 MongoDB에 저장된 좌석 정보를 활용하여
Mysql에 ["1열 2번", "1열 3번"] 형식으로 좌석을 처리하고 있었으나, 유니크 인덱스를 고려하지 않은 설계 때문에 동시성 문제를 제대로 처리하지 못했습니다.
이를 뒤늦게 깨닫고, 복합 유니크 인덱스를 사용하여 좌석 데이터의 유니크성을 보장하려고 했지만, 여전히 실시간 좌석 구매에서의 동시성 문제를 해결하는 데 한계가 있었습니다.
이후, Redis에서 제공하는 atomic (increment) 기능을 활용하여, 좌석을 구매할 때마다 좌석 번호에 대해 incr 명령어를 사용해 좌석을 예약하는 방식으로 개선했습니다. 이를 통해, 각 좌석마다 구매가 이루어지면 그 좌석의 상태가 atomic하게 증가되며, 첫 번째 사용자가 맞는지 체크할 수 있는 시스템을 만들었습니다. 결제 과정 중에는 해당 좌석이 이미 예약된 상태라면 두 번째 구매자가 좌석을 구매할 수 없도록 처리할 수 있게 되었습니다.
해당 회사에 근무 할 당시 저는 플랫폼 개발경험이 없는 신입 개발자였습니다.
이 과정에서 동시성 문제를 해결하면서, 서비스 안정성을 한층 높일 수 있었고,
고객에게 더 신뢰를 줄 수 있는 시스템으로 발전할 수 있었습니다. 또한, 이 문제를 해결하는 과정에서 Redis와 같은 캐시 시스템을 어떻게 효율적으로 활용할 수 있는지에 대해 많은 것을 배울 수 있었습니다.