대진표를 엑셀로 짜면 세 시간 - 급수와 소속을 동시에 만족시키는 조 편성
대회 전날 밤에 임원들이 엑셀을 붙잡고 있었다. 참가 신청서를 보고 복식 조를 짜고, 대진표를 그리고, 같은 동호회끼리 1회전에서 만나면 지웠다가 다시 그렸다. 매번 세 시간쯤 걸린다고 했다.
대회 전날 밤에 임원들이 엑셀을 붙잡고 있었다. 참가 신청서를 보고 복식 조를 짜고, 대진표를 그리고, 같은 동호회끼리 1회전에서 만나면 지웠다가 다시 그렸다. 매번 세 시간쯤 걸린다고 했다.
엑셀 업로드 한 번에 메모리 그래프가 수직으로 올라갔다. 4GB 서버에서 3.1GB. 남은 게 900MB였다.
요구사항을 듣다가 멈칫한 부분이 있었다. “기존 동호회에서 승인을 안 해주면 어떻게 되나요?” 답은 “그러면 못 옮긴다”였다. 그게 기능 명세가 아니라 현재 상황이었다.
통합 인증 전환은 1시간 점검으로 끝났다. 문제는 그다음 주에 왔다. “갑자기 로그아웃돼요”라는 문의가 들어오기 시작했다.
“이거 그냥 새로 만들면 안 되나요?” 처음에 나도 그렇게 생각했다. 10년 넘게 쌓인 PHP 코드를 보면 누구나 한 번은 그 생각을 한다.
레거시 PHP를 Java로 이관하면서 가장 무서웠던 건 성능이 아니었다. 다른 학원의 학생 명단이 보이는 것이었다.
“PHP Fatal Error 발생 → 사내메신저 알림 확인 → 코드 확인 → 원인 분석 → 수정 → PR 생성 → 코드 리뷰 → 배포”. 에러 하나에 평균 1시간. 매번 같은 패턴인데 매번 사람이 해야 했다. “이걸 AI가 하면 안 되나?” 생각이 들었고, 그냥 만들어봤다.
레거시 코드를 리팩토링하면 “잘 동작하는지 어떻게 확인하지?”가 항상 문제였다. 테스트 DB를 쓰면 운영 데이터랑 조건이 달라서 미심쩍고, 운영 DB를 쓰면 데이터가 오염된다. 트랜잭션 롤백으로 이 딜레마를 해결했다.
“슬로우 쿼리 로그 좀 켜볼까요?” 학원 ERP 서비스에서 간헐적으로 API 응답이 느려지는 문제가 있었다. 슬로우 쿼리 로그를 켜보니 원인이 보였다. 하루 평균 15~20건. 인덱스 문제가 아니라 쿼리 구조 자체가 문제였다. 막상 보니 고칠 수 있겠다 싶었다.
“이 코드 누가 짰어요?” 입사 첫 날 코드베이스를 열었을 때 나온 말이다. 컨트롤러 하나에 SQL, 비즈니스 로직, SMS 발송까지 다 들어있었다. 욕이 먼저 나왔고, 그 다음에 어디서부터 건드려야 하나 막막했다.
여러 서비스가 각자 로그인 시스템을 갖고 있으면 사용자는 서비스를 이동할 때마다 다시 로그인해야 한다. 사용자 불만 접수가 계속 들어오는 걸 알면서도 한동안 미뤘다. 세 팀이 동시에 움직여야 하는 작업이라서 조율이 부담이었다. 결국 점검 시간 1시간으로 끝냈다.
실시간 배차 서비스에서 20~30명의 기사가 동시에 수주 버튼을 누르면 어떤 일이 발생할까? 답은 “두 명이 동시에 수락 완료된다”였다. 로그를 처음 봤을 때 이게 실제로 일어나고 있다는 게 믿기지 않았다.
배차 서비스에서 새 배차가 등록되면 모든 기사에게 알림을 보내고 있었다. 서울 기사에게 부산 배차 알림이 가는 게 말이 안 됐다. 기사들 불만이 쌓이다가 배차 수락률이 40%까지 떨어지고 나서야 손댔다.
기사님들이 “새 수주가 늦게 뜬다”고 했다. 로그를 보니 늦게 뜨는 게 아니라, 앱이 늦게 물어보고 있었다.
방문차량 QR 출입을 붙이고 테스트하러 지하주차장에 내려갔다. 리더기가 QR을 읽고 멈췄다. 서버 응답을 기다리다 타임아웃이 났다. 지하 2층에는 신호가 거의 없었다.
“결제 연동 문서 좀 주세요”라고 했더니 .asmx?wsdl 링크가 왔다. 2022년에 SOAP을 만질 일이 있을 거라고는 생각해본 적이 없었다.
main.py를 열었더니 include_router가 60줄 가까이 이어져 있었다. 도메인을 하나 추가하면 네 군데를 고쳐야 했고, 어느 날 하나를 빼먹어서 API가 404를 냈다.
공동주택 관리 서비스를 만들 때, 팀 기술 스택을 Python/FastAPI로 결정했다. Node.js, Django, Spring Boot 등 여러 선택지가 있었는데 왜 FastAPI였을까? 6개월 지나고 나서 “잘 골랐다”는 생각이 들었던 순간들이 있다.
결제 연동을 처음 붙일 때 가장 자연스러워 보이는 흐름이 있다. 결제창이 성공을 알려주면, 그 결과를 서버에 보내서 저장하는 것이다. 이게 왜 위험한지는 개발자 도구를 한 번 열어보면 알게 된다.
인플루언서 매칭 플랫폼을 운영하면서 블로거 지수 분석 기능을 만들었다. 블로그 데이터를 크롤링하고 여러 지표를 계산해서 점수를 매기는 기능이다. 처음 배포하고 나서야 알았다 — 분석 요청 하나가 들어오면 서버 전체가 멈춘다는 걸.
“이 블로거의 영향력이 얼마나 되나요?” 인플루언서 매칭 플랫폼을 만들면서 광고주가 가장 많이 하던 질문이다. 팔로워 수나 방문자 수는 조작 가능하다. 그래서 “조작하기 어려운 지표”를 기준으로 알고리즘을 짜기로 했다.
OddsPortal에서 실시간 배당 데이터를 스크래핑하는 엔진을 구축했다. 외부 사이트는 예고 없이 DOM 구조를 바꾼다. 어느 날 아침 출근하니 데이터가 멈춰 있었고, 원인은 사이트가 디자인을 바꿔버린 것이었다. 그때부터 “어떻게 하면 그 다음에는 이런 일이 안 생길까”를 고민했...
4 vCPU / 4 GB VPS 한 대. 여기에 운영 서비스와 DB와 모니터링과 개발 환경을 다 올려야 했다. 늘릴 수 없으니 안 쓰는 걸 줄이는 수밖에 없었다.
크론 서버가 죽었는데 아무도 몰랐다. 청구서 발행이 안 돼서 학부모 문의가 폭주하고 나서야 알게 됐다. 그때 제일 당황한 건 “왜 몰랐지?”가 아니라 “이게 언제부터였지?”였다.
“배포할게요, 잠깐만요.” 매주 금요일 오후 4시, 배포 담당자가 서버에 SSH 접속해서 git pull → docker-compose restart를 실행한다. 배포가 끝나면 직접 브라우저를 열어서 주요 기능을 확인한다. 언젠가부터 이 루틴이 너무 지겨워졌다.
2025년부터 AI 코딩 도구를 실무에 쓰기 시작했다. 처음엔 반신반의했다. “AI가 코드를 짠다고?” 1년 지나고 보니 생각이 바뀌었다. AI는 코드를 짜는 게 아니라, 내가 코드 짜는 방식을 바꿔놓았다.
프리랜서로 일하면서 가장 힘들었던 건 다른 개발자가 남긴 코드였다. 처음 코드베이스를 받았을 때, 어디서부터 건드려야 할지 막막했다.
공동주택 관리 서비스 팀에 백엔드 주니어 1명, 프론트 주니어 1명이 들어왔다. 처음엔 솔직히 막막했다. 내가 직접 혼자 다 하는 게 빠른데, 이걸 같이 하면서 어떻게 성장까지 시키지? 3개월 후 이들은 독립적으로 기능을 개발하고 배포할 수 있는 개발자가 됐다.