- 발행일
로그아웃은 PATCH인가 DELETE인가 — 그리고 이 비교가 놓쳤던 것
로그아웃은 PATCH인가 DELETE인가
여행 플랫폼([TripTune](/blog/웹 기술로 만드는 협업형 여행 계획 플랫폼 TripTune 개발))의 로그아웃 API를 백엔드 팀원과 설계하며 정리했던 비교입니다. 당시의 비교를 두고, 실제로 무엇을 골랐고 지금은 어떻게 보는지를 뒤에 붙였습니다.
1. 두 방식의 비교 (당시 정리)
PATCH — 로그아웃을 "사용자/토큰의 상태 전환"으로 봅니다. 서버는 세션 데이터를 지우는 게 아니라 '로그아웃됨'으로 표시합니다.
DELETE — 로그아웃을 "세션 리소스의 삭제"로 봅니다. 서버에서 세션·토큰이 사라지므로 이후 인증 요청이 불가능해집니다.
| PATCH | DELETE | |
|---|---|---|
| 의미 | 상태 전환 (부분 수정) | 리소스 제거 |
| 세션 데이터 | 남음 — 이력·재활성화 가능 | 사라짐 — 복구 불가 |
| 보안 관점 | 무효화 표시에 의존 | 물리적으로 제거 |
| 어울리는 상황 | 로그아웃 이력·상태 추적이 필요할 때 | 세션을 깔끔히 정리해야 할 때 |
// 당시 예시 — 이 코드의 문제는 3절에서
const logout = async () => {
const response = await fetch('/api/logout', {
method: 'PATCH',
headers: { Authorization: `Bearer ${token}` },
body: JSON.stringify({ status: 'logged_out' }),
})
if (response.ok) {
localStorage.removeItem('authToken')
}
}
2. 실제 선택 — PATCH, 그리고 그 이유
TripTune은 PATCH /api/members/logout 으로 갔습니다. 서버 구조상 로그아웃은 "세션 row 삭제"가 아니라 refresh token을 무효 상태로 바꾸는 갱신이었기 때문입니다. JWT 기반이라 서버가 지울 세션 자체가 없고, 무효화 목록에 표시하는 쪽이 실제 동작과 일치했어요. 리소스 관점의 순수성보다 서버가 실제로 하는 일과 메서드 의미를 맞추는 것이 기준이었습니다.
3. 다시 보니 — 이 비교가 놓친 세 가지
표에서 가장 흔한 답이 빠져 있었다: POST
실무에서 로그아웃 API의 사실상 표준은 POST /logout 입니다. 로그아웃은 리소스라기보다 동작(action) 이고, 동작 엔드포인트는 POST로 여는 게 널리 쓰이는 관례거든요. GitHub·Google 등 대부분의 실서비스가 이 형태입니다. PATCH vs DELETE라는 2지선다로 문제를 세팅한 순간, 가장 유력한 후보를 심사도 없이 탈락시킨 셈이었어요. 비교 글의 품질은 비교 항목을 고르는 순간 절반이 정해진다는 걸 배웠습니다.
진짜 질문은 메서드가 아니라 "무엇을 리소스로 볼 것인가"였다
/api/logout이라는 URL을 고정해 두고 메서드만 고민했는데, REST의 관점으로 끝까지 가면 리소스는 로그아웃이 아니라 세션(또는 토큰) 입니다 — DELETE /sessions/current처럼요. 그 프레임에서는 메서드 논쟁이 자연스럽게 사라집니다. 메서드 선택이 어색하게 느껴진다면 대개 URL 설계가 동작 중심이기 때문이었어요.
예시 코드의 결함이 실제 코드에도 들어갔다
위 예시는 response.ok일 때만 클라이언트 토큰을 지웁니다. 서버가 죽어 있거나 네트워크가 끊기면? 로그아웃을 눌렀는데 자격증명이 브라우저에 그대로 남습니다. 로그아웃의 클라이언트 정리는 서버 응답과 무관하게 — finally에서 — 실행돼야 해요. 사용자의 의도는 "이 기기에서 세션 끝내기"고, 그건 서버가 실패해도 존중돼야 하는 의도니까요.
이 글을 개고하며 실제 TripTune 코드(logoutApi.ts)를 다시 봤는데, 같은 결함이 그대로 있습니다 — await patch(...)가 던지면 Cookies.remove 줄에 도달하지 못해요. 2024년에 예시로 쓴 코드의 문제를 지적할 눈이 없었으니, 실전 코드에도 같은 문제가 들어간 거죠. try/finally 한 겹이면 끝나는 수정이라 후속 과제로 적어둡니다.
정리
- 메서드 선택의 기준은 REST 교리보다 "서버가 실제로 하는 일" 과의 일치 — 우리는 무효화(갱신)라서 PATCH.
- 비교하기 전에 선택지 목록부터 의심할 것 — 실무 표준(POST)이 표에 없었다.
- 로그아웃의 클라이언트 정리는 서버 실패와 무관하게 실행할 것 —
finally가 자리다.