로컬에선 되던 삭제가 서버에선 405를 뱉었다
배포 환경에서 만난 405 에러 해결기
#Apache #REST #Express #트러블슈팅
커플 맛집 앱에서 즐겨찾기 삭제 버튼을 눌렀는데 콘솔에 빨갛게 이게 떴다. DELETE https://... 405 (Method Not Allowed) 로컬에선 분명 잘 됐다. 즐겨찾기도 잘 지워지고, 닉네임 수정(PUT)도 멀쩡했다. 근데 서버에 올리고 나서 똑같은 코드가 405를 뱉는다. 코드는 안 건드렸는데 환경만 바뀌었더니 깨진 거다. 이런 게 제일 짜증난다 — 뭘 고쳐야 할지 감이 안 오니까. 이 글은 그 405가 어디서 났고, 왜 결국 DELETE랑 PUT을 다 버리고 POST로 통일했는지에 대한 기록이다. 범인은 내 코드가 아니었다 한참을 Express 라우터만 들여다봤다. router.delete 경로도 맞고, 미들웨어도 맞고, 로컬에선 되니까 코드는 죄가 없었다. 그러다 문득 — 로컬엔 없고 서버엔 있는 게 뭐지? 싶었다. Apache . 내 서버는 전부 Apache 리버스 프록시 뒤에서 돈다(이 구조는 따로 정리해둔 글이 있다). 그리고 Apache는 기본적으로 DELETE, PUT 같은 메서드를 "위험한 거"로 보고 막아버린다. 그러니까 내 요청은 Express까지 가지도 못하고 Apache 선에서 잘려서 405로 돌아온 거였다. 로컬은 Apache가 없으니 당연히 멀쩡했고. 코드를 아무리 째려봐도 안 보였던 이유가 이거였다. 문제는 코드 안이 아니라 코드 앞 에 있었다. 두 갈래 길 선택지는 두 개였다. 1. Apache 설정을 풀어서 DELETE/PUT을 허용한다 2. 막히지 않는 메서드(POST/GET)만 쓴다 1번이 "정석"이긴 하다. 근데 이건 서버 전체의 메서드 정책을 건드리는 거다. 여기엔 맛집 앱만 도는 게 아니라 블로그, 코인, 모니터링까지 여러 서비스가 같이 산다. 그 공용 Apache 설정을 풀었다가 딴 데서 뭐가 터질지 모르는 게 부담스러웠다. 그래서 2번을 택했다. 삭제든 수정이든 전부 POST로. 좀스러워 보여도, 건드리는 범위가 내 앱 안으로 한정되는 게 마음 편했다. 기존 걸 안 갈아엎고 POST를 얹기 이미 DELETE/PUT으로 짜둔 라우트가 꽤 됐다. 다 지우고 새로 짜는 건 일이라, 같은 핸들러를 POST로도 같이 등록하는 식으로 했다. 핸들러 하나에 메서드 두 개를 물려두는 거다. // 기존 DELETE는 그대로 두고, POST로도 같은 핸들러 등록 router.delete('/comment/delete/:id', deleteCommentHandler); router.post('/comment/delete/:id', deleteCommentHandler); // 수정도 마찬가지 router.put('/nickname', updateNicknameHandler); router.post('/nickname', updateNicknameHandler); 이러면 로컬에선 DELETE도 되고, 서버(Apache 뒤)에선 POST로 부르면 된다. 프론트는 아예 PUT/DELETE를 안 쓰고 POST/GET만 부르도록 통일했다. 어느 환경에 올라가든 안 깨지게. 삭제인데 POST 쓰는 거, 찜찜하지 않냐면 찜찜하다. REST대로면 삭제는 DELETE가 맞다. POST로 삭제하는 건 교과서적으로 안 예쁘다. 나도 안다. 근데 현실에선 "이론적으로 옳은 것"보다 "지금 이 서버에서 진짜 도는 것" 이 우선이었다. 어차피 이 API를 부르는 클라이언트는 내가 만든 프론트 하나뿐이고, 경로에 /delete, /disconnect라고 의도가 박혀 있어서 헷갈릴 일도 없다. 메서드 이름이 좀 안 맞아도 동작이 분명하면 그걸로 됐다고 봤다. 정리하면 이 삽질에서 건진 교훈은 하나다 — 로컬에선 되는데 서버에서 안 되면, 코드 말고 그 사이의 인프라를 의심해라. 요청이 브라우저에서 Express까지 오는 길에는 Apache, 프록시, 방화벽이 줄줄이 끼어 있고, 거기 어디서든 잘릴 수 있다. 근데 우리는 보통 코드부터 의심한다. 코드는 눈에 보이고 인프라는 안 보이니까. 지금도 이 앱은 삭제든 수정이든 전부 POST로 처리하고 있고, 아무 문제 없이 잘 돈다. REST를 완벽하게 지키는 것보단, 내 환경에서 안 깨지는 구조를 만드는 게 결국 더 중요했다.