HTTP 메서드와 캐시 완벽 가이드

HTTP 메서드의 종류와 특성, API 설계 방식(컬렉션, 스토어 기반), 그리고 캐시 제어에 관한 종합적인 설명과 실제 적용 방법을 다루는 가이드다.

HTTP 메서드의 종류와 차이점

HTTP 프로토콜에서는 다양한 메서드를 제공하여 서버와 클라이언트 간 통신 목적을 명확히 한다.



GET 메서드

GET은 서버로부터 데이터를 조회하는 용도로 사용한다.

  • 쿼리 파라미터(URI)를 통해 데이터 전송
  • 바디를 통한 데이터 전송도 기술적으로 가능하나 지원하지 않는 서버가 많아 비권장
  • 데이터가 URI에 노출되어 보안에 취약
  • URI 길이제한으로 인한 데이터 길이제한 존재
  • 게시판 조회와 같은 조회 요청에 주로 사용
GET /members?page=1&size=10 HTTP/1.1
Host: example.com

GET 메서드는 서버의 데이터나 상태를 변경하지 않는 안전한 메서드로, 캐싱이 가능하다.



POST 메서드

POST는 서버에 데이터를 제출하여 새로운 리소스를 생성하는 용도로 사용한다.

  • 메시지 바디를 통해 데이터 전송
  • 데이터가 URL에 노출되지 않아 상대적으로 안전
  • 데이터 길이제한 없음
  • 게시판 생성과 같은 서버 데이터 생성이나 업데이트에 주로 사용
POST /members HTTP/1.1
Host: example.com
Content-Type: application/json

{
  "name": "홍길동",
  "age": 30
}

POST는 요청마다 새로운 리소스를 생성할 수 있어 멱등성을 가지지 않는다.



PUT 메서드

PUT은 리소스를 완전히 대체하는 용도로 사용한다.

  • 클라이언트가 리소스의 위치를 정확히 알고 있어야 함
  • 리소스를 완전히 덮어씌움
  • 예: member{“고”, 25세} 데이터를 member{“김”}으로 PUT 요청하면 결과는 member{“김”}이 됨
PUT /members/100 HTTP/1.1
Host: example.com
Content-Type: application/json

{
  "name": "김"
}

PUT은 동일한 요청을 여러 번 수행해도 결과가 같아 멱등성을 가진다.



PATCH 메서드

PATCH는 리소스의 일부분만 수정하는 용도로 사용한다.

  • 리소스의 부분 수정이 가능
  • 예: member{“고”, 25세} 데이터를 member{“김”}으로 PATCH 요청하면 결과는 member{“김”, 25세}가 됨
PATCH /members/100 HTTP/1.1
Host: example.com
Content-Type: application/json

{
  "name": "김"
}

PATCH는 부분 수정을 위한 메서드로, 변경되지 않은 필드는 원래 값을 유지한다.



DELETE 메서드

DELETE는 리소스를 제거하는 용도로 사용한다.

  • 지정된 리소스를 완전히 삭제
DELETE /members/100 HTTP/1.1
Host: example.com

DELETE는 동일한 요청을 여러 번 수행해도 결과가 같아 멱등성을 가진다.



HTTP 메서드 속성

HTTP 메서드는 각각 다른 속성을 가지고 있어 용도에 맞게 사용해야 한다.



안전(Safe)

안전성은 메서드가 서버의 상태를 변경하지 않는 특성을 의미한다.

  • 호출해도 리소스를 변경하지 않는 메서드는 안전하다고 함
  • GET, HEAD, OPTIONS 메서드가 안전한 메서드에 해당
  • 로그가 쌓이는 것과 같은 부수 효과는 고려하지 않음

안전한 메서드는 조회 목적으로만 사용되며, 데이터 변경을 일으키지 않는다.



멱등(Idempotent)

멱등성은 동일한 요청을 여러 번 수행해도 결과가 동일한 특성을 의미한다.

  • GET: 몇 번을 조회하든 같은 결과
  • PUT: 몇 번을 요청하든 최종 결과는 동일
  • DELETE: 한 번 삭제된 리소스는 여러 번 삭제해도 결과 동일
  • POST만 멱등하지 않음: 2번 호출하면 결제가 중복될 수 있음

💡 멱등성의 중요성:

  • 자동 복구 메커니즘에 활용 가능
  • 서버가 타임아웃 등으로 응답하지 않을 때 클라이언트가 동일 요청을 안전하게 재시도 가능

