FastAPI - 응답모델

2025. 9. 1. 11:28Programming Language/Python

반응형

Fast API의 라우트 데코레이터(@app.post("/mian") 이 부분)에는 response_model이라는 것이 있는데 이는 스키마를 고정하고 Swagger UI에 문서화로 설정해서 클라이언트가 응답의 형태를 예측할 수 있도록 해주고, 런타임 시점에 핸들러가 타입을 변경해서 반환을 해도 지정한 모델로 검증 및 변환해서 반환하고 모델에 작성되지 않은 필드는 자동으로 제거 해줌으로써 응답을 원하는대로 제한해서 전달할 수 있게 된다.

 

1. response_model의 사용

우선 모델 하나를 생성해주고

이걸 함수의 매개변수로 넣어주자.

그리고 라우트 데코레이터에 response_model을 넣어주고 그 값으로 모델 타입을 넣어주면

이러면 설정이 끝난다

 

2. 응답의 제한

위의 상태에서 password를 뺀 새로운 모델을 하나 만들어보자.

사용자는 요청을 비밀번호를 포함시켜 보냈으나 우리의 응답이 같은 모델로 나갈 경우 비밀번호가 노출될 가능성이 있다.

물론 사용자에게 그대로 돌려보내는거라 당장은 문제가 없으나 보안적으로 비밀번호를 반환한다는건 안될 말이다.

 

이럴 때 위 처럼 응답하지 않고 싶은 멤버를 제외한 새로운 모델을 생성하고 이를 response_model의 값으로 넣어주면

응답의 모델이 비밀번호를 포함하는 형태의 모델이더라도 

response_model에 설정된 모델의 형태에 맞게 password는 제한 응답을 반환한다.

 

그리고 Swagger UI에 보면 

정상 응답의 형태가 해당 모델로 변경되어 반환시킨다는 내용을 확인할 수 있다.

 

여기서 주의해야할 점은 response_model을 사용하는 경우는 최상위 응답의 형태를 강제한다는 특징이 있다.

그렇기에 

@app.post("/response", response_model=Secret_Response_Test)
def response_test(response_test: Response_Test):
    return {"msg": "response_model", "response_test": response_test}

이렇게 서버의 메서드를 만들면 먼저 response_model에 설정된 Secret_Response_Test는 Response_Test모델의 멤버인 id와 name만 있는객체를 return할 것을 기대하는데 return값은 msg와 response_test라는 것으로 구성되어 있으니 pydantic이 매핑하지 못해 ResponseValidationError(500)를 반환하게 된다.

 

그렇기에 response_model의 형태는 응답하는 객체 자체만을 전달해줘야 한다.

아니면 그걸 분리해서 넣어 반환하거나 응답을 위한 형태의 반환 객체를 만들어서 반환하는 것이 좋다.

 

3. 멤버의 제외

모델에는 기본적으로 요청에 값이 들어오지 않은 경우에 기본적으로 값을 형성하게 하기 위해서 기본값을 넣는다 

이 값들은 사용자가 요청에 담아 보내지 않았으나 응답에서는 객체를 전체를 return하기에 None값으로 전달되게 될것이다 

이렇게 사용자가 요청에 값을 담아보내지 않아 기본값이 담긴 멤버를 제외하고 싶다면 라우팅 데코레이터에 response_model_exclude_default이라는 속성에 True/False를 전달해서 제외할지 말지를 설정할 수 있다.

그리고 요청을 던져보면

이렇게 기본값을 제외한 값만을 응답으로 전달한다.

 

그리고 response_model_exclude라는것을 사용할 경우 값을 리스트로 문자열의 형태로 제외하기를 원하는 멤버의 이름을 전달하면

요청에 값을 담아 보내더라도 응답에서 그값을 제외하고 전달한다.

 

4. 모델끼리의 처리 

프로그램을 만들다보면 서로 연관된 모델을 여러가지를 가지게 되는 경우가 다반사이다.

특히 사용자의 정보에 대한 처리를 할때에는 다수의 모델을 가지게 되는데 이는 사용자에게 받을 모델, 사용자에게 전달할 모델, 데이터베이스에 넣기 위한 모델 각각 데이터에 대한 처리를 추가적으로 해야하기 때문이다.

 

예를 들어 사용자에게 기존에 입력을 받는 모델을 보자면

이렇게 구성이 될 수 있는데 이는 사용자로 하여금 데이터를 모두 받아 데이터베이스에 저장하기 위함이다.

 

그런데 사용자에게 응답을 줄 때에는 여기서 비밀번호는 궂이 보내줄 필요가 없기에 사용자한테 전달하기 위한 모델을 또 추가로 구성하게 된다.

그리고 이 모델을 라우팅 데코레이터 내부에 response_model에 등록하면 

사용자에게 해당 모델에 해당하는 멤버들만 User_Info에서 걸러서 응답해라 라고 할 수 있다.

 

이제 이렇게 만든 데이터를 DB에 저장해야할텐데 이때 비밀번호는 그냥 그 자체 평문으로 저장하는게 아니라 암호화를 해서 이를 DB에 넣어 저장을 해줘야 한다 .

그렇기에 우선 DB에 넣을 모델을 하나 만들어주고

그리고 평문을 암호화 해줄 함수를 하나 선언해주자

해당 함수는 그냥 단순하게 사용자 정보를 전달하면 비밀번호에 문자열을 붙여 암호화 됐다고만 일단 넣어서 전달하자.

 

그리고 해당 함수를 호출해서 암호화된 값을 User_Info_DB에 넣어주는 기능을 넣어주자.

그리고 해당 DB 모델을 응답으로 넣어주면 

이렇게 응답의 형태는 응답을 위한 모델의 형태로 나오고 이 안에 암호화된 비밀번호가 저장되어 있는건 

이렇게 서버측에서 확인하고자 print문을 찍어보면 저장되어 있는 것을 볼 수 있다.

 

이런식으로 연관있는 모델들이 다수 생기기도하고 이게 맞게 소스코드를 구성해야함을 볼 수 있다.

 

이때 보면 모델끼리의 중복되는 동일한 모델들이 존재하게 된다.

이 중복을 제거하기 위해서는 base가 되는 모델을 하나 생성해주고(기본적으로 공통되는 멤버에 대해서는 해당 모델에 작성해준다.)

추가적으로 필요한 것들에 대해서만 추가로 모델을 구성해주고

이제 공통되는 Base 모델을 모두 상속해주면

이러면 중복되는 코드를 제거할 수 있다.

기능도 물론 동일하게 작용한다.

 

반응형

'Programming Language > Python' 카테고리의 다른 글

FastAPI - Exception  (0) 2025.09.02
FastAPI - Form Data 받기  (1) 2025.09.01
FastAPI - example  (1) 2025.08.29
FastAPI - 모델의 중첩  (0) 2025.08.29
FastAPI - RequestBody 다중 매개변수  (1) 2025.08.29