최근에 FastAPI로 프로젝트를 진행하게 되었다. 개발은 항상 그렇듯이 환경구축하는게 가장 시간이 많이 드는 작업인 것 같다. 건축할 때 건물을 뚝딱 만들기 위해서는 재료, 환경, 동선 등을 고려하듯이 개발 환경구축도 동일한 작업인 것 같다.
환경 구축을 하면서 관련 키워드도 함께 정리했다. 용어를 최대한 직관적으로 이해할 수 있게끔 썼다. 왜냐하면 지금까지 글을 써본 결과, 컴퓨터와 마찬가지로 사람도 무상태성을 가지기 때문이다. 즉, 기억하지 않고 잊는다. 그러니까 어차피 잊어버릴 것, 보면서 바로 적용할 수 있게 적어놓자.
전체 과정
웹 개발 환경 구축은 순서는 다음과 같다.
✅ 목표
- 웹 개발 환경 구축
- 포어트리를 활용한 가상환경 구축
- 엔드포인트 하나를 가진 서버 구축
- API 문서 확인
- 데이터베이스 활용 준비
📌 용어 정리
📌 웹 프레임워크란?
- 웹 서비스를 하나 만드는 데에 많은 수의 코드가 필요하다. 하지만 하늘 아래에 새로운 것은 없듯이 웹 서비스를 만드는 데에 공통적으로 반복되는 부분들이 있다. 프레임워크는 웹서비스를 구현하는 데에 필요한 코드들을 미리 만들어 놓은 상태로 개발자에게 제공한다. 개발자는 웹 프레임워크를 통해 더 빠르고 쉽게 웹 서비스를 구현할 수 있다.
📌 의존성과 가상환경
- 웹 서비스가 집이라면, 집을 짓는 데 필요한 건축 자재(기술, 코드)가 바로 의존성이다. 집은 벽돌, 철근, 유리창이 없으면 완성될 수 없듯이, 프로젝트도 필요한 기술(의존성)이 없으면 동작할 수 없다.
- 웹 프레임워크는 웹 서비스를 만드는 데 필요한 도구들의 모음이다. 따라서 웹 서비스는 웹 프레임워크에 의존한다. 이처럼 프로젝트나 코드가 정상적으로 작동하려면 다른 기술(코드)에 의존해야 하는데, 이를 의존성(Dependency)이라고 한다.
📌 패키지와 가상환경
- 여기서 가상환경이 필요해진다! 가상환경(Virtual Environment)이란, 각 프로젝트마다 패키지를 분리하여 충돌이 나지 않도록 하는 독립된 실행 공간이다.
- 집을 짓는다면, 각 건설 현장(프로젝트)마다 필요한 건축 자재(패키지)를 따로 보관하는 창고(가상환경)가 있는 것과 같다. 이렇게 하면 A 현장에서 필요한 자재가 B 현장에 섞이지 않도록 관리할 수 있다.
- 의존성(건축 자재)은 패키지 형태로 제공되며, 각 패키지는 여러 버전이 존재한다. 문제는, 특정 기술은 특정 버전의 패키지를 요구할 수 있다는 점이다. 예를 들어, 어떤 웹 프레임워크는 Django 3.2를 필요로 하고, 다른 프로젝트는 Django 4.0을 써야 할 수도 있다.
📌 동기와 비동기
- 코드는 CPU가 실행하는 명령어들의 모음이다. 즉, 코드는 CPU의 작업들이다. CPU가 직접 실행해야하는 작업을 동기 작업, CPU가 다른 시스템의 처리를 기다려야하는 작업을 비동기 작업이라고 한다. 예를 들어 단순 계산, 데이터의 처리 등은 동기작업이지만 API 요청, 네트워크 연결, 데이터베이스 통신 등은 비동기 작업이다.파이썬은 기본적으로 동기실행이 원칙이나 await, async를 통해 비동기 작업을 처리할 수 있다.
📌 FastAPI와 ASGI
- FastAPI는 웹 프레임워크로서 비동기 작업을 지원한다. 하지만 FastAPI가 구동하기 위해서는 ASGI를 지정해야한다. ASGI는 비동기 서버로서 uvicorn과 hypercorn이 있다. FastAPI와 함께 ASGI 서버 중에 하나를 같이 의존성으로 설치해야한다. 가벼운 작업일 경우에는 uvicorn이, 무겁고 다양한 작업을 다룰 경우에는 hypercorn이 권장된다.
📌 스키마
- 스키마란 데이터베이스의 구조를 정의하는 설계도다. 어떤 데이터를 저장할 지, 테이블과 컬럼을 어떻게 구성할 지 정한다. 비유를 하자면 데이터베이스는 창고이고 스키마는 창고의 설계도다. 데이터베이스에는 책, 신발 등과 같은 물건들이 보관되는데 테이블은 창고의 물건분류이다. 컬럼은 각 물건의 특성을 나타내고 행은 실제 보관 된 물건들이다.
🧑🏻💻 가상환경 구축
poetry를 활용해서 가상환경을 구축한다. 아래의 설명은 MacOS 기준으로 진행된다.
✍️ 가상환경 설치
터미널을 켜고 pip를 활용하여 poetry를 설치한다.
pip install poetry
위치를 정한 후에 프로젝트 디렉토리를 생성한다. 이번 토이 프로젝트는 TIL 앱이므로 til로 디렉토리를 생성했다.
mkdir til
디렉토리로 이동한 후에 가상환경 설정을 한다.
$ cd til
$ poetry init
가상환경 설치 과정 중에 설정에 대해 여러 질문들을 한다. 모두 enter
를 통해 넘어간다. 그 결과 pyproject.toml
이 생성된다.
✍️ 가상환경 활성화
이제 가상환경을 활성화한다.
‼poetry shell
위의 명령어 실행 후에 가상환경이 설치 된 경로를 출력한다. 이제부터 패키지(의존성)을 설치할 때는 해당 경로 하위에서 설치된다.
✍️ 패키지 설치
pyproject.toml에는 프로젝트에 필요한 패키지 목록이 기재되어 있다. 프로젝트가 작동하기 위해서는 패키지들이 설치되어 있어야한다. 아래의 명령어를 통해 패키지들을 설치한다.
poetry install
✍️ 패키지 추가
FastAPI 패키지를 추가해보자.
poetry add fastapi
fastapi를 구동하기 위해서는 ASGI 서버가 필요하다. 우리 프로젝트에서는 유비콘을 사용한다.
poetry add "uvicorn[standard]"
🧑🏻💻 API 만들기
루트 디렉토리에 main.py를 생성한다.
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def hello():
return {"Hello": "FastAPI"}
🧑🏻💻 프로젝트 실행하기
uvicorn으로 서버를 구동한다. 이때 반드시 가상환경이 실행된 상태여야한다.
uvicorn main:app --reload
로컬 브라우저 htttp://localhost:8000
를 통해 실행여부를 확인할 수 있다.
🧑🏻💻 프로젝트 문서 확인
http://localhost:8000/docs
를 통해 API 명세를 확인할 수 있다.
🧑🏻💻 데이터베이스 설정
코드 수준에서 의존성 충돌을 방지 하기 위해 초반에 가상환경 설정을 했다. 하지만 코드 수준뿐만 아니라 아키텍처 수준에서도 의존성을 관리해야한다. 예를 들어 서버는 데이터베이스와 통신을 해야하는데 데이터베이스도 버전 관리를 해야한다. 이런 환경들을 일관되게 유지하기 위해 도커를 사용한다.
MySQL을 도커를 통해 실행한다.
docker run --name mysql-local -p 3306:3306/tcp -e MYSQL_ROOT_PASSWORD=test -d mysql:8
컨테이너가 실행되는 지 확인한다.
docker ps
생성한 컨테이너에 접속한다. MySQL 컨테이너이므로 컨테이너 설정 때 지정했던 암호(MYSQL_ROOT_PASSWORD=test
)를 사용한다.
docker exec -it mysql-local mysql -u root -p
MySQL에 접속 후에 스키마를 생성한다. 스키마 이름은 홑따옴표가 아니라 백틱(```)으로 둘러싸여 있다.
CREATE SCHEMA `til`;
스키마가 생성된 것을 확인한다.
SHOW DATABASES;