WeniVooks

검색

FastAPI 베이스캠프

FastAPI 소개

1. FastAPI에 대하여

FastAPI 공식 문서

FastAPI는 현대적이고 빠른(fast) Python 기반의 웹 API 프레임워크입니다. 높은 성능, 빠른 코드 작성, 그리고 쉬운 학습을 특징으로 합니다.

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints.

FastAPI는 표준 Python 타입 힌트를 기반으로 Python 3.7+ 버전에서 API를 구축하기 위한 현대적이고 빠른(고성능) 웹 프레임워크입니다. -FastAPI 공식 문서

공식 문서에서 볼 수 있듯이, FastAPI는 Python의 타입 힌트를 활용하여 빠르고 안전한 API 개발을 지원합니다. 얼마나 빠르고 안정적으로 개발이 되는지 몇 가지 위니브의 사례를 들어보도록 하겠습니다.

아래 서비스는 FastAPI를 사용하여 단 하루만에 만든 교육용 서비스를 소개하는 페이지입니다. 최대 1000명의 학생까지 이 서비스를 통해 간단한 CRUD를 30분간 수행할 수 있습니다. 단 하루만에 만들 수 있었던 이유는 이 서비스는 DB를 사용하지 않고 메모리만을 사용했기 때문입니다. 이처럼 간단한 크롤링, 데이터 처리, CRUD 등의 작업을 빠르게 만들 수 있으며 아키텍처가 단순하기에 안정적이게 만들 수 있습니다.

FastAPI로 만든 서비스 예시

또한 아래 서비스는 사내에 모든 서비스를 모니터링하는 서비스입니다. 이 서비스도 FastAPI로 만들어졌습니다. 제가 기본 골격을 잡을 때 일주일 정도가 걸렸고, 마무리는 회사 데이터 분석 엔지니어와 프론트엔드 개발자가 협업하여 완성한 서비스입니다. 여기서 제가 다른 프레임웤보다 편하다고 생각했던 것은, FastAPI는 아키텍처가 단순하기 때문에 주석만 잘 되어 있어도 인수인계가 빠르게 가능하다는 것이었습니다. 인수인계 과정에서 코드 설명조차 거의 필요 없었습니다. 그 전에 데이터 엔지니어가 전혀 FastAPI를 모르던 상황도 문제가 되지 않았습니다.

2. 용어 정리

FastAPI는 오픈소스 웹 프레임워크라고 했는데 오픈소스는 무엇이고, 웹 프레임워크는 무엇일까요? 이를 이해하기 위해 오픈소스, 프레임워크, 라이브러리, 서드파티에 대해 알아보겠습니다.

2.1 오픈소스

오픈소스란 "누구나 자유롭게 사용, 수정, 공유할 수 있는 소프트웨어"입니다. 코드를 누구나 확인할 수 있고, 무료로 사용할 수도 있습니다. 우리가 FastAPI를 비용을 내지 않고 사용하는 것처럼요. 또한 오픈소스 기여자로 참여하여 소프트웨어를 개선할 수도 있습니다. 이런 방식으로 오픈소스는 더 빠르게 발전하고, 더 안정적인 소프트웨어를 만들 수 있습니다.

2.2 프레임워크

프레임워크는 집을 지을 때의 기본 뼈대와 같습니다. 프레임워크는 이런 기본 틀, 전체적인 구조를 미리 제공해 줍니다. 개발자들은 이 틀 안에서 자신이 원하는 기능을 추가할 수 있습니다. 내 코드가 '주'가 되는 것이 아니라 '부품'이 되는 것이라 생각해주시면 됩니다.

이 방식은 큰 규모의 복잡한 프로그램을 만들 때 유용합니다. 프레임워크를 사용하면 프로젝트 구조, 데이터베이스 연결과 같은 기본적인 부분에 대해 고민할 필요 없이 중요한 기능 개발에 집중할 수 있기 때문입니다. 프레임워크의 예시로는 파이썬에서 사용하는 Django, fastAPI나 자바에서 사용하는 Spring이 대표적인 프레임워크입니다.

반면 아주 작은 프로그램을 만들 때는 프레임워크를 사용하지 않고 직접 만드는 것이 더 효율적일 수 있습니다. 프레임워크는 프로젝트의 규모와 복잡도에 따라 적절히 선택하는 것이 중요합니다. 예를 들어, 파이썬 진형에서 작은 규모의 프로젝트를 할 때에는 Django보다는 FastAPI를 사용하는 것이 더 효율적일 수 있습니다.

