HTTP 요청·응답과 REST API 설계
4강. HTTP 요청·응답과 REST API 설계
1. 이번 강의에서 해결할 문제
기능을 추가할 때마다 임의의 URL을 만들면 클라이언트가 API를 예측할 수 없습니다. 게임 기록을 리소스로 보고 일관된 REST 계약을 작성합니다.
2. 학습 목표
3. 핵심 개념
REST API에서는 URL이 명사형 리소스를, HTTP 메서드가 행동을 표현합니다. GET은 조회, POST는 생성, PATCH는 부분 수정, DELETE는 삭제에 사용합니다. 성공 응답은 보통 200, 생성은 201, 본문 없는 삭제는 204를 사용하며 없는 리소스는 404로 알립니다.
HTTP 요청은 "어디에 무엇을 요구하는가"를 여러 부분으로 나눕니다.
| 부분 | 의미 | 예 |
|---|---|---|
| method | 리소스에 수행할 동작의 성격 | POST |
| path | 대상 리소스 | /records |
| headers | 본문 형식·인증 같은 부가 정보 | Content-Type: application/json |
| body | 생성·수정에 필요한 데이터 | {"game_name":"Rule Break","score":1200} |
| status code | 서버가 처리 결과를 요약한 숫자 | 201 Created |
| response body | 클라이언트가 사용할 결과 또는 오류 정보 | 생성된 기록 JSON |
가장 작은 HTTP 계약 읽기
POST /records HTTP/1.1
Content-Type: application/json
{"game_name":"Rule Break","score":1200}
이 요청은 /create-score라는 동사형 경로 대신 records라는 대상을 path로 두고, 생성 행동을 POST로 표현합니다. 성공 응답은 다음처럼 구분할 수 있습니다.
HTTP/1.1 201 Created
Content-Type: application/json
{"id":1,"game_name":"Rule Break","score":1200}
상태 코드는 단순 장식이 아닙니다. 프론트엔드는 201이면 새 카드를 목록에 추가하고, 422면 입력 오류를 보여 주며, 401이면 로그인 화면으로 안내하는 식으로 분기합니다.
4. 단계별 코드 예시
파일 경로: game-ranking-api/docs/api-design.md
구현 전에 표를 작성하면 프론트엔드와 백엔드가 같은 method·path·성공 결과를 기준으로 작업할 수 있습니다. 같은 리소스라도 목록과 상세는 path 모양으로 구분합니다.
| Method | Path | 의미 | 성공 |
| --- | --- | --- | --- |
| GET | /records | 기록 목록 | 200 |
| POST | /records | 기록 생성 | 201 |
| GET | /records/{record_id} | 기록 상세 | 200 |
| PATCH | /records/{record_id} | 기록 일부 수정 | 200 |
| DELETE | /records/{record_id} | 기록 삭제 | 204 |
| GET | /rankings | 게임별 랭킹 | 200 |
파일 경로: game-ranking-api/app/main.py
from fastapi import FastAPI, status
app = FastAPI(title="Game Ranking API")
@app.post("/records", status_code=status.HTTP_201_CREATED)
def create_record() -> dict[str, object]:
return {"id": 1, "game_name": "Rule Break", "score": 1200}
코드 한 줄씩 이해하기
status모듈은 의미 있는 상수 이름으로 HTTP 상태 코드를 선택하게 합니다.@app.post("/records", ...)는 POST method와/recordspath 조합을 등록합니다. GET/records와는 별도 작업입니다.HTTP_201_CREATED는 새 리소스가 생성됐다는 계약을 응답과 OpenAPI 문서에 반영합니다.create_record가 반환한 dict는 JSON이 됩니다. 지금은 입력과 DB가 없어 매번 같은 값만 반환하는 학습용 단계입니다.- 반환 타입의
object는 값 종류가 섞일 수 있음을 나타내지만, 이후 강의에서는 Pydantic 모델로 더 정확한 계약을 만듭니다.
실행 위치: game-ranking-api/
python -m uvicorn app.main:app --reload
Invoke-WebRequest -Method Post http://127.0.0.1:8000/records | Select-Object StatusCode, Content
구체적인 실행 결과
StatusCode Content
---------- -------
201 {"id":1,"game_name":"Rule Break","score":1200}
브라우저 주소창은 기본적으로 GET을 보내므로 주소창에 /records를 입력하는 것만으로 POST 코드를 시험할 수 없습니다. PowerShell, API 문서 /docs, curl처럼 method를 지정할 수 있는 도구를 사용합니다.
5. 코드가 동작하는 이유
경로는 기록이라는 리소스를 나타내고 POST가 생성을 표현합니다. status_code는 실제 응답과 OpenAPI 문서에 201을 기록합니다. 아직 값은 메모리에 고정되어 있지만 계약부터 결정했습니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
8. 이해 점검 질문 3개
9. 핵심 요약
다음 강의 연결
method·path·상태 코드 계약을 만들었습니다. 5강. Path와 Query 매개변수에서 /records/{record_id}의 한 기록과 목록 필터 값을 실제 함수 입력으로 받습니다.
HTTP와 REST 설계 점검
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.