멱등성은 외부 요인으로 인한 리소스 변경은 고려하지 않으며, 동일한 요청에 대한 서버 상태 변화만을 고려한다.



캐시 가능(Cacheable)

캐시 가능성은 응답 결과를 캐시해서 재사용할 수 있는지를 나타낸다.

  • GET, HEAD, POST, PATCH 메서드가 캐시 가능
  • 실제로는 GET, HEAD만 주로 캐시로 사용
  • POST, PATCH는 본문 내용까지 캐시 키로 고려해야 해서 구현이 복잡함

HTTP 메서드 속성 표:

image-20250418174542430

캐시 가능한 메서드는 네트워크 부하를 줄이고 응답 속도를 높이는 데 중요한 역할을 한다.



HTTP API 설계 방식

API 설계는 리소스 중심의 설계가 중요하며, 행위는 HTTP 메서드로 표현하는 것이 좋다.



컬렉션 기반 API 설계 (POST 기반)

컬렉션은 서버가 관리하는 리소스 디렉토리로, 서버가 리소스 URI를 생성하고 관리한다.

  • 회원 관리 API 예시:
    • 회원 목록: GET /members
    • 회원 등록: POST /members
    • 회원 조회: GET /members/{id}
    • 회원 수정: PATCH, PUT, POST /members/{id}
      • 회원 수정에 개념적으론 PATCH 사용이 제일 좋다.
    • 회원 삭제: DELETE /members/{id}
  • 특징:
    • 클라이언트는 등록될 리소스의 URI를 모름
    • 서버가 새로 등록된 리소스 URI를 생성해 줌
    • 응답 예: HTTP/1.1 201 Created, Location: /members/100

컬렉션 방식은 서버가 URI를 관리하므로 클라이언트는 리소스 생성 위치를 알 필요가 없다.



스토어 기반 API 설계 (PUT 기반)

스토어는 클라이언트가 관리하는 리소스 저장소로, 클라이언트가 리소스 URI를 알고 관리한다.

  • 파일 관리 API 예시:
    • 파일 목록: GET /files
    • 파일 조회: GET /files/{filename}
    • 파일 등록: PUT /files/{filename}
    • 파일 삭제: DELETE /files/{filename}
    • 파일 대량 등록: POST /files
  • 특징:
    • 클라이언트가 리소스 URI를 알고 있어야 함
    • 클라이언트가 직접 리소스의 URI를 지정
    • 요청 예: PUT /files/star.jpg

스토어 방식은 클라이언트가 URI를 지정하므로 리소스 위치에 대한 제어권이 클라이언트에 있다.



HTML FORM 사용 (GET, POST만 지원)

HTML FORM은 GET과 POST 메서드만 지원하므로 제약이 있다.

  • 회원 관리 웹 페이지 예시:
    • 회원 목록: GET /members
    • 회원 등록 폼: GET /members/new
    • 회원 등록: POST /members/new 또는 POST /members
    • 회원 조회: GET /members/{id}
    • 회원 수정 폼: GET /members/{id}/edit
    • 회원 수정: POST /members/{id}/edit 또는 POST /members/{id}
    • 회원 삭제: POST /members/{id}/delete
  • 특징:
    • GET, POST만 사용 가능
    • 제약을 해결하기 위해 동사를 사용한 컨트롤 URI 방식 사용
    • 예: /members/{id}/delete

HTML FORM은 제약이 있지만, 컨트롤 URI를 통해 다양한 기능을 구현할 수 있다.


참고) URI 설계 개념

참고 문서: https://restfulapi.net/resource-naming

  • 문서(document):
    • 단일 개념(파일 하나, 객체 인스턴스, 데이터베이스 row)
    • 예: /members/100, /files/star.jpg
  • 컬렉션(collection):
    • 서버가 관리하는 리소스 디렉터리
    • 서버가 리소스의 URI를 생성하고 관리
    • 예: /members
  • 스토어(store):
    • 클라이언트가 관리하는 자원 저장소
    • 클라이언트가 리소스의 URI를 알고 관리
    • 예: /files
  • 컨트롤러(controller), 컨트롤 URI:
    • 문서, 컬렉션, 스토어로 해결하기 어려운 추가 프로세스 실행
    • 동사를 직접 사용
    • 예: /members/{id}/delete

