Skip to content
isdnetworks
Go back

되돌리니 멎었다, 그런데 원인은 모른다

(수정됨)

이미지 처리 엔드포인트 /image/resize 에서 시간 초과가 나기 시작했고 직전 배포를 git revert 로 되돌리자 멎었다. 그 배포가 원인이라고 적었는데 그 배포에는 기능이 세 개 들어 있었다.

Table of contents

Open Table of contents

상황 — 되돌림이 지운 것

되돌린 커밋에는 quality 를 요청마다 정하는 동적 압축 도입과 ratio 상한 처리와 요청 url 검증이 함께 들어 있었다. 증상이 멎은 것은 셋 중 하나 때문인데 어느 것인지는 되돌림이 알려 주지 않는다.

더 곤란한 것은 나머지 둘이 함께 사라졌다는 점이다. url 검증은 외부에서 들어온 주소로 127.0.0.1 이나 10.0.0.0/8 같은 내부망을 찌르는 것을 막는 장치였고 이번 오류와 아무 관계가 없었다. 증상은 멎었고 무관한 보호는 없어진 상태로 며칠이 지났다.

판단 기준 — 실측치와 한계치의 자릿수 차이

의심한 것은 동적 압축이었다. imagejpeg() 인코딩이 한 번 더 도니 느려졌을 것이라고 봤고 그럴듯했다. PHP 매뉴얼의 imagejpeg 항목대로 quality 는 0~100 이고 기본은 IJG 기본값인 75 쯤이라, 요청마다 낮은 값을 주면 파일은 작아지되 인코딩은 매번 돈다.

재 봤더니 1000×1800 이미지 한 장에 1초 미만이었고 시간 제한은 60초였다. 한 자릿수도 아니고 두 자릿수 차이라 이것이 단독으로 시간 초과를 낼 수는 없다. 실측치와 한계치가 자릿수 단위로 벌어지면 그 항목은 단독 원인이 아니다.

여기서 앞의 판단이 틀렸다는 것이 드러났다. 되돌림으로 멎은 것과 그 기능이 원인인 것은 다른 얘기였다.

원인 — 겹침의 구조

더 파 보니 access.log 에서 그 시간대에 /image/resize 요청이 몰렸고 평소의 몇 배가 짧은 구간에 들어와 있었다. 압축이 더한 처리 시간 자체는 짧지만 php-fpm 워커가 동시에 처리하는 수가 늘면 대기가 쌓인다. 처리 시간 증가와 요청 급증이 겹쳐야 시간 제한에 닿는 구조였다.

되돌림이 멎게 한 이유도 이걸로 설명된다. 처리 시간을 줄여서 겹침이 임계 아래로 내려간 것이지 압축 자체가 문제여서가 아니다. 그러므로 급증이 더 커지면 되돌린 상태에서도 같은 일이 난다. 되돌림은 증상을 멎게 했을 뿐 조건을 없애지 않았다.

조치 — 조치와 진단의 구분

되돌림은 서비스를 살리는 데 필요한 조치이고 그 점은 맞다. 문제는 거기서 멈추는 것이다. 되돌리니 멎었다는 사실은 원인 후보를 하나로 좁히지 못하고 묶여 있던 기능 수만큼 후보를 남긴다.

되돌린 뒤에 할 일이 몇 가지 있다. 각 기능의 실측치를 한계치와 비교할 수 있는 수로 따로 내고, 증상이 난 시점의 부하를 access.log 로 확인하고, 되돌림이 함께 지운 것을 목록으로 만들어 무관한 보호는 따로 되살린다. 되살리는 데는 두 가지 방법이 있었는데 되돌린 커밋을 다시 올리고 압축만 끄는 것과 url 검증만 따로 떼어 새 커밋으로 내는 것이다. 뒤쪽을 골랐다. 이유는 되돌린 커밋에 무엇이 들었는지 다시 읽는 사람이 없어서다. 대신 같은 코드를 두 번 리뷰하는 것을 감수했다. 근거는 되살리는 커밋이 보호 장치 하나만 담아야 다음에 또 되돌릴 때 함께 사라지지 않는다는 점이다. 다시 배포할 때는 하나씩 넣는다. 셋을 다시 한 번에 넣으면 같은 자리로 돌아온다.

묶어서 배포한 대가

진단이 불가능해진 지점은 조사 시점이 아니라 배포 시점이다. 기능 세 개를 하나로 묶은 것은 각각 작아서 리뷰도 한 번이면 됐기 때문이었다.

그 편의의 대가가 이것이다. 문제가 생겼을 때 원인을 가를 수 없고 되돌리는 것 말고 할 수 있는 것이 없으며 되돌려도 알게 되는 것이 없다. 지금은 성격이 다른 변경을 나눠서 내고 있고, 특히 quality 처럼 성능에 영향을 주는 것과 url 검증 같은 보안 장치는 같은 배포에 넣지 않는다. 하나 때문에 되돌릴 때 다른 하나가 함께 빠지기 때문이다.

정리


Share this post on:

Previous Post
Claude Code 프로젝트 설정 구조 — 실전 사례
Next Post
Google Cloud OpenTelemetry 자동 활성화 — 영향과 대응