파이썬의 대표적 프레임워크의 관심도 추이는 아래와 같습니다. 검색 키워드를 기반한 것이라 점유율이 높은 순은 아닙니다. 또한 해당 관심도는 검색에 기반하고 있어 ChatGPT가 나온 이후 검색 키워드 자체가 줄어들었기 때문에 사용량 등이 반영된 것은 아닙니다. 이러한 관심도는 자료의 수와도 관련이 있습니다. 상대적으로 FastAPI는 Django나 Flask에 비해 자료의 수가 적습니다.

2.3 라이브러리

라이브러리는 도구 상자입니다. 프로그래밍에서 자주 사용되는 유용한 기능들을 모아놓은 것이죠. 라이브러리를 사용하면 개발자는 필요한 기능을 직접 만들지 않고도 쉽게 가져와 사용할 수 있습니다. 상자에서 도구를 꺼내는 것처럼 개발자는 원하는 기능을 라이브러리에서 골라 사용할 수 있습니다. 프레임워크와 다르게 여기서는 내 코드가 '주'이고 라이브러리가 '부품'이 됩니다.

파이썬의 requests 라이브러리는 인터넷에서 정보를 가져오는 복잡한 과정을 몇 줄의 코드로 쉽게 처리할 수 있게 해줍니다. 또한 Pandas 라이브러리는 대량의 데이터를 쉽게 다룰 수 있게 도와주어, 복잡한 데이터 분석 작업을 효율적으로 수행할 수 있게 합니다.

이렇게 라이브러리를 사용하면 개발자는 시간을 절약하고 더 효율적으로 프로그램을 만들 수 있습니다.

2.4 서드파티

서드파티는 프로그램을 만든 회사가 아닌 다른 회사나 개발자들이 만든 추가 도구입니다. 스마트폰에 다양한 앱을 설치하여 기존에 할 수 없었던 책을 읽는 기능, 운동을 기록하는 기능 등을 추가할 수 있듯이, 서드파티는 프로그램에 새로운 기능을 더해줍니다.

2.5 프레임워크 vs 라이브러리

많이 혼동되는 개념이 프레임워크와 라이브러리의 차이입니다. 둘 다 개발을 도와주는 도구이지만, 사용하는 방식과 목적이 다릅니다. 아래 표를 통해 둘의 차이를 살펴보겠습니다.

특성 프레임워크 라이브러리
제어의 주체 프레임워크가 전체 흐름을 제어하고 개발자의 코드를 호출 개발자가 흐름을 제어하고 필요할 때 라이브러리를 호출
유연성 정해진 구조와 규칙이 있어 유연성이 상대적으로 낮음 개발자가 원하는 대로 사용할 수 있어 유연성이 높음
학습 곡선 전체 구조와 철학을 이해해야 해서 초기 학습 곡선이 가파름 필요한 기능만 학습하면 되어 상대적으로 학습이 쉬움
개발 속도 초기 설정 후에는 빠른 개발이 가능 모든 것을 직접 구현해야 해서 처음부터 빠른 개발이 어려울 수 있음
2.6 API

API (Application Programming Interface)는 소프트웨어 간의 상호작용을 가능하게 하는 인터페이스입니다. 예를 들어 자동차의 페달도 API라고 볼 수 있습니다. 운전자가 자동차 엔진의 동작 원리를 모르더라도 페달을 밟으면 자동차가 움직이는 것처럼, API를 통해 서로 다른 소프트웨어가 데이터를 주고받거나 하드웨어를 제어하거나 서비스를 요청할 수 있습니다.

API는 애플리케이션이 서로 통신하고 데이터를 교환할 수 있도록 하는 일련의 규칙을 정의합니다. 예를 들어, 추상화 같은 것입니다. 추상화는 복잡한 내부 로직을 숨기고 간단한 인터페이스를 제공합니다. 이를 통해 개발자는 내부 구현을 알 필요 없이 기능을 사용할 수 있습니다. 또 다른 특징으로는 표준화, 보안 등이 있습니다.

API는 통신에서만 사용되는 것이 아닙니다. API라고 한다면 대부분 웹 API를 의미하긴 합니다만 다른 형태도 있다는 것을 기억해두시기 바랍니다. 웹 개발 맥락에서 '웹 API'는 주로 RESTful API 형태로 구현되며, HTTP 프로토콜을 사용하여 클라이언트와 서버 간의 통신을 가능하게 합니다. FastAPI는 이러한 웹 API를 빠르고 효율적으로 개발할 수 있도록 설계된 프레임워크입니다.

