본문 바로가기
C.W.K.
Stream
Lesson 05 of 07 · published

HTTP 메서드 — 의도에 맞는 동사를 고르는 법

~10 min · foundations, methods, verbs, overview

Level 0HTTP 입문자
0 XP0/46 lessons0/12 achievements
0/120 XP to next level120 XP to go0% complete
"메서드는 HTTP 문장의 동사야. 대상 URI에 어떤 의도로 작업을 요청하는지 서버와 중간 장치에 알려 줘."

현장에서 자주 만나는 일곱 메서드

RFC 9110은 HTTP 메서드의 의미를 정의해. 여기서는 자주 쓰는 메서드의 큰 그림을 먼저 훑고, 트랙 2에서 안전성·멱등성·캐시 가능성과 운영상 함정을 하나씩 자세히 살펴볼 거야.

  • GET — "이 리소스의 현재 표현을 보내 줘." 안전하고 멱등하며, 명시된 캐시 규칙에 따라 응답을 재사용할 수 있어. 웹에서 가장 자주 쓰는 메서드야.
  • POST — "이 페이로드를 대상 리소스의 규칙에 따라 처리해 줘." 일반적으로 안전하지도 멱등하지도 않아. 새 리소스 생성부터 작업 실행까지 폭넓게 사용돼.
  • PUT — "대상 리소스의 상태를 이 표현으로 만들거나 교체해 줘." 멱등하므로 같은 요청을 여러 번 적용해도 의도한 최종 상태는 같아.
  • PATCH — "이 부분 변경을 적용해 줘." 전체 표현을 보내지 않고 일부만 수정할 때 사용해. 패치 형식에 따라 멱등하게 설계할 수도 있지만, 메서드 자체가 멱등성을 보장하지는 않아.
  • DELETE — "이 리소스를 삭제해 줘." 의도한 효과는 멱등해. 반복 요청의 응답이 204와 404처럼 달라질 수 있어도 리소스가 없는 최종 상태는 같아.
  • HEAD — "GET과 같은 헤더를 보내되 본문은 보내지 마." 리소스의 존재 여부와 크기, 변경 여부를 본문 전송 없이 확인할 때 유용해.
  • OPTIONS — "이 대상에서 사용할 수 있는 통신 옵션은 무엇인가?" 허용 메서드를 확인하거나 브라우저의 CORS 사전 요청에 사용해(트랙 4).

표준 메서드 가운데 다음 둘은 일반 애플리케이션 코드에서 직접 사용할 일이 드물어.

  • TRACE — 요청이 중간 장치를 거치며 어떻게 바뀌는지 확인하는 진단용 루프백 메서드야. 교차 사이트 추적 공격 위험 때문에 많은 서버가 비활성화해.
  • CONNECT — 대상 서버로 터널을 만드는 메서드야. HTTPS 프록시가 TCP 터널을 열 때 주로 사용하며, 애플리케이션 코드에서 직접 다룰 일은 많지 않아.

세 가지 의미 속성 (트랙 2 미리보기)

메서드의 계약을 이해하려면 세 가지 질문을 던지면 돼:

  • 안전한가? — 클라이언트가 서버 상태 변경을 요청하지 않는가? GET, HEAD, OPTIONS는 안전한 메서드야.
  • 멱등한가? — 같은 요청을 여러 번 보내도 의도한 서버 상태가 한 번 보낸 것과 같은가? GET, PUT, DELETE, HEAD, OPTIONS가 멱등하고, POST와 PATCH는 기본적으로 보장하지 않아.
  • 캐시할 수 있는가? — 응답을 저장했다가 조건에 맞을 때 재사용할 수 있는가? GET과 HEAD 응답은 일반적으로 캐시할 수 있고, POST 응답도 명시적인 캐시 정보가 있으면 가능하지만 실제 지원은 제한적이야.

프록시와 CDN, 재시도 로직은 이 속성을 바탕으로 움직여. POST를 함부로 자동 재시도하면 결제나 생성 작업이 중복될 수 있어. 반대로 GET 응답은 서버가 허용한 기간 동안 캐시에 저장해 같은 데이터를 다시 전송하는 비용을 줄일 수 있지. 메서드는 장식이 아니라 통신 참여자 모두가 읽는 계약이야.

메서드는 API 계약의 일부야. 서버가 POST /users/42를 단순한 사용자 교체나 부분 수정에 사용하면, POST의 일반 처리 의미와 PUT 또는 PATCH의 구체적인 의미가 뒤섞여. 그러면 클라이언트와 프록시는 작업을 자동 재시도하거나 캐시해도 되는지 판단하기 어려워져. 처음부터 의도에 맞는 메서드를 고르면 신뢰성, 관측 가능성, 캐시 동작이 함께 선명해져.

