콘텐츠로 이동

HTTP 요청 개요#

2024 iThome 철인 대회

이 글은 Django Ninja 입문 가이드의 9번째 글이에요.

3장 2절에 오신 것을 환영해요!

API의 핵심 로직 구현체로서 뷰(view) 함수는 의심할 여지 없이 Django Ninja API의 영혼이라고 할 수 있어요.

Django Ninja는 FastAPI나 Flask와 마찬가지로 주로 function-based views(이하 FBVs)를 사용해요. 따라서 학습의 핵심은 대부분 뷰 함수의 입출력(input과 output)을 중심으로 이루어져요.

다시 말해, 전체 Django Ninja 프레임워크의 기능은 뷰 함수의 이러한 핵심 부분들을 구성하며, 여기에는 다음이 포함되지만 이에 국한되지는 않아요:

  1. HTTP 요청의 매개변수와 본문(body) 처리.
  2. HTTP 응답 내용의 직렬화 및 형식화(formatting).
  3. 데이터 검증 및 에러 처리.

이것들이 함께 Django Ninja의 주요 기능을 구성해요.

이번 절과 다음 절에서는 위 3가지 포인트 중 처음 두 가지인 요청과 응답에 집중할 거예요. 세 번째 포인트는 5장에서 다시 소개할게요.

GitHub 예제 프로젝트#

👉 Django-Ninja-Tutorial


이번 절 안내#

이전 절의 "라우팅"에 이어, 이번 절에서는 Django Ninja가 HTTP 요청을 어떻게 처리하는지—경로(path), URL 쿼리 매개변수 및 본문을 어떻게 분석(parse)하는지—살펴볼게요.

이번 절은 총 4편으로 구성되어 있어요:

또한, 뷰 함수의 요청 처리 기능은 이미 Django Ninja가 Python의 타입 힌트(type hints)를 사용하여 요청 데이터를 어떻게 검증하는지와 연관되어 있으므로, 예제 코드에 Python 타입 힌트를 추가하기 시작할 거예요.

타입 힌트 문법은 Python 3.12를 기준으로 해요.

공식 문서#

이 시리즈를 작성하면서 종종 "Django Ninja 공식 문서"를 참조하게 되는데, 특히 아키텍처 표현 부분에서 그래요.

하지만 문서는 결국 모든 개발자를 대상으로 쓰인 것이라, 학습 순서가 충분히 고려되어 있지 않아요.

이 시리즈는 주로 입문자를 대상으로 하기 때문에, 실제 조작과 입문자의 요구에 더 중점을 두고 적절히 배경 지식을 보충하여 학습 곡선이 비교적 완만할 수 있도록 보장할게요.

또한 프레임워크 자체에 대해서도 더 많은 예시와 설명을 제공하여 새로운 개념을 더 잘 이해하고 숙달할 수 있도록 할 거예요.

그럼에도 불구하고 공식 문서는 Django Ninja를 사용할 때 항상 참고해야 할 내용이에요. 비록 Django나 Django REST framework의 문서보다는 비교적 "간단하게" 쓰여 있긴 하지만요!


이 글의 요지#

이번 2절의 개론으로서 이 글의 목표는 Django Ninja의 뷰 함수와 그것이 HTTP 요청을 어떻게 처리하는지에 대한 기본적인 이해를 돕는 것이에요.

다음 세 가지 핵심 사항을 통해 여러분이 점진적으로 익숙해지도록 할게요:

  1. FBVs의 장점.
  2. Django Ninja의 HTTP 요청 처리 흐름.
  3. Django Ninja와 Type Hints의 긴밀한 결합.

말은 이만 줄이고 바로 시작할게요.


Class-based views (CBVs)와 FBVs는 모두 Django MTV 아키텍처에서 Views를 구현하는 수단으로, 각각 적합한 시나리오가 있어요.

CBVs는 코드 재사용에 이점이 있어 대형 프로젝트에 적합해요. 반면 FBVs는 간단하고 직관적이라는 점이 매력적이어서 중소형 프로젝트를 빠르게 개발하는 데 유용해요.

이 둘의 비교는 〈Day27 : CBV vs. FBV〉 글을 참고하셔도 좋아요.

Django Ninja는 FBVs를 채택하고 있으므로, 이 글에서는 FBVs의 장점만 다룰게요.

1. FBV의 장점#

FBVs는 Django Ninja가 채택한 뷰 형식이에요. CBVs에 비해 FBVs는 더욱 간결하고 유연하여, "어떤 CBV 속성을 올바르게 오버라이드해야 하는지"와 같은 배경 지식을 많이 알지 못해도 개발자가 쉽게 API 로직을 작성할 수 있게 해줘요.

간결함과 유연성#

FBVs는 클래스 메서드를 상속하거나 오버라이드할 필요 없이, 모든 로직이 하나의 함수에 집중돼요.

이는 코드 작성과 유지보수를 훨씬 더 직관적으로 만들어 줘요.

