Home FastAPI란?
Post
Cancel

FastAPI란?

0. 학습 이유

재직 중 국비 교육으로 Multi AI Agent 프로젝트 과정을 수강하게 되었고,
백엔드 구현 기술로 FastAPI를 사용하게 되었다.

기존에 Python을 사용해 본 경험은
4년전 첫 직장에서 입사 초기에 3~4개월 가량 진행했던 Spoon Radio 백오피스 Django 프로젝트를
Kotlin + Spring Boot로 컨버팅했던 것이 전부라
사실상 PythonFastAPI 모두 처음이라고 봐도 무방한 상태였다.

이번 프로젝트를 진행하면서
FastAPI 프레임워크를 학습해야 했고,
이 과정에서 Python 언어 자체도 함께 다시 정리할 필요가 있다고 생각했다.

그래서 FastAPI를 학습하면서
프레임워크 사용 방법뿐만 아니라
Python 기본 문법과 비동기 처리 방식까지 같이 정리하려고 한다.

이 글은 FastAPI를 얕게 학습하면서 정리한 내용이다.


2. FastAPI란?

FastAPI는 Python으로 API 서버를 만들기 위한 웹 프레임워크이다.

공식 문서에서는 FastAPI를 다음과 같이 설명한다.

  • 빠름: (Starlette과 Pydantic 덕분에) NodeJS 및 Go와 대등할 정도로
  • 매우 높은 성능. 사용 가능한 가장 빠른 파이썬 프레임워크 중 하나.
  • 빠른 코드 작성: 약 200%에서 300%까지 기능 개발 속도 증가. *
  • 적은 버그: 사람(개발자)에 의한 에러 약 40% 감소. *
  • 직관적: 훌륭한 편집기 지원. 자동완성이 모든 곳에서 동작. 적은 디버깅 시간.
  • 쉬움: 쉽게 사용하고 배우도록 설계. 적은 문서 읽기 시간.
  • 짧음: 코드 중복 최소화. 각 매개변수 선언의 여러 기능. 적은 버그.
  • 견고함: 준비된 프로덕션 용 코드를 얻으십시오. 자동 대화형 문서와 함께. 표준 기반: API에 대한 (완전히 호환되는) 개방형 표준 기반: OpenAPI (이전에 Swagger로 알려졌던) 및 JSON Schema.

3. Spring과 FastAPI API(Input Adapter) 처리 방식 비교

