포도스피킹 퇴사 회고

40 min read로딩중...
📑 목차 보기

오랜만에 회고를 쓴다.

퇴사를 앞두고 있다. 2024년 10월 15일에 입사해서, 2025년 12월 10일에 나간다. 1년 2개월. 숫자로 보면 길지 않은 시간인데, 돌아보면 밀도가 높았던 시간이었다. 입사 14개월 만에 회사가 BEP(손익분기점)를 달성하는 것까지 함께 봤고, 그 과정에서 많은 것을 만들고, 부수고, 다시 만들었다.

이 글은 그 시간 동안 내가 무엇을 했는지, 어떤 사람들과 일했는지, 그리고 나는 어떻게 달라졌는지에 대한 기록이다. 회사에 대한 이야기이기도 하지만, 결국 그 안에서의 나에 대한 이야기다.

왜 이 회사를 선택했나

휴톰을 나오고 다음 회사를 고를 때, 나름의 기준이 있었다.

첫째, 글로벌 서비스를 경험하고 싶었다. 타임존, 다중 결제, 국제화가 뒤섞인 복잡한 도메인. 한국 시장만 보는 서비스와는 다른 종류의 문제들을 풀어보고 싶었다.

둘째, 스케일 업 단계의 회사를 원했다. 이미 안정된 곳보다는, 아키텍처를 함께 진화시킬 기회가 있는 곳. 시스템이 성장하는 과정을 직접 겪어보고 싶었다.

셋째, 단순히 피처를 찍어내는 게 아니라 시스템 설계에 직접 손댈 수 있는 환경을 찾았다.

데이원컴퍼니의 레모네이드 CIC, 그중에서도 포도스피킹 팀이 그 기준에 맞았다. 1:1 영어 회화 서비스. 필리핀이나 남아공에 있는 튜터들이 한국 학생들과 화상으로 수업을 하는 구조였다. 튜터 앱과 학생 앱, 두 개의 서비스를 만들어야 했고, 튜터 쪽은 글로벌 타임존을 다뤄야 했다. 학생은 아직까지 한국 고객들만 있었지만, 결제 시스템이나 스케줄링 로직은 글로벌 확장을 염두에 두고 설계해야 했다.

복잡하겠다는 생각이 들면서 동시에 기대가 됐다. 결과적으로 그 직감은 맞았다.

결제 도메인을 맡다

입사하고 가장 먼저 맡은 건 결제 도메인이었다.

처음에 "결제 쪽 좀 봐주세요"라는 말을 들었을 때, 솔직히 부담이 됐다. 결제는 돈이 오가는 영역이다. 버그 하나가 매출에 직접적인 영향을 준다. 하지만 막상 코드를 열어보니, 진짜 문제는 버그가 아니었다.

문제는 "뭐가 문제인지 알 수 없다"는 것이었다.

유저가 "결제가 안 돼요"라고 연락하면, 우리는 Datadog을 뒤지고, 백엔드 로그를 뒤졌다. 그런데 어느 지점에서 끊겼는지 선명하게 잡히지 않았다. GA 리포트를 열어봐도 유입 경로에는 not set이 줄줄이 찍혀 있었다. 유저가 어떤 경로로 들어와서 결제 페이지까지 왔는지, 결제 버튼을 눌렀는데 왜 실패했는지, 다시 시도는 했는지, 한 화면에서 이어서 보기 어려웠다. 정보는 있었지만, 서로 다른 곳에 흩어져 있었다.

분산된 채널, 분산된 로깅

당시 결제 관련 로그는 여러 Slack 채널에 나뉘어 있었다. 결제 성공은 A 채널, 실패는 B 채널, 쿠폰 발급은 C 채널. 하나의 유저 플로우를 추적하려면 채널을 계속 왔다 갔다 해야 했다.

