군 입대 세 시간 전까지 숙소에서 노트북을 두들기게 만들던 문제가 있었다. 서비스에 사용하려고 하던 GCP 프리티어 VM이 자꾸 죽는 현상이었다. 짐작되는 문제들을 해결하는 코드를 푸시해 넣고 문제가 발생하지 않기만을 바랐다. 나의 힘으로만 빌드한 첫 번째 서비스의 인프라 문제를 해결하지 못하면, 앞으로도 나의 서비스를 평생 만들지 못할 것 같았다.
결국 그 문제는 입대 전까지 해결되지 않았고 이후로 3달간 나를 괴롭혔다. 이 문제를 오래 끈 진짜 병목은 원인 후보가 없다는 점이 아니라, 정확히 무엇이 문제인지 비교할 수 있는 기록 구조(observability)가 부족했다는 점이다. 이미 각종 관측 도구들은 붙어 있었다. GCP 로그도 있었고, 애플리케이션 로그도 있었다. 하지만 이것들을 정확한 타임스탬프를 기준으로 하나로 통합할 생각은 하지 못했다. VM 내부 이상, 컨테이너 이상, 프록시 이상, 외부 API 지연이 같은 시간축 위에 나란히 놓이지 않으면, 맞는 가설을 세우는 일보다 틀린 가설을 버리는 일이 더 어려워진다. 메모리 지표는 뚝뚝 끊기는데 CPU, 디스크, 네트워크 로그는 점진적으로 감소하고, nginx에서는 timeout이 보이고, 로그는 어느 순간부터 조금씩 밀리더니 한참 뒤에 뒤늦게 밀려 올라왔다. 정말 미칠 노릇이었다. 하드웨어 계층: 디스크 I/O 병목인가? 운영체제 계층: 파일 디스크립터 고갈인가? 네트워크 계층: 프록시의 타임아웃인가? 애플리케이션 계층: n8n 또는 내가 작성한 코드의 문제인가? 같은 가설이 모두 부분적으로만 맞아 보였다.
이 사례를 비롯하여 지금까지 내가 겪었던 소프트웨어 장애뿐 아니라 모종의 문제 해결 과정에서 적어 나간 메모들을 돌아보았을 때 반복적으로 보이는 나의 습관은 문제 해결이 직관에 의존하며, 그렇기에 불필요한 스택을 깊게 파보게 된다는 것이다. 특히, 원인의 후보가 많을 때, 서로 다른 계층에서 이상 신호가 한꺼번에 겹쳐 보일 때 약하다. 거시적으로 하나씩 소거를 하기보다는 무엇이 문제일 것이라는 생각에 사로잡혀 학문적으로/논리적으로 그 생각이 참이다/거짓이다가 자명해질 때까지 개념을 찾아보는 습관이 있다. 나는 이를 연역의 습관, 고등학생/취준생/대학원생 습관이라고 부른다.
빠른 문제 해결이 중요하다면 이런 상황에서 가져야 할 태도는 이진 탐색이다. 가령 사양이 의심된다면 돈을 지불해서라도 훨씬 넉넉한 VM에 동일한 환경을 세팅해서 ‘일단 돌아가는 상태’를 확보해야 한다. 그리고 나서 문제를 좁혀 나갈지를 결정하고, 이때는 정확한 관측가능성을 최대한 확보하여 로그를 통합하고 원인 후보를 소거해 나갈 수 있도록 할 것이다.
<aside>
언젠가 이 메모에 쓰이면 좋을 것 같은 재료들입니다.
<aside>
from: 이 메모에 쓰인 생각을 만든 앞의 생각들입니다. 앞의 생각과 연관관계를 설명합니다.
<aside>
supplementary: 이 메모에 작성된 생각을 뒷받침하는 생각의 새로운 메모입니다.
</aside>
<aside>
opposite: 이 메모에 작성된 생각과 대조되는 생각의 새로운 메모입니다.
</aside>
<aside>
to: 이 메모에 작성된 생각으로부터 발전된 생각의 새로운 메모입니다.
</aside>
<aside>
ref: 생각에 참고한 자료입니다.
</aside>
영구메모 템플릿 버전 2026.03.20