C.W.K.
Stream
Lesson 05 of 07 · published

Methods Overview — Server 가 알아듣는 일곱 verb

~10 min · foundations, methods, verbs, overview

Level 0HTTP Newbie
0 XP0/46 lessons0/12 achievements
0/120 XP to next level120 XP to go0% complete
"Method 는 verb 야. URI 가 가리키는 resource 한테 뭘 하고 싶은지 server 한테 알려줘. 표준 verb 가 일곱 개고, 대부분 앱은 그중 네 개를 써."

현장에서 만날 일곱 개

HTTP/1.1 이 표준 method 한 줌을 정의했고 RFC 9110 이 변경 없이 이어받았어. 여기는 survey — Track 2 가 각각을 semantic invariant 와 production 에서 사람들 무는 gotcha 가진 full lesson 으로 만들 거야.

  • GET — "이 resource 의 representation 줘." Safe, idempotent, cacheable. 웹에서 가장 많이 쓰이는 method.
  • POST — "이 payload 를 이 resource 에 대해 처리해." Not safe, not idempotent. "뭔가 해줘" 의 만능.
  • PUT — "이 resource 를 payload 로 교체해." Idempotent. 같은 PUT 5번 보내도 같은 state.
  • PATCH — "이 부분 update 를 적용해." 일반적으로 not idempotent. 전체 resource 안 보내고 필드만 update 할 때.
  • DELETE — "이 resource 지워." Effect 면에서 idempotent (지워진 건 지워짐). 두 번째 DELETE 는 404 나 204 돌려주지만 state 는 같아.
  • HEAD — "GET 처럼 response header 줘, 근데 body 는 빼." 싼 존재 / 신선도 체크.
  • OPTIONS — "이 URI 가 어떤 method 받아?" 브라우저가 CORS preflight 로 많이 써 (Track 4).

둘 더 있는데 앱 코드에선 거의 안 중요:

  • TRACE — debug echo. Server 가 보통 비활성화 (cross-site tracing 공격 보안 이유).
  • CONNECT — TCP tunnel 열기. HTTPS proxy 가 씀; 앱 코드에선 CONNECT 거의 안 써.

세 가지 invariant (Track 2 미리보기)

모든 method 의 계약은 yes/no 질문 셋으로 줄어:

  • Safe? — server state 안 바꾼다고 약속해? (GET, HEAD, OPTIONS 가 safe.)
  • Idempotent? — 같은 request 반복해도 같은 state 남아? (GET, PUT, DELETE, HEAD, OPTIONS 가 idempotent. POST 와 PATCH 는 아님.)
  • Cacheable? — Response 를 저장하고 재사용할 수 있어? (GET 과 HEAD 가 기본; POST 는 명시 header 가 그러라고 해야만.)

이 세 속성이 proxy, CDN, retry 로직이 의존하는 거야. POST 는 CDN 이 조용히 retry 못 해 — POST 가 not idempotent 라서 CDN 이 retry 가 중복 만들지 모름. GET 은 10분 캐시 가능 — GET 이 safe + idempotent 이라서. Method 는 호환 안 돼; 계약이야.

Method 는 계약의 일부야. Server 가 POST /users/42 를 "user 42 update" 로 받아들이면, POST (process) 를 PUT (replace) 나 PATCH (partial update) 와 섞은 거야. Client 와 중간자가 operation 비용이나 retry 안전성을 알 수 없어. 처음부터 올바른 verb 고르면 caching, observability, reliability 에서 본전 뽑아.

cwkPippa 의 method 현실

backend/routes/ 걸으면 흔한 method 다섯 다 보여: 대화/폴더는 GET, 새 채팅/업로드는 POST, 이름 변경은 PUT, 폴더 부분 update 는 PATCH, 항목 삭제는 DELETE. OPTIONS 는 모든 endpoint 에서 FastAPI 의 CORS middleware 가 자동 처리 — 직접 OPTIONS handler 안 써. HEAD 는 주로 health check 와 pre-flight probe 가 써.

Code

각 HTTP method 한 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 — 같은 shape, method 당 함수 하나·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 method 당 decorator 하나·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

Resource 하나 가진 작은 FastAPI (혹은 Express) 앱 띄워 — 예를 들어 /notes. GET, POST, PUT, PATCH, DELETE handler 정의해. 그 다음 각각을 curl 로 호출하고 status code 봐. 보너스: 정의 안 한 method 를 일부러 호출해 (예: GET/POST 만 썼는데 PATCH). 어떤 status code 가 오고, 어떤 response header 가 client 한테 어떤 method 가 허용되는지 알려줘?
Hint
정의된 resource 의 정의 안 된 method 는 405 Method Not Allowed 돌려줘. Response header 는 Allow: GET, POST (네가 정의한 거 뭐든). 이게 client 가 문서 안 읽고 verb 단어를 발견하게 해주는 wire-level mechanism 이야.

Progress

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

댓글 0

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

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