완벽한 단일 타임라인을 만들지는 못했지만, 적어도 각 단계별로 로깅을 남기는 구조는 갖췄다. Datadog과 Slack 웹훅을 조합해서 결제 시작, 상품 선택, PG사 선택, 결제 완료(또는 실패) 같은 주요 이벤트들을 기록했다.

이후에는 "이 유저가 어디까지 진행했는지" 정도는 바로 확인할 수 있게 됐다. CS 이슈가 들어왔을 때 대응 속도가 눈에 띄게 빨라졌다.

이 일을 하면서 자연스럽게 이런 생각을 하게 됐다.

화려한 모니터링 시스템을 갖추는 것보다, 문제가 생겼을 때 원인을 빨리 좁힐 수 있는 구조를 만드는 게 더 중요하다.

대시보드가 멋있게 보이는지는 중요하지 않다. 결국 필요한 건 "지금 이 유저에게 무슨 일이 있었는지"를 빠르게 복기할 수 있는 최소한의 흔적이었다.

브라우저 이탈과 이벤트 드리븐

결제 도메인을 파다 보니 흥미로운 문제를 만났다.

우리 시스템은 Event-Driven Architecture로 설계되어 있었다. 결제가 완료되면 이벤트를 퍼블리싱하고, 그 이벤트를 구독하는 쪽에서 쿠폰 발급, 수강권 활성화 같은 후속 작업을 처리하는 구조였다.

문제는 "결제 완료"를 누가 알려주느냐였다.

일반적으로는 클라이언트에서 결제 성공 콜백을 받으면 서버에 알리고, 서버가 이벤트를 퍼블리싱한다. 그런데 만약 유저가 결제 성공 직후에 브라우저를 닫아버리면? 클라이언트 콜백이 실행되기 전에 페이지가 사라지면?

결제는 됐는데 이벤트는 안 날아가고, 유저는 수강권을 못 받는 상황이 생길 수 있었다.

두 곳에서 이벤트를 퍼블리싱하고, 멱등성으로 보장하기

결국 제안한 방식은 이랬다.

  1. 클라이언트: 결제 성공 콜백에서 이벤트 퍼블리싱 요청
  2. PG사 웹훅: 결제 완료 웹훅에서도 동일한 이벤트 퍼블리싱 요청

두 경로가 같은 이벤트를 보내도록 한 것이다. 자연스럽게 "이벤트가 두 번 처리되면 어떡하나"라는 걱정이 따라왔다. 그래서 멱등성(idempotency)이 필요했다.

아임포트(현 포트원)의 imp_uid를 활용했다. 백엔드에 "같은 imp_uid로 이벤트가 두 번 오면, 두 번째는 무시해달라"고 요청했다. 이렇게 하면 클라이언트에서 이벤트가 날아가든, 웹훅에서 날아가든, 둘 다 날아가든 결과적으로 한 번만 처리된다.

이 구조를 적용한 뒤에는 브라우저 이탈로 인한 수강권 미발급 이슈를 거의 보지 않게 됐다.

이때 느낀 건 이거였다.

분산 시스템에서는 "정상 동작"을 전제로 설계하기보다, 중간에 반드시 한 번쯤은 끊긴다고 생각하고 구조를 짜야 한다.

"유저가 브라우저를 안 닫겠지"를 기대하는 대신, "닫을 수도 있으니 그래도 괜찮은 구조"를 만들어야 했다.

GA가 "not set"으로 가득 찬 이유

결제 모니터링을 만들면서 GA도 함께 들여다봤는데, 여기서 더 큰 문제가 보였다.

당시 포도스피킹의 구조는 이랬다.

  • podo.re-speak.com - Next.js로 만든 학생 앱
  • app.podo-speaking.com - Nuxt.js로 만든 학생 앱
  • grape.re-speak.com - PHP로 만든 관리자 페이지

유저가 광고를 보고 들어와서 여러 도메인을 거쳐 결제까지 가면, 매출이 어디서 난 건지 GA에서 제대로 추적이 안 됐다. 도메인이 다르면 GA 세션이 끊긴다. 리포트를 보면 유입 경로가 not set으로 꽉 차 있었다.

