웹 개발을 하다 보면 HTTP 메서드를 언제 무엇을 써야 할지 고민될 때가 많다. 단순히 데이터를 보내는 용도라면 POST 하나로 다 해결할 수 있을 것 같지만, 실제로는 목적에 따라 엄격하게 구분해서 사용한다. 왜 이렇게 나누어 놓았는지, 그리고 각 메서드의 차이점이 무엇인지 정리해 본다.

 


 

1. HTTP 메서드별 역할 (CRUD)

가장 기본적으로 HTTP 메서드는 데이터베이스의 CRUD 작업과 매칭된다. 

메서드  역할 (CRUD) 멱등성  설명
GET Read Yes 리소스 조회
POST Create No 리소스 생성 및 복잡한 연산
PUT Update Yes 리소스 전체 수정 (덮어쓰기)
PATCH Update No 리소스 부분 수정
DELETE Delete Yes 리소스 삭제
멱등성(Idempotency)이란?
동일한 요청을 여러 번 수행해도 결과(서버의 상태)가 똑같은 성질을 의미한다. 네트워크 오류로 인해 클라이언트가 요청을 재시도해야 할 때 매우 중요한 기준이 된다.

 


 

2. 왜 굳이 나누어서 사용하는가?

 

단순히 "데이터 전송"만 생각하면 비효율적이라고 느낄 수 있지만, 명확하게 구분했을 때 얻는 이점이 더 크다.

 

첫째, 시맨틱(Semantics) 즉, 의미의 명확성 때문이다.

코드나 로그만 봐도 이 요청이 조회를 위한 것인지, 삭제를 위한 것인지 한눈에 알 수 있다. 협업 과정에서 API의 의도를 파악하는 시간을 획기적으로 줄여준다.

 

둘째, 캐싱을 통한 성능 최적화다.

GET 요청은 서버의 상태를 바꾸지 않기 때문에 브라우저나 프록시 서버에서 결과를 미리 저장(캐싱)해둘 수 있다. 반면 데이터가 변하는 POST나 PUT은 캐싱하지 않아 데이터의 무결성을 지킨다.

 

셋째, 네트워크 안정성이다.

멱등성이 보장되는 GET, PUT, DELETE는 네트워크 장애 시 자동으로 재시도(Retry) 로직을 타게 설계할 수 있지만, POST는 중복 생성 위험 때문에 재시도가 조심스럽다.

 


 

3. 부분 수정은 어떻게 할까? (PUT vs PATCH)

데이터를 수정할 때 흔히 하는 실수가 무조건 PUT을 사용하는 것이다. 하지만 둘은 확실히 다르다.

 

  • PUT (전체 수정): 리소스의 모든 필드를 보내야 한다. 만약 일부 필드만 보낸다면, 서버에서는 보내지 않은 나머지 필드를 Null이나 기본값으로 덮어버릴 위험이 있다. 즉, 리소스를 통째로 갈아 끼울 때 쓴다.
  • PATCH (부분 수정): 수정하고 싶은 데이터(예: 비밀번호, 닉네임)만 Body에 담아 보낸다. 자원을 효율적으로 사용하고 부수 효과를 줄일 수 있다.

 


 

4. GET으로 DELETE를 처리하면 안 되는 이유

편의상 GET /user/delete?id=1 처럼 설계하는 경우가 간혹 있는데, 이는 매우 위험한 안티 패턴이다.

 

  1. 검색 엔진 크롤러의 위협: 구글이나 네이버 같은 크롤러는 웹상의 모든 GET 링크를 자동으로 타고 들어간다. 만약 삭제 로직이 GET으로 되어 있다면, 크롤러가 지나가는 것만으로 DB의 데이터가 전부 삭제되는 대참사가 날 수 있다.
  2. 보안 및 기록: GET 요청은 모든 파라미터가 URL에 노출된다. 서버 로그나 브라우저 히스토리에 삭제 관련 정보가 남기 때문에 보안상 취약하다.
  3. 캐싱 문제: 삭제 요청인데 브라우저가 "이미 처리된 결과가 있네?" 하고 캐싱된 데이터를 보여주면, 실제 서버에서는 삭제가 안 되었음에도 클라이언트는 삭제된 것으로 착각할 수 있다.

 


 