2.6.1 모놀리식

모놀리식 아키텍처는 전체 어플리케이션을 하나의 단일 시스템으로 구성합니다. 이 방식은 개발, 테스팅, 배포 등이 간단하고, 코드도 직관적으로 이해하기 쉽습니다. 하지만, 모놀리식 아키텍처는 시간이 지남에 따라 어플리케이션의 복잡성이 증가하고, 유지보수와 업데이트가 어려워질 수 있습니다.

예를 들어 에어비엔비처럼 숙박 서비스를 제공하는 앱을 모놀리식으로 구현하게 되었을 때, 리뷰를 제공하는 DB서버가 다운되어버리거나 배포에 문제가 생겨 일부 기능에 문제가 발생했을 경우, 사용자 정보를 처리하거나 결제를 하는 다른 모든 시스템에 영향을 미치게되어 전체 서비스가 마비되는 상황에 이를 수 있습니다.

FastAPI도 물론 모놀리식으로 구현할 수 있지만, 모놀리식으로 구현하도록 설계된 프레임워크는 아닙니다. 이 점이 초급자가 조금 어려워할 수 있는 부분입니다. 코드가 쉽다고 해서 서비스를 구현하기 쉬운 것은 아닙니다. 오히려 더 복잡해질 수 있습니다. 이러한 이유로 FastAPI를 목적에 맞게 사용하는 것이 초급자에겐 매우 중요합니다.

2.6.2 마이크로서비스

반면에, 마이크로서비스 아키텍처는 어플리케이션을 작고, 독립적인 서비스들로 분리합니다. 각 서비스는 자체적으로 개발되고, 배포되며, 다른 서비스와는 네트워크를 통해 통신합니다. 이 방식은 유지보수와 확장성이 용이하며, 개발 팀을 작게 분할하여 각각 독립적으로 작업할 수 있게 해줍니다.

덕분에 앞서 예를 든 숙박 서비스에서 마이크로서비스 패턴으로 개발이 되었다고 한다면 어떤 한 기능에 문제가 생겨도 그것은 일부 서비스의 문제일 뿐 다른 중요한 기능들에 영향을 미치지는 않습니다.

여기에 중간에 API라고 적혀 있는 것이 있습니다. 이것이 앞서 설명한 API 입니다. 만약 FastAPI를 통해 우리가 웹 서비스를 만든다면, 아래와 같은 구조가 될 것입니다.

  1. 가장 먼저 https://www.books.weniv.co.kr/와 같은 서비스에 접속하면
  2. Front-End Server에서 .html, .css, .js와 같은 파일을 USER에게 주게 됩니다.
  3. 이 파일 중 .js 파일에는 API 요청을 보내는 코드가 있습니다. 이 요청을 FastAPI 서버에 보내게 됩니다.
  4. FastAPI 서버는 요청을 받아서 DB에 저장된 데이터를 가져와서 USER에게 응답을 보냅니다.

위에 언급된 순서는 실제 운영되는 서비스와 유사합니다. 이러한 구조를 이해하고 있어야 FastAPI를 사용하는 것이 의미가 있습니다. 만약 이런 개념이 전혀 없이 서비스를 만들고 싶어 FastAPI를 배우겠다라고 한다면, FastAPI를 배우는 것이 아니라 Django를 권합니다.

2.6.3 구현할 서비스 경험하기

앞서 언급한 FastAPI로 만든 서비스 예시 서비스는 FastAPI를 통해 만들어져 있습니다. 이 서비스를 통해 우리가 어떤 것을 만들 수 있는지 확인해보세요. 이 서비스는 완성된 API를 제공합니다.

브라우저를 연 다음 URL 창에 about:blank를 입력하고 F12Ctrl+Shift+I를 눌러 개발자 도구를 열어주세요. 이후 Console 탭을 클릭하고 아래 코드를 입력해주세요. 여기서 734는 1부터 1000까지 임의의 숫자를 넣어주세요.

fetch("https://eduapi.weniv.co.kr/734/blog")
    .then((response) => response.json())
    .then((json) => console.log(json))
    .catch((error) => console.error(error));
fetch("https://eduapi.weniv.co.kr/734/blog")
    .then((response) => response.json())
    .then((json) => console.log(json))
    .catch((error) => console.error(error));

5개의 게시물이 들어온 것을 확인할 수 있습니다. 이를 통해 서비스를 구현하면 됩니다. 데이터 구조는 아래와 같습니다.