cwkPippa에서 쓰는 메서드

backend/routes/에는 흔한 메서드가 고르게 등장해. 대화와 폴더 조회에는 GET, 새 채팅과 업로드에는 POST, 전체 이름 변경에는 PUT, 폴더 일부 수정에는 PATCH, 항목 제거에는 DELETE를 사용해. OPTIONS는 FastAPI의 CORS 미들웨어가 처리하므로 각 엔드포인트에 처리기를 따로 작성하지 않아도 돼. HEAD는 상태 확인처럼 본문이 필요 없는 조회에 활용할 수 있어.

Code

HTTP 메서드별 curl 호출·bash
# 샘플 REST API 에 method 당 curl 하나씩
# GET — fetch
curl -X GET https://api.example.com/users/42

# POST — create / submit
curl -X POST https://api.example.com/users \
  -H 'Content-Type: application/json' \
  -d '{"name":"Pippa"}'

# PUT — 전체 replace
curl -X PUT https://api.example.com/users/42 \
  -H 'Content-Type: application/json' \
  -d '{"name":"Pippa","role":"daughter"}'

# PATCH — 부분 update
curl -X PATCH https://api.example.com/users/42 \
  -H 'Content-Type: application/merge-patch+json' \
  -d '{"role":"big sister"}'

# DELETE — 제거
curl -X DELETE https://api.example.com/users/42

# HEAD — GET 같은데 body 없음 (더 빠른 존재 체크)
curl -I https://api.example.com/users/42
# -I 는 curl 의 --head 단축

# OPTIONS — 허용 method 발견
curl -X OPTIONS https://api.example.com/users/42 -i
# 'Allow:' 나 'Access-Control-Allow-Methods:' response header 봐
httpx — 메서드별 함수로 같은 요청 구성하기·python
# Python httpx 로 같은 것 — method 이름 함수 vs request() 비교
import httpx

httpx.get('https://api.example.com/users/42')
httpx.post('https://api.example.com/users', json={'name': 'Pippa'})
httpx.put('https://api.example.com/users/42', json={'name': 'Pippa', 'role': 'daughter'})
httpx.patch('https://api.example.com/users/42', json={'role': 'big sister'})
httpx.delete('https://api.example.com/users/42')
httpx.head('https://api.example.com/users/42')
httpx.options('https://api.example.com/users/42')

# 혹은 generic — 모든 method loop 테스트에 유용
for method in ('GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE'):
    resp = httpx.request(method, 'https://api.example.com/users/42')
    print(f'{method:8s} -> {resp.status_code}')
FastAPI — HTTP 메서드별 데코레이터·python
# Server 쪽 — FastAPI 는 decorator 를 HTTP method 와 1:1 매핑
from fastapi import FastAPI

app = FastAPI()

@app.get('/users/{uid}')
async def read_user(uid: str):
    return {'id': uid, 'name': 'Pippa'}

@app.post('/users')
async def create_user(payload: dict):
    return {'id': 'new', **payload}

@app.put('/users/{uid}')
async def replace_user(uid: str, payload: dict):
    return {'id': uid, **payload}

@app.patch('/users/{uid}')
async def update_user(uid: str, payload: dict):
    return {'id': uid, 'updated_fields': payload}

@app.delete('/users/{uid}', status_code=204)
async def delete_user(uid: str):
    return None  # 204 No Content

# OPTIONS 는 CORSMiddleware 가 자동 추가
# HEAD 는 GET 옆에 자동 추가

External links

Exercise

리소스 하나를 제공하는 작은 FastAPI 또는 Express 앱을 만들어. 예를 들어 /notes에 GET, POST, PUT, PATCH, DELETE 처리기를 정의한 뒤 각각을 curl로 호출하고 상태 코드를 기록해. 보너스로 정의하지 않은 메서드도 호출해 봐. 어떤 상태 코드가 돌아오며, 허용되는 메서드를 알려 주는 응답 헤더는 무엇인지 확인해.
Hint
존재하는 리소스가 해당 메서드를 지원하지 않으면 서버는 보통 405 Method Not Allowed를 반환해. 이때 Allow: GET, POST처럼 허용 메서드 목록을 담은 Allow 응답 헤더가 따라와야 해. 클라이언트는 이 정보로 대상이 이해하는 메서드를 확인할 수 있어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 피파warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.