3부. 높을수록 얇은 공기
게임팀의 중심은 늘 서버와 클라이언트 개발자들이었다.
내가 맡고 있던 게임웹은 그 옆에서 입구와 운영을 받치는, 한 걸음 비켜선 역할에 가까웠다.
그러다 조직이 흔들리는 틈에서 게임 DBA(Database Administrator) 자리의 공백을 보게 됐다.
라이브 서비스를 앞둔 팀에는 대규모 데이터를 관리할 사람이 절실했지만, 내부에 적임자는 없었다.
게임 서버 개발자들이 임시로 DB 업무를 메우고 있었고, 전문적인 튜닝과 관리까지 기대하기는 어려웠다.
라이브 서비스에서는 게임 서버의 데이터를 책임지는 DBA도 자연히 무거운 자리가 됐다.
실행로그를 들여다보던 나는 아찔해졌다.
인덱스 없이 날아가는 쿼리들이 보였다.
라이브 트래픽이 몰리면 바로 터질 구조였다.
웹 개발자로 일하면서도 나는 늘 데이터베이스에 갈증을 느끼고 있었다.
대학에서 데이터베이스를 전공했고, OCP(Oracle Certified Professional) 자격증도 갖고 있었다.
나는 팀장님을 찾아가 말했다.
"웹은 후임을 채용해 인계하겠습니다. 론칭하려면 누군가는 전담해서 DB 인덱스부터 스키마까지 잡아야 합니다. 전공을 살려서 기여하고 싶습니다."
팀장님은 내가 정리해 간 로그 자료를 훑어보더니 짧게 답했다.
"웹 후임 뽑는 거 전제로, 일단 해봐."
그 한마디로 나는 웹 개발자에서 DBA로 자리를 옮겼다.
문제는 전환이 끝나기도 전에 론칭이 닥쳐왔다는 것이었다.
새로 뽑은 웹 후임은 아직 업무에 완전히 적응하지 못했고, 나는 DBA라는 새 명찰을 달고도 웹 실무까지 함께 짊어진 채 오픈 당일을 맞았다.
특히 게임의 데이터 연동 기능 상당수가 웹뷰(WebView) 형태였기 때문에, 나는 데이터의 안정성과 유저가 진입하는 웹의 입구를 동시에 책임져야 했다.
론칭 스펙은 방대했고, 내 몸은 하나였다.
공들여 준비한 신작이 세상에 나올 날이었다.
모든 준비를 마치고 '오픈' 버튼을 눌렀다.
클릭 한 번이었다.
마우스는 가볍게 '딸깍' 소리를 냈고, 화면도 크게 달라지지 않았다.
이렇게 큰일이 이렇게 작은 소리로 시작된다는 것이 오히려 허무했다.
잠깐의 정적.
그리고 그 정적을 찢듯 알림과 목소리가 몰려왔다.
"웹 안 뜹니다! 게임 진입이 안 돼요!"
웹 론칭 방식으로 게임을 실행하던 구조였기에, 웹이 먹통이 되었다는 건 게임으로 들어가는 입구가 통째로 막혔다는 뜻이었다.
몇 년 전 수습 시절의 악몽이 스쳐 갔다.
지금의 나는 멘붕에 빠지는 대신 곧장 인프라 모니터링 툴을 켰다.
웹 서버 CPU는 평온했다.
평일 오전이라 트래픽이 폭발할 시간도 아니었다.
진짜 범인은 엉뚱한 곳에 있었다.
DB CPU가 100%를 찍으며 비명을 지르고 있었다.
급히 쿼리 로그를 뒤졌다.
범인은 게임 서버에서 날아오는 '캐릭터 확인' 로직이었다.
개발과 테스트 환경에서는 데이터가 적어 문제가 없었다.
라이브 데이터가 쌓이기 시작하자, 최적화되지 않은 쿼리가 인덱스 없이 수백만 행을 처음부터 끝까지 훑고 있었다.
그걸 수천 명이 동시에 하고 있었다.
CPU가 꽉 차버리자 DB는 어떤 작업도 처리하지 못하는 마비 상태에 빠졌고, 그 여파가 웹 서버까지 번져 게임의 입구를 막아버렸다.
"일단 서버 내리세요! 해당 요청 유입 차단합니다!"
작업 공간을 확보하기 위해 연결부터 끊어냈다.
그리고 미친 듯이 명령어를 입력했다.
누락된 인덱스를 생성하는 명령어를 입력하는 짧은 시간 동안 등줄기에 식은땀이 흘렀다.
서버나 클라이언트는 파일을 갱신하면 그만인 경우가 많지만, 데이터베이스는 운영 중인 데이터를 그대로 둔 채 손봐야 했다.
데이터를 유지한 채 구조를 손봐야 하고, 조회 특성에 맞게 인덱스를 설계해야 한다.
그런데 론칭 당일의 수많은 웹 작업에 치여, 정작 내가 DBA로서 끝까지 챙겼어야 할 최적화 반영을 놓쳤다.
인덱스 생성이 끝나고 서버를 다시 올리자, 트래픽이 다시 흐르기 시작했다.
"웹 뜹니다! 유저들 들어오기 시작해요!"
사무실 여기저기서 안도의 한숨이 터져 나왔다.
하지만 나는 고개를 들 수 없었다.
이건 명백한 내 실패였다. 내가 DBA였으니까.
사무실 불이 하나둘 꺼지고, 모니터만 남은 자리에서 나는 한참을 앉아 있었다.
화면에는 내가 빠뜨렸던 인덱스 생성 스크립트가 아직 열려 있었다.
빠뜨린 건 몇 줄 안 되는 인덱스 생성 스크립트였다.