GET과 POST를 사용하고 JSON을 반환한다고 해서 모두 REST의 조건을 충족하는 것은 아닙니다. win-j의 관리자 글 저장 기능과, 같은 기능을 자원 중심 API로 새로 설계하는 예시를 비교하면 이 차이를 구체적으로 볼 수 있습니다.

현재 저장 경로에서 출발하기

이 사이트의 /manager/posts/write-v2/는 staff 로그인과 CSRF 보호를 거쳐 폼 데이터를 읽습니다. 제목·카테고리·본문을 검사하고 글을 만든 뒤 성공 메시지와 이동 주소를 JSON으로 반환합니다. 현재 성공 코드는 200입니다.

이는 특정 관리자 화면을 위한 HTTP 인터페이스입니다. 세션 기반 인증과 화면 동작을 전제로 하므로, 경로를 /api/posts로 바꾼다고 REST 설계가 완성되지는 않습니다. 이 글에서는 현재 운영 경로를 바꾸지 않고 별도 설계 예시만 비교합니다.

자원 중심으로 다시 설계한다면

아래 /api/posts 경로들은 설명용이며 win-j에 구현되어 있지 않습니다. 그대로 운영 사이트에 호출하지 않습니다.

목적 설계 예시 응답 계약 예시
글 목록 조회 GET /api/posts?limit=20 200, 목록과 다음 페이지 정보
글 하나 조회 GET /api/posts/42 200, 글 표현과 ETag
새 글 생성 POST /api/posts 201, 생성된 글과 Location
수정 가능한 표현 전체 교체 PUT /api/posts/42 200 또는 204
일부 필드 변경 PATCH /api/posts/42 정해진 패치 형식과 결과
글 삭제 DELETE /api/posts/42 삭제 정책에 따른 204 등

PUT은 단순히 “수정”이라는 뜻보다 대상 표현을 요청 내용으로 교체하는 의미가 중요합니다. 빠진 필드를 유지할지 지울지 모호하게 두지 말고 수정 가능한 필드의 계약을 정해야 합니다. PATCH도 필드 병합인지 JSON Patch 같은 연산 목록인지 명시해야 합니다. PUT 메서드 정의

멱등성은 같은 응답을 보장한다는 뜻이 아니다

같은 PUT을 반복해 제목을 같은 값으로 바꾸면 의도한 최종 상태는 같아야 합니다. DELETE도 첫 요청이 삭제 성공, 두 번째 요청이 404여도 의도한 결과인 “대상이 없음”은 같을 수 있습니다.

반대로 POST /api/posts를 두 번 보내면 글 두 개가 만들어질 수 있습니다. 글 작성 버튼 중복 클릭을 막는 화면 처리만으로 네트워크 재시도를 해결할 수는 없습니다. 생성 요청의 중복을 허용하지 않아야 한다면 서버의 요청 식별자 저장과 중복 처리 규칙을 별도로 설계합니다. PATCH 역시 어떤 연산을 정의했는지에 따라 멱등성이 달라집니다.

REST에서 더 확인해야 하는 조건

REST는 클라이언트와 서버의 역할 분리, 무상태 통신, 캐시 가능 여부, 일관된 인터페이스, 계층 구조 등의 제약을 조합한 아키텍처 스타일입니다. 선택적인 code-on-demand 제약도 있습니다. 무상태는 데이터베이스를 쓰지 말라는 뜻이 아니라, 요청을 이해하는 데 필요한 맥락을 이전 대화 상태에 의존하지 않도록 한다는 의미입니다. JSON과 JWT는 REST의 필수 형식이 아닙니다. Fielding의 REST 정의

자원 이름과 HTTP 메서드뿐 아니라 표현의 자기 설명성, 다음 가능한 행동을 알려주는 링크도 인터페이스 설계에 포함됩니다. 예를 들어 목록 응답이 다음 페이지 링크를 제공하면 클라이언트가 페이지 URL 규칙을 임의로 조합할 필요가 줄어듭니다.

두 사람이 같은 글을 수정할 때

자원 API를 설계할 때 자주 빠지는 문제가 덮어쓰기입니다. 다음은 구현 제안이며 현재 관리자 저장 기능이 제공하는 동작은 아닙니다.

  1. A와 B가 같은 버전의 글을 조회하고 서버의 ETag를 받습니다.
  2. A가 그 값을 If-Match에 담아 변경합니다.
  3. 서버가 현재 버전과 일치하면 저장하고 새 ETag를 발급합니다.
  4. B가 이전 ETag로 변경하면 서버는 412로 충돌을 알리고 최신 글을 다시 확인하게 합니다.

이 방식은 ETag 발급과 조건부 변경 검사를 서버가 실제로 구현해야 작동합니다. 헤더를 클라이언트에 추가하는 것만으로 덮어쓰기를 막을 수는 없습니다. If-Match 조건부 요청

현재 내부 화면용 API를 즉시 바꿀 필요는 없습니다. 외부 클라이언트 지원, 버전 호환성, 페이지 탐색, 동시 수정처럼 필요한 요구가 생겼을 때 응답 계약을 설계하고 기존 화면과의 호환성을 시험해야 합니다. 현재 구현의 입력·인증 구조는 API 계약 읽기에서 확인할 수 있습니다.