본문 바로가기
개발관련/FastAPI(BE)

FastAPI - (3) Request Body

by yjoo_ 2023. 10. 10.

이번 편에서는 Request Body를 다뤄볼 예정이다.

https://fastapi.tiangolo.com/ko/tutorial/body/

https://fastapi.tiangolo.com/ko/tutorial/body-multiple-params/

https://fastapi.tiangolo.com/ko/tutorial/body-fields/

https://fastapi.tiangolo.com/ko/tutorial/body-nested-models/

 

순서 상 중간에 매개변수 검증 파트가 끼어있으나, Body와 묶어서 정리해보도록 하겠다.


Request Body?

이전 시간에 HTTP 메서드를 언급할 때 Body를 언급한 적이 있다.

POST와 PUT 요청, 즉 데이터 생성과 수정 요청 시 그 데이터 값을 가지고 있는 녀석들이다.

 

웹에서 말하는 요청은 일반적으로 HTTP 요청을 말한다.

HTTP 요청은 크게, header와 body로 나뉘어져 있다.

자세한 내용은 따로 검색해서 찾아보길 추천한다.

대충 이런 형태의 구조를 가지고 있는데, 우리가 이번에 다룰 Body는 초록색 영역데이터부분이다.

물론 모든 HTTP 요청이, Body를 보낼 필요는 없다. 위에서도 언급했는 POST와 PUT같이

사용자가 데이터를 보내야 하는 상황에서 사용한다.

 

클라이언트에서 FastAPI 서버로 요청을 보낼 때 정해진 규격에 맞게 보내야 우리가 예상하고 데이터를 처리할 수 있다.

 

그 정해진 규격을 정의하는 방법은 FastAPI에서 사용하는 Pydantic 라이브러리에서 지원하고 있다.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

# DB가 없으니 임시로 데이터를 저장할 person객체
person = []

# Person 모델 선언
class Person(BaseModel):
	# 타입 어노테이션이라 부르며 int형과 str을 보장하도록 한다.
	age: int
	name: str

# Person 클래스의 인스턴스는 어떻게 생겼는지 확인하는 코드
@app.get("/jym")
async def get_JYM():
	JYM = Person(age=25, name='주영민')
	return JYM

if __name__ == "__main__":
	import uvicorn
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

FastAPI에서 Model을 선언해보자.

 

DB로 데이터를 저장할 때, RDBMS에선 정해진 형태의 테이블에 값을 저장한다.

 

당연히 프론트엔드에서 값들을 받아와서 특정 규격에 맞게 데이터를 정렬한 뒤
데이터베이스에 저장하는 과정이 진행된다.

 

그렇다면 각 API에서 호출 요청에 맞춰 매번 노가다 코드를 작성해서 정렬할 것인가?

 

Smart하지 못한 방법이다.

 

Class란 자주 사용하는 객체의 특성들을 설계하는 일종의 틀이다.

당연히 데이터 구조에도 똑같이 사용할 수 있다.

 

그렇기에 자주 사용하는 데이터 유형을 의미하는 Model은 Class로 선언된다.

 

BaseModel을 상속하는 이유는 심플하다. Model에 어떤 데이터가 전달되든 프로그래머가 지정한 타입을 보장한다.

 

만약에 타입 캐스팅(변환)이 불가능하다면, 에러를 발생시킬 뿐이다.

 

물론 BaseModel은 다양한 기능을 지원하지만, 너무 많이 알아봤자 머리만 아프니까 필요할 때 설명을 추가하겠다.

 

위 코드를 실행해보자!

Person 모델의 인스턴스를 리턴하면 JSON형태로 리턴된다.

 

이번엔 입력을 받아보자. 코드를 다음과 같이 수정한다.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

person = []

class Person(BaseModel):
	age: int
	name: str

# post 요청이 온다면
@app.post("/signup")
async def signup(user: Person):
	# 입력받은 데이터는 모델 인스턴스로 받는다.
    # user를 6번 라인의 person 리스트에 추가
	person.append(user)
	return person

if __name__ == "__main__":
	import uvicorn
	uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

FastAPI 앱을 실행하고 docs로 이동한다.

코드 주석에 설명을 달아두었으니 꼭 읽어보기를 바란다.

 

Try it out버튼을 눌러보면 API 테스트가 가능해진다.

 

이녀석이 바로 request body!

key값은 건들지말고 value만 수정해서 excute해주면 

 

이건 Response body로 요청 바디가 아닌 응답 바디다.

이런 결과 값이 나온다.

 

코드를 조금 읽어봤다면 이해했겠지만, 입력할수록 점점 쌓인 리스트가 return되도록 만들었다.

다만 DB에 저장한 것이 아니라 서버가 꺼졌다 켜지면 데이터가 사라지게된다.

 

사실 22.5살과 23.5살이 섞여있다. 빠른년생 같으니라고

자 이제 Request Body가 무엇인지 대충 감이 잡혔을 것이다.

그냥 입력 폼의 값을 넘기는 JSON 객체 그것이 Request Body다.

 

당연히 request body, 쿼리 매개변수, 경로 매개변수는 모두 다 같이 사용이 가능하다.

아래 코드를 참조해보자.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

person = []

class Person(BaseModel):
	age: int
	name: str

@app.post("/signup/{item_id}")
async def signup(user: Person, item_id: int, q: str):
	person.append(user)
	return {
		"item_id": item_id,
		"person": person,
		"query": q 
		}

if __name__ == "__main__":
	import uvicorn
	uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

마침 쿼리 매개변수, 경로 매개변수, Model까지 나왔으니 한가지를 더 다뤄보도록 하겠다.

 

우리는 사용자로부터 다양한 값을 받는다. 필수적으로 입력받아야 하는 값도 있지만,

사용자가 입력하기를 선택할 수 있는 경우도 있다.

 

이런 경우의 처리를 어떻게 해야할까?

 

class Person(BaseModel):
	age: int
	name: str
	job: str
	hobby: str
	major: str

예시를 모델로 잡기는 했으나, 쿼리나 경로에서도 적용되는 사항이다.

직업, 취미, 전공은 모두 대부분의 사람이 갖고있으나, 없는 경우도 존재하는 데이터다.

그냥 이 상태로 쓴다면, 어떤 한 데이터라도 비어있으면 오류가 날 것이다.

 

typing 라이브러리의 Union이나 Optional을 사용하면 된다.

다음은 사용하는 예시이다.

class Person(BaseModel):
	age: Union[int, float]
	name: str
	job: Optional[str] = None
	hobby: str | None = None
	major: Union[str, None] = None

당연히 여기서 사용된 문법은 쿼리, 경로 파라미터에서도 그대로 사용 가능하다.

각 어노테이션 끝에 = None이 사용된 이유는 str이 아니라 None일 때 기본 값을 지정해주기 위함이다.

'개발관련 > FastAPI(BE)' 카테고리의 다른 글

FastAPI - (5) Model  (0) 2023.10.19
FastAPI - (4) DB 연결하기  (0) 2023.10.16
FastAPI - (2) HTTP메소드, URL 매개변수  (1) 2023.10.07
FastAPI - (1) 개념 및 설치  (2) 2023.10.06