도메인을 합쳐야겠다는 생각이 들었다. 문제는 세 개의 스택이 전부 다르다는 것이었다. Nuxt.js, Next.js, PHP. 이걸 어떻게 하나의 도메인으로 묶을 수 있을까.

Multi-Zone MFE: Next.js를 오케스트레이터로

결국 선택한 구조는 Multi-Zone Micro Frontend였다.

  • 외부에서 보는 도메인은 podo.re-speak.com 하나로 통일
  • Next.js가 오케스트레이터 역할을 하면서, 경로에 따라 적절한 서비스로 프록시
    • /tutor/* → Nuxt 서비스
    • /admin/* → PHP 서비스
    • 나머지 → Next.js

이렇게 하면서 몇 가지가 동시에 풀렸다.

첫째, Same-Origin. 모든 서비스가 같은 도메인을 쓰기 때문에 쿠키를 공유할 수 있게 됐다.

둘째, GA 일원화. 오케스트레이터 레이어에서 GA 스크립트를 관리할 수 있어서 전체 유저 여정을 하나의 흐름으로 볼 수 있게 됐다.

셋째, 점진적 마이그레이션. Nuxt에서 Next.js로 화면을 하나씩 옮길 수 있는 발판이 생겼다.

이 작업에 약 4개월이 걸렸다. 중간에 "이게 정말 되는 건가" 싶은 순간도 있었는데, GA에서 유저 플로우가 끊기지 않고 이어지는 걸 처음 봤을 때 그동안의 삽질이 조금은 보상받는 느낌이었다.

그때 내가 했던 고민은 기술적인 우아함보다 이런 쪽에 가까웠다.

이 구조가 마케팅팀과 비즈니스 쪽에서 보고 싶은 숫자를 제대로 보여줄 수 있는가?

Next.js rewrites가 이론적으로 가장 멋진 선택이었는지는 잘 모르겠다. 다만 캠페인 성과를 숫자로 설명할 수 있게 된 순간, 이 방향은 충분히 의미 있었던 결정이었다.

수업 시간에만 서버가 터지는 문제

입사 초반, 학생용 수업 플랫폼에서 이상한 패턴을 발견했다.

평소에는 멀쩡한데, 특정 시간대에만 서비스가 느려지거나 죽었다. 1:1 회화 서비스 특성상 수업이 몰리는 시간대가 있었다. 저녁 7시에서 10시, 주말 오전 같은 피크 타임에 트래픽이 갑자기 치고 올라갔고, 인프라가 이걸 제대로 받지 못했다.

부하 테스트를 돌려보니 예상했던 것보다 결과가 좋지 않았다. 스파이크 상황에서 요청 성공률이 크게 떨어졌다. 코드를 보기 전에, 인프라 구조 자체를 의심하게 됐다.

원인을 찾아가는 과정

가장 먼저 해본 건 Node.js 버전을 20에서 22로 올리는 일이었다. 성능 지표가 약간 좋아지긴 했지만, 이걸로 상황이 근본적으로 바뀌지는 않았다.

조금 더 들여다보니, 같은 API 응답을 매번 새로 요청하고 있다는 점이 눈에 들어왔다. 수업 정보, 튜터 정보처럼 자주 바뀌지 않는 데이터인데도 매 요청마다 원본 API를 계속 두드리고 있었다. EKS 환경에서 여러 Pod가 동시에 이런 요청을 보내니, 부하가 몰리는 시간대에는 여기서 병목이 생겼다.

그래서 API 응답 캐싱을 도입했다. 자주 바뀌지 않는 데이터는 Redis에 캐싱해두고, 일정 시간 동안은 캐시된 값을 읽도록 바꿨다. Pod 메모리도 256Mi에서 512Mi로 올렸다.

이 변화가 가장 큰 효과를 냈다. 성공률이 눈에 띄게 올랐다.

다음으로 HPA(Horizontal Pod Autoscaler) 설정을 손봤다. 처음에는 점진적으로 스케일업하도록 튜닝했는데, 수업 시간대처럼 트래픽이 짧은 시간 안에 치고 올라가는 상황에서는 이 접근이 따라가지 못했다. 그래서 좀 더 공격적으로 스케일업하도록 다시 설정했다.

마지막으로 Probe 설정을 추가했다. startupProbe, livenessProbe, readinessProbe 세 가지를 모두 걸었다. 이게 없으면 비정상 상태의 Pod가 계속 트래픽을 받는다. Probe를 추가한 이후부터는 지표가 안정적으로 유지되는 걸 보면서 안심할 수 있었다.

이 과정을 겪으면서, 나한테는 세 가지 정도가 또렷하게 남았다.

  • 캐싱이 생각보다 훨씬 강력하다.
  • Probe가 없으면, 어디선가 한동안은 좀비 Pod가 트래픽을 받고 있을 가능성이 크다.
  • "이러면 빨라지겠지"라는 느낌만으로 손대지 말고, 측정 → 가설 → 실험 → 검증의 사이클을 계속 돌려야 한다.

5초 안에 롤백할 수 있는 배포 시스템

성능 문제를 어느 정도 정리하고 나니, 다음으로 눈에 들어온 건 배포 안정성이었다.

멀티존 구조에서는 배포가 특히 까다롭다. 튜터 앱(Nuxt)과 학생 앱(Next.js)이 서로 의존성이 있는 상태에서, 한쪽만 먼저 새 버전으로 올라가면 API 호환성 문제가 생길 수 있다. 기존에는 Rolling Deployment를 쓰고 있었는데, 배포 중간에 구 버전과 신 버전이 섞여 있는 시간이 생겼다. 이 구간이 항상 불안했다.

Rolling에서 Blue-Green으로

그래서 배포 전략을 Blue-Green으로 바꾸기로 했다.

구조는 대략 이렇게 잡았다.

  1. 태그 푸시 → ECR에 새 이미지 생성
  2. Blue 환경 배포 → 외부에서는 보이지 않는 상태에서 새 버전 기동
  3. 기본적인 검증이 끝나면 Green 환경에도 배포
  4. 검증 완료 시 Service selector를 바꿔 트래픽을 새 버전으로 전환
  5. 문제 발생 시 selector만 다시 돌려서 수 초 내 롤백

핵심은 두 버전이 동시에 떠 있다는 점이다. 문제가 생겼을 때 코드를 되돌리고 다시 빌드·배포하는 게 아니라, 이미 떠 있는 구 버전으로 트래픽만 다시 돌리면 된다.

Keel Approve 기반 반자동화

완전 자동 배포는 우리 상황에서는 위험하다고 판단했다. 그래서 Keel을 도입해서 반자동 흐름을 만들었다.

  • Keel이 태그 푸시를 감지하면 Blue 환경에 자동 배포
  • 운영자가 확인 후 Approve를 누르면 Green에도 반영
  • 승인 없이는 프로덕션으로 나가지 않음

이 구조 덕분에 속도와 안정성을 어느 정도 같이 가져갈 수 있었다. 특히 멀티존 환경에서 Nuxt와 Next.js 사이의 배포 조합이 꼬이지 않도록 관리하는 데 도움이 됐다.

첫 롤백, 그리고 우리가 부족했던 것

시스템을 만들어두고 얼마 지나지 않아 실제로 롤백을 해야 하는 순간이 왔다.

시스템을 만들어두고 얼마 지나지 않아 실제로 롤백을 해야 하는 순간이 왔다.첫수업독려 기능을 배포했을 때였다. iframe 기반으로 MFA(Micro Frontend Architecture)를 적용했는데, 특정 고객들에게 수업 입장이 안 되는 문제가 터졌다. 핵심 플로우가 막혔기 때문에, 나는 바로 롤백을 제안했다.

그런데 여기서 문제가 생겼다.

테크팀은 "롤백 시스템이 잘 동작하네, 바로 돌리자"는 반응이었는데, 다른 팀들은 당황한 기색이 역력했다.

  • "배포한 걸 다시 되돌린다는 게 무슨 의미인가요?"
  • "그럼 기능 출시는 어떻게 되는 건가요?"

같은 질문들이 쏟아졌다.Slack에서 몇 차례 메시지가 오가는 동안, 나는 비로소 깨달았다.

우리는 롤백이라는 개념 자체를 팀 전체와 제대로 공유한 적이 없었다. 테크팀 입장에서는 당연한 선택지였지만, 다른 팀들에게는 처음 듣는 얘기였던 거다.

결국 롤백은 진행했다. selector만 바꿔서 5초 만에 구 버전으로 전환됐다. 수업 입장 문제는 바로 해결됐다.

그날, 마케팅 디자이너 동료분이 이런 말을 했다. (지혜님 미안합니다)

웃기면서도 정확한 비유였다. ㅋㅋㅋ

하지만 롤백을 왜해야하는지?에 대한 공유가 잘 되지않았을까 라는 생각이 들었다.

우리는 기술적으로는 롤백 시스템을 잘 만들었지만, 언제, 왜 롤백을 해야 하는지에 대한 팀 차원의 합의가 없었던 거다.

함께 기준을 만들어가기며칠 뒤, 팀 전체가 모여서 회의를 했다.

정리된 기준은 단순했다.

  • 수업 입장에 영향이 있으면 롤백
  • 그 외는 가능한 선에서 핫픽스

이 기준이 생기고 나서, 장애 대응이 훨씬 빨라졌다. 버그가 터졌을 때 Slack에 "이거 수업 입장에 영향 있어요?"라는 질문 하나면 방향이 정해졌다.

예전처럼 "롤백할까요, 핫픽스할까요"를 30분씩 논의할 필요가 없어졌다.

그리고 중요한 건, 이 과정을 거치면서 롤백이 실패가 아니라 안전장치라는 인식이 팀 전체에 자리 잡았다는 점이다. 처음에는 "롤백 = 뭔가 잘못됐다"는 느낌이 강했다면, 지금은 "롤백 = 빠르게 복구하고 제대로 고칠 수 있는 기회"로 받아들이게 됐다.

함께 일한 사람들

돌아보면, 이 회사에서 가장 많이 배운 건 기술이 아니라 사람이었다.

이 사진은 우리 포도 서비스의 1주년을 맞아서 초를 불었던 Monthly 사진이다. 포도팀 사람들과 일하는 게 너무 행복했었다.

위닝마인드를 심어준 테크리드

팀 테크리드는 에너지가 많은 사람이었다. 회의실에 있으면 자연스럽게 중심이 되는 타입이었다.

그분의 인상적인 지점은 위닝마인드였다. 어려운 문제가 나와도 "이건 우리 팀이 해낼 수 있다"라는 태도를 먼저 보여줬다. 처음에는 "저게 말처럼 쉽나" 싶다가도, 실제로 하나씩 결과를 만들어내는 걸 보면서 납득하게 됐다.

말뿐이 아니라 직접 손을 대서 구현하고, 눈에 보이는 개선을 만들어냈다. 그 과정을 반복하면서 팀 전체의 분위기가 조금씩 바뀌었다. "우리가 하면 된다"는 감각이 생겼다.

그분에게서 배운 건, 기술적으로 뛰어난 것과 별개로 팀이 할 수 있다고 믿게 만드는 역할이 존재한다는 점이었다. 리더가 먼저 가능성을 믿고, 그걸 결과로 연결시킬 때 팀의 기준이 올라간다는 걸 가까이에서 봤다.

웃으면서 "왜?"를 물어보는 PO

팀 PO는 늘 웃으면서 "왜?"를 물었다.

"이 기능 왜 이렇게 만들었어요?"
"이 플로우, 유저 입장에서 보면 어떤 장점이 있어요?"
"여기서 유저가 왜 이탈한다고 생각하세요?"

분위기는 부드러운데, 질문은 가볍지 않았다. 답을 대충 할 수가 없었다.

한번은 결제 페이지 개편을 얘기하면서 "이렇게 하면 구조가 더 깔끔해요"라고 설명했다가, "그렇게 되면 유저 입장에서는 뭐가 좋아지나요?"라는 질문을 받았다. 그 자리에서 바로 답을 못했다. 그날 이후로는 뭔가를 바꾸기 전마다 "이게 유저에게 어떤 차이를 만들어낼까"라는 질문을 먼저 떠올리게 됐다.

그렇게 잡도리를 당하면서, 기술적으로 예쁜 것과 사용자에게 도움이 되는 것 사이에 항상 간격이 있다는 걸 다시 느꼈다.

레거시를 다르게 보게 해준 동료

PHP 레거시 시스템을 오래 담당해 온 동료가 있었다. 처음에는 "고생이 많겠구나" 정도로 생각했다.

코드를 같이 보다가 그분이 이런 말을 했다.

"이 코드가 왜 이렇게 되어 있는지 알아요?"

그러더니 한 줄 한 줄에 얽힌 사정을 들려줬다. "당시에 긴급하게 배포해야 해서 이렇게 우회했어요", "저 라이브러리가 그때는 버그가 있어서, 이게 최선이었어요" 같은 이야기였다. 레거시는 그냥 "나쁜 코드"가 아니라, 그 시점에 주어진 조건과 시간 안에서 나온 선택이라는 걸 알게 됐다.

그분 덕분에 나는 레거시를 욕하는 사람에서 레거시를 이해하고, 옆에 새 길을 하나 더 내는 사람 쪽으로 조금씩 옮겨갔다. 이건 내 태도에서 가장 크게 바뀐 부분 중 하나다.

나는 어떻게 변했을까

입사 전의 나와 지금의 나를 비교해보면, 몇 가지는 확실히 달라졌다.

기술 위주에서 제품/유저 중심으로

예전에는 "이 아키텍처가 더 우아하다", "이게 더 깔끔하다"가 판단의 기준이었다면, 지금은 그 앞에 이런 질문이 먼저 온다.

"이 구조가 비즈니스 관점에서 어떤 차이를 만들까?"

GA 추적 개선은 그 대표적인 예였다. GA 설정을 손본다는 건 기술적으로 보면 작은 작업일 수 있다. 하지만 그게 마케팅팀의 캠페인 분석으로 이어지고, 예산 배분과 전략 수정으로 이어지고, 결과적으로 매출과 연결된다. 그 흐름을 실제로 보면서, "기술적인 개선"을 넘어서 "제품과 비즈니스에 미치는 영향"까지 생각하게 됐다.

혼자 파는 타입에서 함께 목적을 맞추는 타입으로

예전에는 "일단 내가 다 해볼게요"라는 태도가 익숙했다. 빨리 움직이는 것처럼 보일 때도 있었지만, 팀 관점에서 보면 좋은 방식은 아니었다.

지금은 "이 일을 왜 하는지"를 먼저 맞추려고 한다. 같은 문제를 보고 있어도 각자 머릿속에 떠올리는 화면이 다르면, 결국 엇갈린다. 그래서 시작할 때 가능한 범위 안에서 목적과 기준을 같이 정리하려고 한다. 그 위에서 "누가 어떤 역할을 맡으면 좋은지"를 나누는 게 더 자연스럽다는 걸 조금씩 체감했다.

레거시를 대하는 태도

레거시는 어디에나 있다. 욕한다고 사라지지 않는다. 중요한 건 그 위에 무엇을 쌓고, 어떻게 서서히 바꾸느냐다.

포도스피킹에서의 1년 2개월은, 레거시를 무시하거나 밀어버리려 하기보다 옆에 새 길을 만들고, 트래픽을 조금씩 옮겨가는 방식에 익숙해지는 시간이었다.

아쉬웠던 점

좋았던 점만 있는 시간은 아니었다. 돌아보면 몇 가지는 분명히 아쉽다.

GitOps 전환을 끝까지 보지 못했다

회사 차원에서 ArgoCD 도입을 준비하고 있었다. 중간 단계까지는 같이 따라갔지만, 내가 나갈 때까지 완전히 정착된 모습을 보지는 못했다. 실제로 운영 환경에 GitOps가 안착했을 때 어떻게 달라지는지를 경험해보고 싶었는데, 그 부분은 아쉬움으로 남는다.

학생 페이지 마이그레이션을 마무리하지 못했다

튜터 페이지는 PHP에서 Next.js로 옮기는 작업을 크게 한 사이클 돌렸다. 학생 페이지는 PHP와 Nuxt가 섞여 있던 구조를 Next.js로 통합하는 계획이 잡혀 있었고, 일부는 진행 중이었다. 완전히 정리된 모습을 보지 못한 채 나가는 건 솔직히 마음에 남는다.

팀원들과 더 깊이 이야기할 시간

일에 치이는 날들이 많았다. 그래서 팀원들과 1:1로 깊게 얘기하는 시간을 일부러 만들지는 못했다. 회의와 작업 사이 짧은 대화들로 많은 걸 나누긴 했지만, 퇴사를 앞두고 나니 "그때 좀 더 시간을 냈으면 어땠을까" 싶은 순간들이 떠오른다. 다음 회사에서는 이런 시간을 의식적으로 확보하고 싶다.

좋았지만, 떠나는 이유

데이원은 좋은 회사였다. 빠르게 성장하고 있었고, 기술 선택의 자유도도 높았고, 함께 일한 동료들의 기준도 높았다. BEP를 달성하는 순간까지 옆에서 지켜봤다.

그런데 BEP 달성 전부터, 조직의 무게 중심이 조금씩 옮겨가는 게 느껴졌다. 처음에는 미묘했다. 새로운 프로젝트를 시작하는 속도가 예전보다 조금 더뎌졌고, 리소스 배분의 우선순위가 점차 안정적인 운영 쪽으로 기울어가는 게 보였다.

BEP를 달성하는 순간은 그 변화가 더 명확해진 시점이었다. 성장 단계에서 성숙 단계로 넘어가는 과정에서, 새로운 시도보다는 안정적인 운영과 유지 쪽에 더 많은 리소스가 할당되기 시작했다. 팀 규모도 조정되면서, 예전처럼 크고 새로운 문제를 정의해서 끌고 가는 일은 줄어들었다.

이 변화 자체는 자연스럽다. 제품이 성장하면 언젠가는 안정화로 방향을 잡는 게 맞다.

다만 나는 아직은 제품이 성장하는 과정에서, 처음부터 문제를 정의하고 풀어가는 일에 더 끌린다. 사용자 경험을 개선하고, 실험을 하고, 그 결과를 보고 다음을 고민하는 사이클. 지금은 그 구간에 더 있고 싶다.

지금 회사에서 그런 기회가 완전히 사라진 것은 아니다. 다만 예전에 비해서는 줄어들고 있다는 감각이 있었고, 이 지점에서 한 번 방향을 바꾸는 게 맞겠다는 결론을 내렸다.

그 무렵 토스가 대규모 채용을 진행 중이었다. 만약 좋은 기회가 된다면 언젠가는 가보고 싶었던 회사였는데, 지금 내가 찾고 있던 것과 맞는지 확인해볼 시점이 아닐까 싶었다.

제품이 성장하는 과정에서 문제를 정의하고 풀어가는 일을 다시 해볼 수 있는 곳일 수도 있겠다는 기대가 있었다. 지원 안 할 이유는 없어 보였다.

다음 회사에서 이어가고 싶은 것

다음 회사는 토스플레이스다. 기대와 긴장감이 동시에 있다.

사용자가 성장하는 경험을 다시 설계하고 싶다

포도스피킹에서 가장 재미있었던 일 중 하나는 사용자가 서비스를 통해 성장하는 경험을 설계하는 부분이었다. 한 번 결제하고 끝나는 게 아니라, 수업을 듣고, 복습하고, 다음 수업을 예약하고, 레벨이 올라가는 과정. 그 흐름 안에서 사용자가 스스로 변화를 느끼도록 만드는 일.

토스플레이스도 비슷한 면이 있다고 생각한다. 결제 단말기를 한 번 판매하고 끝나는 게 아니라, 사업자가 플랫폼을 통해 매장을 운영하고, 데이터를 보고, 거기서 얻은 인사이트로 더 나은 선택을 하고, 그 결과가 매출과 운영에 반영되는 경험. 에듀테크에서 학생의 성장을 도왔다면, 이번에는 사업자의 성장을 돕는 쪽으로 무대만 바뀐 느낌이다.

한 번의 거래로 끝나지 않고, 계속해서 쓰고 싶어지는 경험을 어떻게 만들 것인가.
이 질문을 다시 붙잡고 일할 수 있으면 좋겠다.

더 큰 스케일에서 다시 검증해 보고 싶다

데이원에서 배운 것들—성능 최적화 사이클, 분산 시스템 설계, 배포 안정성—을 더 큰 스케일과 다른 제약을 가진 조직에서 다시 시험해보고 싶다. 같은 접근이 통할지, 아니면 전혀 다른 방식이 필요할지, 몸으로 확인해보고 싶다.

비교하고 배우기

한 조직에서 오래 있으면, 어느 순간 "우리는 이렇게 한다"가 기준이 되기 쉽다. 다른 조직, 다른 문화, 다른 제품을 겪어보면서 내가 지금까지 쌓아온 기준이 어느 부분에서는 유효하고, 어느 부분에서는 수정이 필요한지 배우고 싶다.

프론트엔드 플랫폼 관점 넓히기

디자인 시스템, 개발자 경험, 모니터링 같은 프론트엔드 플랫폼 영역에 더 깊게 관여하고 싶다. 피처 개발을 잘하는 것도 중요하지만, 팀 전체의 생산성을 끌어올리는 기반을 설계하는 일에 더 많은 시간을 쓰고 싶다.

마무리

데이원에서의 1년 2개월은, 나에게는 "버그를 고치는 개발자"에서 "시스템을 설계하고 관찰하는 개발자"로 옮겨가는 시기였다.

BEP 달성 순간을 보면서 이런 생각을 했다.

결국 코드는 상품 그 자체가 아니라, 상품이 고객에게 닿는 길을 만드는 도구다.

이 감각을 다음 회사에서도 잊지 않고 가져가고 싶다.

나는 어떤 개발자이고 싶은가. 제품을 위한 개발자, 유저를 위한 개발자. 그리고 함께 일하는 사람들이 다시 같이 일하고 싶다고 떠올릴 수 있는 동료.

앞으로도 담담하게, 꾸준히, 좋은 임팩트를 만드는 개발자로 남고 싶다.

진짜 마지막으로

포도의 BEP 달성 회식기념 하는날 우리팀은 마니또를 하기로했었다.

거기서 나의 마니또였던 서현(PO)님은 마니또 선물로 퇴사 케이크를 선물해주셨었다.

(그런데 아래의 코드는 항상 false를 반환하는데... 쩝... 서현님!!!!!!!! 최고~)

if(App.isSlow) {
  miss('Ryan');
  return false // 심지어 조건부 반환이네요...
}

너무 감사해요 서현님 그런데 이거먹고 혓바닥이라 입술이 다 파래져서 양치 세번했어요..!

포도팀 다들 감사했습니다.