자정이 넘은 새벽, 슬랙 알림음이 고요한 방을 깨운다. 서버 응답이 없다는 메시지가 핸드폰 화면을 물들이고, 순간 잠이 다 깬다. 베개 옆에서 자고 있던 아내와 아이들을 깨우지 않으려 발소리를 죽이며 거실로 나와 노트북을 연다. 배포 버튼을 누르는 순간의 떨림과는 또 다른 종류의 공포가 밀려온다. 이미 일어난 일에 대한 책임감, 빠르게 복구해야 한다는 압박감, 그리고 혹시나 더 큰 문제로 번질지도 모른다는 불안감이 어깨를 짓누른다.
운영 환경이란 그런 곳이다. 완벽하게 준비했다고 생각했던 코드가 예상치 못한 접속자 폭증 앞에서 무너지고, 테스트 환경에서는 멀쩡했던 기능이 실제 사용자들의 다양한 사용 패턴 앞에서 오작동을 일으킨다. 스테이징 환경(실제 서비스와 동일한 조건으로 만든 연습용 공간)에서 아무리 많은 시나리오를 검증해도, 실제 세상은 언제나 우리의 상상을 뛰어넘는 예외 상황들을 던져준다. 그래서 개발자는 운영 환경에 대한 경외심을 갖는다. 운영 환경에서만큼은 개발자들은 상당한 보수주의자가 된다.
에러 기록을 따라가다 보면 때로는 한 줄의 코드 때문에 전체 시스템이 마비된 것을 발견한다. 반복 작업 중에서 잘못된 조건 하나, 데이터를 잘못 불러온 실수 하나가 메모리 과부하를 일으키고, 그것이 서버 전체를 다운시킨다. 동료들과의 검토 과정에서 "이 정도는 괜찮겠지"라고 넘어갔던 부분이, 실제 운영 환경에서는 치명적인 약점이 되어 돌아온다. 개발자가 운영 환경을 두려워하는 이유는 이런 나비효과 때문이다. 작은 변화가 예측할 수 없는 거대한 파장을 만들어낸다.
지난주 저녁, 일곱 살 큰딸이 "아빠, 내가 그린 그림 어때?" 라며 자랑스럽게 보여줬을 때, 나는 일을 하느라 정신없이 바빠서 "응, 예쁘네"라고 대충 대답했다. 그 순간 아이의 눈빛이 조금 꺼지는 것을 보았지만, 급한 업무에 쫓겨 있던 나는 그냥 넘어갔다. 며칠 뒤 아이가 그림을 다 그리고도 나에게 보여주지 않고 서랍에 넣어두는 것을 보았다. 네 살 둘째가 "언니, 아빠한테 보여줘"라고 하자 큰딸이 "아빠는 바빠서 안 봐도 돼"라고 말하는 것을 들었을 때, 가슴이 철렁 내려앉았다. 내가 무심코 흘린 한 마디가, 바쁘다는 이유로 성의 없이 넘어간 그 순간이, 아이에게는 얼마나 큰 상처였을지를. 아이의 마음에는 되돌리기 버튼이 없다. 한 번 입력된 상처는 다시 지울 수 없다. 테스트 환경이 없는 운영환경이다.
테스트 환경이 없는 상황에서 개발할 때 가장 중요한 것은 방어적 프로그래밍이다. 모든 가능성에 대해 예외 상황을 미리 대비하고, 오류가 발생할 수 있는 부분들을 안전장치로 감싸고, 빈 데이터가 들어올 경우를 여러 번 확인한다. 코드의 읽기 편함이 떨어지더라도 안정성을 우선시한다. 동료들과의 검토 과정에서도 "이런 경우는 어떻게 될까요?"라는 질문을 끊임없이 던진다. 성능보다는 안전함을, 빠른 배포보다는 확실한 검증을 선택한다. 때로는 답답하지만, 이런 신중함이 시스템을 지켜낸다.
아이들을 키우는 것도 마찬가지다. 두 딸과 함께하는 모든 순간에 예외 상황 대비가 필요하다. 큰딸이 학교에서 친구들과 갈등이 있을 때, 둘째가 처음 보는 놀이기구를 타려 할 때, 두 아이가 싸우기 시작할 때, 항상 "혹시나"를 생각해야 한다. 하지만 아이들을 키우다 보면 예상치 못한 상황들이 계속 발생한다. 큰딸이 갑자기 어린이집에 가기 싫다고 하거나, 둘째가 밤중에 무서운 꿈을 꿨다며 울거나, 자매가 서로 질투하며 싸우거나, 그럴 때마다 나는 깨닫는다. 아이라는 시스템에는 완벽한 예외 처리가 불가능하다는 것을. 그래서 더욱 조심스러워진다. 매순간이 실제 서비스 환경에서의 실시간 작업이니까 항상 긴장해야 한다.
휴가를 가더라도 노트북이 없으면 몹시 불안한다. 서버는 언제 어떻게 다운될지 모른다. 그에 대한 여러가지 장치들이 있지만 그 장치들을 뚫고도 다운되는 경우도 있다. 서버가 다운되면 개발자는 바로 노트북을 펼쳐야 한다. 시스템 상태를 확인하고, 오류 기록을 추적하고, 코드와 데이터베이스 상태를 점검한다. 원인을 찾을 때까지 포기할 수 없다. 사용자들이 서비스를 이용할 수 없는 시간이 길어질수록 비즈니스에 미치는 영향이 커지기 때문이다. 빠른 임시 조치로 서비스를 복구한 후에는 근본 원인을 찾아 재발 방지책을 마련한다. 실패로부터 배우는 것, 그리고 같은 실수를 반복하지 않는 것이 개발자의 성장이다.
새벽 두 시에 둘째가 "아빠"를 부르며 울음을 터뜨리면 부모는 잠옷 차림으로 아이 방으로 달려간다. 열이 있는지 확인하고, 목이 마른지 살펴보고, 무서운 꿈을 꾸었는지 물어본다. 아이가 다시 잠들 때까지 포기할 수 없다. 아이의 울음에는 반드시 이유가 있고, 그것을 찾아내는 것이 부모의 역할이다. 때로는 해결책이 보이지 않아 함께 울고 싶을 때도 많다. 그래도 참고 견디고 이해해야 한다. 지금의 나의 언행이 아이에게는 롤백할 수 없는 상처가 되기도 소중히 간직할 추억이 되기도 하기 때문이다.
지금 생각해보면, 두 딸은 내 인생에서 가장 중요한 운영 환경이다. 테스트 단계를 거칠 수 없고, 되돌릴 수도 없고, 매 순간이 실시간 적용이다. 코드는 버전 관리 시스템에 이전 상태들이 모두 기록되지만, 아이들과의 순간들은 한 번 지나가면 다시 오지 않는다. 그 소중함과 무게감 앞에서 나는 오늘도 한 걸음 한 걸음 신중하게 살아간다. 프로그램은 오류가 생기면 수정할 수 있지만, 상처받은 마음은 업데이트로 고칠 수 없다. 그리고 내가 잘 한다면 이 시간들이 아이들에게 아빠와의 소중한 추억이 될 것이다.
개발자로서 배운 것은 완벽한 시스템은 존재하지 않는다는 사실이다. 아무리 꼼꼼하게 설계해도, 아무리 많은 테스트를 거쳐도, 언젠가는 예상치 못한 문제가 발생한다. 중요한 것은 그때 얼마나 빠르게 대응하고, 얼마나 진심으로 문제를 해결하려 노력하느냐다. 부모도 마찬가지다. 완벽한 부모는 없다. 하지만 사랑이라는 이름의 안전장치가 있다면, 어떤 오류라도 함께 극복해낼 수 있다. 그리고 그 과정에서 우리는 더 나은 사람이 되어간다. 운영 환경에서 직접 코드를 수정하듯 조심스럽게 말이다.