[
    {
        "_id": "16118968-7332-4d5d-B815-1741bc01d43c",
        "index": "1",
        "thumbnail": "asset/blogs/1.webp",
        "title": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt",
        "content": "Duis aute irure dolor in.",
        "email": "user-ww0qnop@Eu.com",
        "author": "licat",
        "views_count": "10527",
        "time": "19:54:55",
        "date": "2024-02-01"
    },
    {
        "_id": "829b151c-fa81-4b14-B389-32c77b18b21b",
        "index": "2",
        "thumbnail": "asset/blogs/2.webp",
        "title": "consectetur adipiscing elit, sed do eiusmod tempor incididunt",
        "content": "Duis aute irure dolor in.",
        "email": "user-tu8b2y7@sollicitudin.net",
        "author": "gary",
        "views_count": "39231",
        "time": "20:46:34",
        "date": "2024-04-29"
    }
]
[
    {
        "_id": "16118968-7332-4d5d-B815-1741bc01d43c",
        "index": "1",
        "thumbnail": "asset/blogs/1.webp",
        "title": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt",
        "content": "Duis aute irure dolor in.",
        "email": "user-ww0qnop@Eu.com",
        "author": "licat",
        "views_count": "10527",
        "time": "19:54:55",
        "date": "2024-02-01"
    },
    {
        "_id": "829b151c-fa81-4b14-B389-32c77b18b21b",
        "index": "2",
        "thumbnail": "asset/blogs/2.webp",
        "title": "consectetur adipiscing elit, sed do eiusmod tempor incididunt",
        "content": "Duis aute irure dolor in.",
        "email": "user-tu8b2y7@sollicitudin.net",
        "author": "gary",
        "views_count": "39231",
        "time": "20:46:34",
        "date": "2024-04-29"
    }
]

이제 이 데이터를 화면에 게시판 형태로 만들어보도록 하겠습니다. 앞서 진행했던 콘솔창에 아래 코드를 입력해보세요. 이러한 코드가 앞서 살펴봤던 4가지 순서에서 3번째에 해당합니다.

fetch("https://eduapi.weniv.co.kr/734/blog")
    .then((response) => response.json())
    .then((json) => {
        const body = document.querySelector("body");
        const blogList = document.createElement("div");
        json.forEach((blog) => {
            const blogItem = document.createElement("div");
            blogItem.innerHTML = `
                <img width='500px' src="https://eduapi.weniv.co.kr/${blog.thumbnail}" alt="${blog.title}" />
                <h2>${blog.title}</h2>
                <p>${blog.content}</p>
                <p>${blog.author} | ${blog.date} ${blog.time}</p>
            `;
            blogList.appendChild(blogItem);
        });
        body.appendChild(blogList);
    })
    .catch((error) => console.error(error));
fetch("https://eduapi.weniv.co.kr/734/blog")
    .then((response) => response.json())
    .then((json) => {
        const body = document.querySelector("body");
        const blogList = document.createElement("div");
        json.forEach((blog) => {
            const blogItem = document.createElement("div");
            blogItem.innerHTML = `
                <img width='500px' src="https://eduapi.weniv.co.kr/${blog.thumbnail}" alt="${blog.title}" />
                <h2>${blog.title}</h2>
                <p>${blog.content}</p>
                <p>${blog.author} | ${blog.date} ${blog.time}</p>
            `;
            blogList.appendChild(blogItem);
        });
        body.appendChild(blogList);
    })
    .catch((error) => console.error(error));

여기서 주고 받는 통신 즉, 앞서 출력했던 데이터를 사용자가 요청했을 때 데이터를 줄 수 있게 만드는 것이 이 수업에 목표입니다.

2.7 RESTful API

RESTful API는 개발자들 사이에서 정보를 주고받기 위한 표준화된 형식으로, 어떤 문법이 아닌 형식으로 언어에 구애받지 않고 사용되는 일종의 개발 철학이라고 생각할 수 있습니다. 권장하고 있는 설계 원칙은 마이크로소프트의 문서를 첨부합니다.

웹 API 디자인 모범 사례 - Azure Architecture Center

RESTful API는 Representational State Transfer Application programing interface 의 약자입니다. 한국말로 직역하면 '표현적인 상태로 전송하게 만드는 앱 프로그래밍 수단' 정도로 해석할 수 있겠습니다. 여기서 '표현적인 상태'란 API 의 형태만으로도 기능을 짐작할 수 있는 상태를 말하며, RESTful API의 핵심은 단순히 어떤 기능을 구동하기 위한 API요청이 아닌, API 요청 방식의 모습만으로도 어떤 기능을 수행할지 예상 가능하다는 점에 있습니다.