실무에서는 주로 컬렉션 방식을 사용하며, 필요에 따라 컨트롤 URI를 혼합하여 사용한다.



HTTP 캐시와 프록시 캐시

HTTP 캐시는 네트워크 부하를 줄이고 응답 속도를 향상시키는 중요한 기술이다.



캐시 기본 동작

브라우저 캐시를 사용하면 처음 데이터 다운로드 이후 시간을 크게 단축할 수 있다.

  • 캐시 유효 시간 동안은 네트워크를 사용하지 않고 로컬 캐시에서 데이터 제공
  • 개발자 도구의 네트워크 탭에서 캐시 사용 여부 확인 가능 (회색 텍스트로 표시)
  • 304 Not Modified 응답은 캐시 재검증 후 캐시 사용을 의미



검증 헤더와 조건부 요청

image-20250418181133848

캐시 유효 시간이 만료되었을 때 서버와 검증을 통해 캐시를 재사용할 수 있다.

  • 검증 헤더(Validator):
    • ETag: “v1.0”, “asid93jkrh2l” - 리소스의 버전을 태그로 관리
      • 만약 서버 데이터 수정할 일이 거의 없는 경우는 ETag가 좋지.
    • Last-Modified: Thu, 04 Jun 2020 07:19:24 GMT - 마지막 수정 시간 기반
  • 조건부 요청 헤더:
    • If-Match, If-None-Match: ETag 값 사용
    • If-Modified-Since, If-Unmodified-Since: Last-Modified 값 사용

서버 데이터가 변경되지 않았다면 304 Not Modified 응답과 함께 헤더 메타 정보만 전송하고 바디는 전송하지 않는다.


아래는 캐시 유효시간 만료되었는데 304응답으로 캐시 사용하는 모습 (검증 헤더 2가지 ver)

image-20250418181428310

image-20250418181455111


캐시 제어 헤더

  • Cache-Control: 캐시 제어의 기본 헤더
    • max-age=초단위: 캐시 유효 시간 설정
    • no-cache: 데이터는 캐시해도 되지만, 항상 원 서버에 검증 필요
    • no-store: 민감한 정보가 있어 캐시 저장 금지
    • public: 공유 캐시(프록시 캐시)에 저장 가능
    • private: 브라우저 같은 특정 사용자 환경에만 저장(기본값)
    • s-maxage: 프록시 캐시에만 적용되는 max-age
  • Pragma: no-cache (HTTP 1.0 하위 호환) -> 옛날..
  • Expires: 캐시 만료일 지정 (하위 호환) -> 옛날..

Cache-Control 헤더는 HTTP/1.1의 표준 캐시 제어 방식으로, 다양한 옵션을 통해 세밀한 캐시 정책 설정이 가능하다.



헤더 - 프록시 캐시와 CDN

프록시 캐시는 클라이언트와 서버 사이에 위치하여 캐시 기능을 제공한다.

  • AWS CloudFront와 같은 CDN 서비스가 대표적인 프록시 캐시 예시
  • 원 서버(Origin Server)와 클라이언트 사이에서 캐시 제공
  • 여러 사용자가 접근하는 콘텐츠를 효율적으로 전달

image-20250418181732125

  • Cache-Control: public
    • 응답이 public 캐시에 저장되어도 됨
  • Cache-Control: private
    • 응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값)
  • Cache-Control: s-maxage
    • 프록시 캐시에만 적용되는 max-age
  • Age: 60 (HTTP 헤더)
    • 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)



헤더 - 캐시 무효화

확실한 캐시 무효화가 필요한 경우 다음과 같은 헤더 조합을 사용한다.

  • Cache-Control: no-cache, no-store, must-revalidate
  • Pragma: no-cache (HTTP 1.0 하위 호환 필요 시)


must-revalidate의 중요성:

  • 캐시 유효 시간이 지난 경우 반드시 원 서버에 검증해야 함
  • 원 서버 접근 실패 시 오류 발생(504 Gateway Timeout)
  • 이를 통해 오래된 데이터가 제공되는 것을 방지

image-20250418182617843

image-20250418182645572

image-20250418182700250

HTTP 캐시는 네트워크 효율성과 사용자 경험을 크게 향상시키는 중요한 기술이며, 적절한 캐시 정책 설정을 통해 성능 최적화와 데이터 일관성을 모두 달성할 수 있다.

댓글남기기