5. 메서드별 캐싱(Caching) 메커니즘 정리

메서드  캐싱 가능 비고
GET Yes (기본) 대부분의 HTTP 캐싱은 GET 요청을 대상으로 함.
HEAD Yes 응답 바디 없이 헤더 정보만 가져오므로 캐싱 가능.
POST Yes (조건부) 캐시 관련 헤더(Expires 등)가 명시적일 때만 가능하나, 실무에선 거의 쓰지 않음.
PUT/PATCH/DELETE No 리소스를 변경하므로 캐싱하지 않음. 기존 캐시를 무효화함.

 


 

5-1. 왜 특정 메서드만 캐싱하는가?

GET, HEAD가 캐싱되는 이유

  • 안전성(Safe): 이 메서드들은 서버의 데이터를 변경하지 않습니다. 즉, 언제 호출해도 같은 결과(리소스)를 받을 가능성이 높기 때문에 복사본을 저장해 두었다가 꺼내 쓰는 것이 효율적입니다.
  • 성능 최적화: 웹 페이지의 이미지, CSS, JS 파일 등은 모두 GET으로 호출됩니다. 이를 매번 서버에서 새로 가져오지 않고 캐시에서 불러와야 로딩 속도가 비약적으로 빨라집니다.

 

POST가 캐싱되기 어려운 이유

  • POST는 호출할 때마다 서버에 새로운 리소스를 생성하거나 처리를 요청합니다.
  • "결제하기" 요청을 캐싱해서 재사용한다면, 사용자는 한 번 클릭했지만 서버는 여러 번 결제된 것으로 오해할 수 있는 위험이 있습니다. 따라서 기본적으로는 캐싱하지 않는 것이 원칙입니다.

 


 

5-2.수정/삭제 메서드와 캐시의 관계 (Cache Invalidation)

 

PUT, PATCH, DELETE 메서드는 캐싱이 되지 않을 뿐만 아니라, 기존에 저장된 캐시를 삭제(무효화) 하는 중요한 역할을 합니다.

 

  • 동작 원리:
    1. 브라우저가 GET /user/1 요청을 보내서 사용자 정보를 캐싱함.
    2. 이후 PATCH /user/1 요청(이름 수정)을 보냄.
    3. 브라우저와 프록시 서버는 "아, 리소스가 변했구나"라고 판단하여 기존에 저장되어 있던 GET /user/1의 캐시 데이터를 즉시 삭제함.
  • 이를 통해 클라이언트가 수정된 이후에도 과거의 잘못된(Stale) 데이터를 보는 것을 방지합니다.

5-3. 캐싱 제어 방법

실제 개발 시에는 단순히 메서드 구분뿐만 아니라 응답 헤더를 통해 캐싱을 더 세밀하게 제어합니다.

 

주요 캐시 제어 헤더

Cache-Control: max-age=3600 (1시간 동안 캐시 유지)
Cache-Control: no-store (절대 캐싱 금지 - 민감한 정보)
Cache-Control: no-cache (캐시는 하되, 사용 전에 서버에 확인 요청)

 


 

 

요약 및 마무리

 

결국 HTTP 메서드를 나누는 이유는 "약속"을 지키기 위함이다.

  • 조회는 GET
  • 생성은 POST
  • 전체 교체는 PUT, 부분 수정은 PATCH
  • 삭제는 DELETE

이 원칙(RESTful)만 잘 지켜도 훨씬 유지보수하기 쉽고 안정적인 서비스를 만들 수 있다.

+ Recent posts