fastapi Swagger Response 분리하기
개요
fastapi 를 사용하고 있는데, fastapi 공식문서를 따라가면서 swagger문서를 작성하다보니 불편함을 느꼈다.
그것은 바로
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@router.get("/ingredient",
responses={
status.HTTP_200_OK: {
"description": "재료 조회 성공",
"content": {
"application/json": {
"example": {
"code": 200,
"message": "Success",
"data": [
{
"ingredient_name": "당근",
"ingredient_url": "https://default.image"
},
{
"ingredient_name": "토마토",
"ingredient_url": "https://default.image"
},
{
"ingredient_name": "치즈",
"ingredient_url": "https://default.image"
}
]
}
}
}
},
status.HTTP_401_UNAUTHORIZED: {"description": "토큰 에러",
"content": {
"application/json": {
"example": {
"code": 401,
"message": "Parsing Error token",
"data": None
}
}
}
}
}
)
async def search_ingredient_history(
db: Session = Depends(get_db),
user: Optional[UserResponseByToken] = Depends(get_current_user_authorizer())
):
return StandardizedResponse(code=200, data=await user_service.search_ingredient_history(db, user))
이런 코드들이 Controller
에 너무 많이 있었다.
뭐가 불편한가?
service를 호출하는 코드는 return StandardizedResponse(code=200, data=await user_service.search_ingredient_history(db, user))
로 단 한 줄인데 swagger를 작성하는 코드는 약 40줄에 달한다.
배보다 배꼽이 더 큰 상황인데, 이런 코드들이 점점 많아지니까 스웨거를 자세히 작성하는데에 불편함도 느끼고 함수를 찾아가는데에도 번거로움을 느꼈다. 무엇보다 정리되지 않은 느낌이 싫었다.
해결방법
분리하기 위해서는 2가지 방법이 있었다.
- 직접
.yml
파일을 작성하고, 해당 파일을 명시하는 방법 - 함수형태로 호출
각각 장단점이 있는데, .yml
파일을 작성하면 간결하게 읽을 수 있겠지만 모델이 변경하는 등의 수정작업이 있으면 .yml
파일도 같이 수정해줘야한다.
함수호출형태는 수정작업이 이루어져도 모델을 참조하고 있기에 관리가 용이하지만 파일이 늘어난다는 단점이 있다.
나는 관리포인트를 최소화하고 싶어서 함수호출형태로 변경하였다.
사전준비
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@router.post(
"/verification",
description="사용자 토큰 검증 api",
status_code=status.HTTP_200_OK,
response_description="유저의 email과 이름 정보",
responses=verification_user_response()
)
## 분리된 파일
def verification_user_response():
return {
status.HTTP_200_OK: {
"description": "Success",
"content": {
"application/json": MediaType(
example=Example({
"code": 200,
"message": "Success",
"data": {
"name": "username",
"email": "test@naver.com",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuaWNrbmFtZSI6IkppaG8gSmFuZyIsImV4cCI6MTcxMjIyODAzM30.RUl1PC3VuuQuldnl0IZMg4YEgSq-P1oZmKDrnjzt-uZ"
}
})
)
}
},
status.HTTP_401_UNAUTHORIZED: {
"description": "Unauthorized",
"content":{
"application/json": MediaType(
example=Example({
"code": 401,
"message": "Parsing Error token",
"data": None
})
)
}
}
}
이렇게 작성해주면 된다.
이게 가능한 이유는 @router
에 response가 스키마를 구성할때 데이터 타입은 dictionary
로 데이터를 받고 있기에 위와같은 구조가 가능한 것이다.
이렇게 한결 깔끔하게 문서관리를 할 수 있게 되었다.
끝
This post is licensed under CC BY 4.0 by the author.