3.1 Endpoint 정의

  • 비교
    • Spring : Annotation기반으로 컨트롤러와 요청 URL을 매핑한다.
    • FastAPI : Decorator기반으로 함수와 요청 URL을 직접 매핑한다.
  • 차이
    • 구조적으로 Spring은 클래스 > 함수 계층으로 구성되어있어 클래스별로 그 역할이 명확하게 드러나고, FastAPI는 함수 단위로 매핑되어 간결하고 빠르게 작성가능.
  • 코드
    • Spring
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        
        @RestController
        @RequestMapping("/users")
        public class UserController {
            @GetMapping
            public String getUsers() {
                return "users";
            }
            @PostMapping
            public String createUser() {
                return "created";
            }
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        7
        8
        
        from fastapi import FastAPI
        app = FastAPI()
        @app.get("/users")
        def get_users():
            return {"result": "users"}
        @app.post("/users")
        def create_user():
            return {"result": "created"}
        

3.2 Path Variable

  • 차이 : Spring에서는 @Pathvariable을 이용하여 함수 파라미터로 선언해야 했으나 FastAPI에서는 경로 변수와 함수 인자명이 같으면 자동으로 매칭이된다.

  • 코드

    • Spring
      • 1
        2
        3
        4
        
        @GetMapping("/users/{id}")
        public String getUser(@PathVariable Long id) {
            return "user id = " + id;
        }
        
    • FastAPI
      • 1
        2
        3
        
        @app.get("/users/{id}")
        def get_user(id: int):
            return {"user_id": id}
        

3.3 Query Parameter

  • 차이 : Spring에서는 @RequestParam을 이용하여 함수 파라미터로 선언해야 했으나 FastAPI에서는 경로 변수와 함수 인자명이 같으면 자동으로 매칭이된다.

  • 코드

    • Spring
      • 1
        2
        3
        4
        
        @GetMapping("/users")
        public String getUsers(@RequestParam(required = false) String name) {
            return "name = " + name;
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        
        from typing import Optional
        from fastapi import FastAPI
        app = FastAPI()
        @app.get("/users")
        def get_users(name: Optional[str] = None):
            return {"name": name}
        

3.4 Request Body

  • 차이 : Spring@RequestBody를 이용하여 단순 객체 바인딩을 지원하지만 FastAPIPydantic모델을 사용하여 타입 검증 + 문서 생성 자동화를 지원해준다.

  • 코드

    • Spring
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        
        public class UserRequest {
            private String name;
            private int age;
        
            public String getName() { return name; }
            public int getAge() { return age; }
            public void setName(String name) { this.name = name; }
            public void setAge(int age) { this.age = age; }
        }
        
        @PostMapping("/users")
        public String createUser(@RequestBody UserRequest request) {
            return request.getName();
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        
        from pydantic import BaseModel
        from fastapi import FastAPI
        
        app = FastAPI()
        
        class UserRequest(BaseModel):
            name: str
            age: int
        
        @app.post("/users")
        def create_user(request: UserRequest):
            return {"name": request.name}
        

3.5 Validation

  • 차이 : Spring@Valid, Bean Validation을 이용하여 어노테이션 기반 검증, FastAPIPydantic을 이용하여 타입 + 필드 제약 기반 검증을 지원해준다.

  • 코드

    • Spring
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        
        public class UserRequest {
        
            @NotBlank
            private String name;
        
            @Min(1)
            private int age;
        
            public String getName() { return name; }
            public int getAge() { return age; }
            public void setName(String name) { this.name = name; }
            public void setAge(int age) { this.age = age; }
        }
        
        @PostMapping("/users")
        public String createUser(@Valid @RequestBody UserRequest request) {
            return "ok";
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        
        from pydantic import BaseModel, Field
        from fastapi import FastAPI
        
        app = FastAPI()
        
        class UserRequest(BaseModel):
            name: str = Field(..., min_length=1)
            age: int = Field(..., ge=1)
        
        @app.post("/users")
        def create_user(request: UserRequest):
            return {"result": "ok"}
        

3.6 Response 처리

  • 차이 : Spring 객체 반환 또는 ResponseEntity로 감싸서 상태코드 제어 반환, FastAPI dict, Pydantic Model, 객체 반환이 기본, 필요시 상태 코드 지정.

  • 코드

    • Spring
      • 1
        2
        3
        4
        5
        6
        7
        
        @GetMapping("/users/{id}")
        public ResponseEntity<UserResponse> getUser(@PathVariable Long id) {
            UserResponse response = new UserResponse(id, "angrypig");
            return ResponseEntity.ok(response, HttpStatus.CREATED);
        }
        
        public record UserResponse(Long id, String name) {}
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        
        from fastapi import FastAPI
        from pydantic import BaseModel
        app = FastAPI()
        class UserResponse(BaseModel):
            id: int
            name: str
        @app.get("/users/{id}", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
        def get_user(id: int):
            return UserResponse(id=id, name="angrypig")
        

3.7 의존성 주입 (DI)

  • 차이 : Spring 생성자 주입, 컨테이너 기반 DI, FastAPI 함수기반 DI

  • 코드

    • Spring
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        
        @RestController
        @RequestMapping("/users")
        public class UserController {
            private final UserService userService;
            public UserController(UserService userService) {
                this.userService = userService;
            }
            @GetMapping
            public String getUsers() {
                return userService.getUser();
            }
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        
        from fastapi import Depends, FastAPI
        
        app = FastAPI()
        
        class UserService:
            def get_user(self) -> str:
                return "user"
        
        def get_user_service() -> UserService:
            return UserService()
        
        @app.get("/users")
        def get_users(user_service: UserService = Depends(get_user_service)):
            return {"result": user_service.get_user()}
        

3.8 비동기 처리

  • 차이 : Spring 기본 동기 처리, 동기 처리시 WebFlux 학습 필요, FastAPI async def로 간단히 사용 가능.

  • 코드

    • Spring : 구성 코드는 같으나 spring-boot-starter-web이 아닌org.springframework.boot:spring-boot-starter-webflux의존을 가지고 있음.
      • 1
        2
        3
        4
        
        @GetMapping("/users")
        public String getUsers() {
            return "users";
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        
        from fastapi import FastAPI
        app = FastAPI()
        @app.get("/users")
        async def get_users():
            return {"result": "users"}
        

4. Spring과 FastAPI HTTP 처리 방식 비교

4.1 HttpRequest 접근

  • 차이 : Srping Servlet 객체 직접 사용, FastAPI Starlette Request(ASGI기반)사용

  • 코드

    • Spring
      • 1
        2
        3
        4
        5
        
        @GetMapping("/test")
        public String test(HttpServletRequest request) {
            String ip = request.getRemoteAddr();
            return ip;
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        
        from fastapi import FastAPI, Request
        app = FastAPI()
        @app.get("/test")
        def test(request: Request):
            ip = request.client.host
            return {"ip": ip}
        

4.2 HttpResponse 접근

  • 차이 : Spring ResponseEntity 많이 사용 직접적으로 HttpServletResponse 호출할일이 거의 없음(호출 케이스 : 파일 작업, Filter 작업)

  • 코드

    • Spring
      • 1
        2
        3
        4
        
        @GetMapping("/test")
        public ResponseEntity<String> test() {
            return ResponseEntity.ok("ok");
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        
        from fastapi import Response, FastAPI
        app = FastAPI()
        @app.get("/test")
        def test(response: Response):
            response.status_code = 200
            return {"result": "ok"}
        

4.3 Header 처리

  • 차이 : Spring 어노테이션 기반 처리(HttpRequest를 통해서도 가능), FastAPI 함수 파라미터 기반

  • 코드

    • Spring
      • 1
        2
        3
        4
        
        @GetMapping("/header")
        public String header(@RequestHeader("User-Agent") String userAgent) {
            return userAgent;
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        
        from fastapi import Header
        from typing import Optional
        @app.get("/header")
        def header(user_agent: Optional[str] = Header(None)):
            return {"ua": user_agent}
        

4.4 Cookie 처리

  • 차이 : Spring 어노테이션 기반 처리(HttpRequest를 통해서도 가능), FastAPI 함수 파라미터 기반

  • 코드

    • Spring
      • 1
        2
        3
        4
        5
        6
        
        @GetMapping("/cookie")
        public String cookie(
            @CookieValue(value="sessionId", required=false) String sessionId
        ) {
            return sessionId;
        }
        
    • FastAPI
      • 1
        2
        3
        4
        5
        6
        7
        8
        
        from fastapi import Cookie
        from typing import Optional
        
        @app.get("/cookie")
        def cookie(
            session_id: Optional[str] = Cookie(default=None, alias="sessionId")
        ):
            return {"session_id": session_id}
        

4.5 Responses

  • 차이 : Spring 서버 세션 기본 기원, FastAPI 기본 제공이 없어서 직접 구현하여 사용.

  • 코드

    • Spring
      • 1
        2
        3
        4
        5
        
        @GetMapping("/session")
        public String session(HttpSession session) {
            session.setAttribute("user", "angrypig");
            return (String) session.getAttribute("user");
        }
        
    • FastAPI
      • 기본 세션을 제공하지 않아 아래의 방법중 택해서 사용
        • Cookie + JWT
        • Redis Session
        • Middleware
        • Starlette Session

5. 느낀점

FastAPI를 학습하면서 느낀점은 아직 프레임워크 내부 구조까지 깊게 들어가 보지는 않았고,
API 서버를 구성하는 수준에서만 사용해 본 상태이다.

그래서 FastAPI 자체를 깊게 이해했다고 보기는 어렵지만,
기존에 Spring을 사용하면서 HTTP 요청 처리 방식이나
Controller, Request, Response 구조에 익숙해져 있어서
공식 문서를 보면서 학습하는 데에는 큰 어려움은 없었다.

오히려 FastAPI는 구조가 단순하고
기본 기능들이 자동으로 연결되는 부분이 많아서
Spring보다 훨씬 빠르게 API 서버를 만들 수 있다는 느낌을 받았다.

특히 타입 힌트 기반으로 요청을 받고,
자동으로 검증과 문서 생성까지 되는 부분은
개발 속도를 크게 높여주는 요소라고 생각했다.

그리고 FastAPI의 가장 큰 장점은
Python 생태계를 그대로 사용할 수 있다는 점이라고 느꼈다.

이번 프로젝트처럼

  • LLM 호출
  • AI Agent 구성
  • 외부 Python 라이브러리 사용

같은 작업을 해야 할 경우
Python 기반으로 구현하는 것이 훨씬 자연스럽고 편했다.

Java로도 구현이 가능하긴 하지만
결국 Python 코드를 따로 실행하거나
외부 프로세스를 호출해야 하는 경우가 많아서
개발 과정이 상당히 번거로워질 것 같다는 느낌을 받았다.

이런 점에서 FastAPI

  • AI 서버
  • LLM 서버
  • Agent 서버

같이 Python 라이브러리를 적극적으로 사용해야 하는 프로젝트에서
매우 적합한 프레임워크라고 생각했다.

아직 FastAPI를 깊게 사용해 본 것은 아니지만,
이번 프로젝트를 통해 기본적인 구조와 특징을 이해할 수 있었고
앞으로 AI 관련 프로젝트를 진행할 때 자주 사용하게 될 것 같다.


6. 참고

This post is licensed under CC BY 4.0 by the author.