HTTP 구조로 예를 들어보도록 하겠습니다.

GET /books?year=2024 HTTP/1.1
Host: weniv.co.kr
GET /books?year=2024 HTTP/1.1
Host: weniv.co.kr

위의 예시는 2024년에 출시된 도서 목록을 조회하는 RESTful API 요청입니다. GET 메서드를 사용하여 /books 리소스에 접근하고, 쿼리 파라미터 year를 통해 2024년을 지정했습니다. 이러한 형식의 API 요청은 직관적이며, 요청의 의도를 명확하게 전달할 수 있습니다.

이렇게 URL로 원하는 자원을 명시하고 적절한 HTTP 메서드를 사용하여 해당 자원의 요청사항을 반환하는 URL 설계 철학을 RESTful API 라고 볼 수 있습니다.

예를 들어 아래와 같이 자원이 아닌 행위가 URL에 포함되는 것은 RESTful하다 얘기하지 않습니다.

// Bad
GET /books/delete/1 HTTP/1.1
Host: weniv.co.kr
 
// Good
DELETE /books/1 HTTP/1.1
Host: weniv.co.kr
// Bad
GET /books/delete/1 HTTP/1.1
Host: weniv.co.kr
 
// Good
DELETE /books/1 HTTP/1.1
Host: weniv.co.kr

백엔드 개발자가 이러한 API 설계와 구현, 문서화를 해놓으면 프론트엔드 개발자가 그 문서를 보고 개발하게 됩니다.

아래 예시는 교육용으로 만들어 놓은 API 명세입니다. 다만 실무에서도 이 RESTful API 작성 원칙을 모두 지키지 않기 때문에, 모든 규칙들이 다 지켜지면서 만든 API 명세는 아닙니다. 이렇게 협업한다는 사실만 참고해주세요.

위니브 샘플 API 명세

이러한 문서화가 매우 어렵기 때문에 문서 자동화 도구를 사용합니다. 대표적으로는 스웨거가 있습니다. FastAPI는 스웨거, 자동화 문서 도구를 지원합니다. 앞서 실습했었던 서비스에 스웨거 문서를 확인해보세요.

위니브 API FastAPI 스웨거 문서

FastAPI로 웹 API를 만들 때 이러한 RESTful API 설계 원칙을 지키면서 개발할 수 있습니다.

3. FastAPI의 주요 특징

공식 문서에 언급된 장점이 아니라 FastAPI를 사용하면서 느꼈던 핵심 장점을 소개해보겠습니다.

  1. 빠른 성능

    • FastAPI는 Starlette과 Pydantic을 기반으로 하여 매우 높은 성능을 제공합니다. Node.js나 Go와 비견될 만한 속도를 자랑합니다.
    • FastAPI는 파이썬 프레임웤 중에서도 빠른 속도를 자랑합니다. Flask와 벤치마크 비교해보더라도 3배 이상의 빠른 속도를 보여줍니다.
  2. 문서화

    • FastAPI는 자동으로 API 문서를 생성해주는 기능을 제공합니다. 이를 통해 API의 상세 목록과 테스트를 쉽게 진행할 수 있습니다. 별도의 문서화 도구를 설치하지 않고 기본으로 사용할 수 있습니다.
    • FastAPI는 JSON 형태의 API 문서를 자동으로 다운로드 받는 기능을 제공합니다.
  3. 쉽고 빠른 코드 작성

    • FastAPI는 아키텍처가 단순합니다. 따라서 ChatGPT나 Copilot등을 사용하면 거의 완성된 코드를 얻을 수 있습니다. 또한 Python의 타입 힌트를 사용해서 직관적인 코드로 API를 작성할 수 있습니다.
  4. DB 연동

    • FastAPI는 SQLAlchemy나 다른 ORM을 사용해서 데이터베이스와 연동이 가능합니다. Django처럼 완전 자동화 되어 있진 않지만, 연동할 수 있는 방법을 제공하여 편리합니다.

FastAPI는 이러한 특징들을 통해 빠르고 안정적인 API 개발을 가능하게 합니다. 작은 규모의 프로젝트부터 대규모 서비스까지 다양한 규모의 프로젝트에 사용할 수 있습니다. 많은 기업들이 이미 FastAPI를 채택하여 사용하고 있습니다.

1.1 강의와 대상 소개1.3 개발 환경설정