FBVs는 본질적으로 함수이기 때문에, 다양한 로직과 조건을 더 유연하게 적용할 수 있어요. 개발자는 클래스의 구조나 상속 관계를 고려할 필요 없이, 단일 함수 내에서 요청 처리의 전체 흐름을 완벽하게 제어할 수 있답니다.

쉬운 디버깅#

FBVs의 코드는 비교적 직관적이어서 초보자도 읽고 이해하기 훨씬 쉬워요. 오류가 발생했을 때 문제를 빠르게 파악할 수 있는데, 이는 CBVs로는 쉽게 얻기 힘든 편리함이에요.

제 생각#

Django는 포괄적인 기능을 제공하는 프레임워크지만, 종종 "무겁다"고 비판받기도 해요. FBVs는 어느 정도 이러한 무거운 느낌을 완화해 줘요.

상상해 보세요. 막 Django를 접한 초보자가 다양한 프레임워크의 환경 설정을 이해한 뒤, CBVs의 세계까지 깊이 파고들어야 한다면 너무 버겁지 않을까요?

결론적으로, 저에게 묻는다면 저는 절대적으로 FBVs를 선호해요. 그리고 "경량화"는 현대 개발의 트렌드이기도 하죠.


2. Django Ninja의 HTTP 요청 처리 흐름#

Django Ninja에서 "요청"을 처리하는 과정은 몇 가지 핵심 단계로 나눌 수 있어요:

  1. 라우팅 매칭: 요청이 들어오면 프레임워크는 먼저 들어온 URL을 정의된 경로 규칙(엔드포인트)과 일치시켜요. 매칭이 성공하면 HTTP 요청과 관련 매개변수를 뷰 함수로 전달해요.
  2. 매개변수 파싱: URL에서 경로 매개변수(path parameters)와 쿼리 매개변수(query parameters)를 추출하여, 뷰 함수의 "인자"(arguments)로 변환해요. 함수의 타입 힌트에 따라 자동으로 타입 변환과 검증이 이루어져요.
  3. Request body 처리: POST나 PUT처럼 본문(body)이 있는 요청의 경우, Django Ninja는 개발자가 Schema(Pydantic BaseModel)를 사용해 본문 데이터 모델을 정의하게 하고, 들어온 데이터를 자동으로 이 모델에 매핑해 줘요.

Django Ninja HTTP 요청 처리 흐름

위 1번 항목은 이 장의 첫 번째 절에서 자세히 설명했어요.

2번과 3번 항목은 이번 절을 구성하는 총 4편의 글에서 다룰 주요 내용이에요.


3. Django Ninja와 Type Hints의 긴밀한 결합#

Django Ninja는 HTTP 요청 내의 데이터를 처리할 때 Python의 type hints에 매우 크게 의존해요.

그리고 Pydantic을 통해 자동 데이터 검증타입 변환을 구현하여, 개발자가 수동으로 데이터를 확인하고 변환하는 부담을 줄여줘요.

예를 들어 다음 코드를 볼까요:

@router.get("/posts/{post_id}")
def get_post(request, post_id: int):
    return {"post_id": post_id}

post_id 매개변수가 int로 표시되면, Django Ninja는 타입 검사를 수행해요. 만약 전달된 매개변수가 int로 변환될 수 없다면, 프레임워크는 상태 코드가 422인 HTTP 응답을 즉시 반환해요.

다시 말해, post_idstr로 표시한다면 Django Ninja는 자동으로 post_id를 문자열로 변환할 거예요.

Django Ninja를 처음 접했을 때, Python의 type hints를 이 정도로 훌륭하게 활용할 수 있다는 사실에 매우 놀랐던 기억이 나요. 단순한 타입 안전성을 위한 도구를 넘어, 전체 API 개발 흐름에 녹아들어 있었거든요.

뷰 함수 내의 request 매개변수#

위 예제에서 주목할 만한 세부 사항이 있는데, 바로 뷰 함수의 첫 번째 매개변수request예요.

Django에서 뷰 함수의 첫 번째 매개변수는 반드시 request여야 해요. 이 매개변수의 이름은 사용자 정의가 가능하지만, 보통 request로 명명해요.

HTTP 요청을 받을 때, Django는 전체 요청을 HttpRequest 객체로 패키징하고 이를 첫 번째 매개변수로서 뷰 함수에 전달하므로, 이것은 필수불가결한 요소예요.

관련 글: Django HttpRequest 주요 속성 소개

request 매개변수는 Django와 Django REST framework에서 매우 중요한데, 요청의 쿼리 매개변수나 body 등의 내용을 가져오는 데 자주 사용되기 때문이에요.

Django Ninja에서는 이러한 데이터들을 함수의 매개변수를 통해 직접 가져오기 때문에, request가 여전히 필요하긴 하지만 사용 빈도는 상대적으로 낮아요.


다음 단계#

다음으로 우리는 Django Ninja가 요청을 처리하는 구체적인 세부 사항을 깊이 있게 탐구해 볼게요.

다음 글에서는 경로 매개변수(path parameters)에 초점을 맞추고, Django 고유의 path converters와 어떻게 함께 사용하는지 알아볼 거예요. 기대해 주세요!