본문 바로가기
Web 개발/FAST API (인프런 강의 내용)

1 실습1 GET API 전체조회

by yororing 2024. 4. 5.

00 프로젝트 소개환경 구축 - ToDo 서비스

1. ToDo (Version 1) 서비스 만들기

1) ToDo 서비스의 기능

  • 할 일을 적고 수행 여부 체크

2) ToDo API

  • 생성할 API 5가지: 1) 전체 ToDo 조회, 2) 단일 ToDo 조회, 3) ToDo 생성, 4) ToDo 수정, 5) ToDo 삭제 
Method 기능 url
GET 전체 ToDo 조회 /api/v1/todos
단일 ToDo 조회 /api/v1/todos/<id>
POST ToDo 생성 /api/v1/todos
PATCH ToDo 수정 /api/v1/todos/<id>
DELETE ToDo 삭제 /api/v1/todos/<id>

 

2. 환경 구축

1) projects라는 폴더를 원하는 경로에 생성

mkdir <원하는 경로>/projects

2) 파이썬 가상환경 생성 후 해당 폴더로 이동

# todos라는 가상환경 폴더 생성
$ python3.10 -m venv todos # 강사님
$ python -m venv todos	# 나

# todos로 이동
$ cd todos

# 목록 확인
$ ls
Include/	Lib/	pyvenv.cfg	Scripts/

3) 가상환경 활성화/설정

$ source bin/activate	# 강사님
$ source Scripts/activate	# 나

# 잘 작동하는지 확인
(todos)$ python --version
Python 3.12.1

 

01 전체 ToDo 조회하기 (GET Method 사용)

  • 목표: GET Method를 이용해 전체 ToDo 내용 조회하기

1. todos 폴더 > src 폴더 > main.py 파일 생성

  • 여기서 src는 source의 약자
(todos)$ pwd	# 현재 디렉토리 확인
/c/Users/관리자/Desktop/projects/todos

(todos)$ python --version	# 잘 작동하는지 확인
Python 3.12.1

(todos)$ mkdir src	# src 폴더 생성
(todos)$ cd src	# src 폴더로 이동
(todos)$$ touch main.py	# main.py라는 파이썬 빈 파일 생성

1) PyCharm 사용 시

  • src 폴더 우클릭 > Mark Directory as > Source Root
    • Python 파일들을 import하는 경로에서 이 src 디렉토리를 root path로 잡도록 설정하는 것

2. 필요한 library 설치: fastapi, uvicorn

(todos)$ pip install fastapi
(todos)$ pip install uvicorn
  • uvicorn: fastapi를 동작시키기 위한 라이브러리
  • 일반적으로 fastapi와 uvicorn 같이 사용됨

3. main.py에 쓰기

# todos > src > main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")				# @app.get에 root path를 매핑
def health_check_handler():		# health_check_handler라는 함수 생성
	return {"ping": "pong"}		# 핑퐁 반환

1) FastAPI import 및 app 객체에 FastAPI() instantiate

  • from fastapi import FastAPI: fastapi 라이브러리에서 FastAPI import
  • app = FastAPI(): app이라는 이름으로 FastAPI을 instantiate
    • instantiate (v.): 생성된 오브젝트의 인스턴스를 반환하도록 함

2) root path에 GET 요청을 보내는 API 생성

  • app이라는 객체에 API를 연결하여 서버를 띄우면 서버로 어떤 HTTP 요청 보내기 가능
  • @app.get("/"): @app.get에 root path를 매핑
  • def health_check_handler(): : health_check_handler라는 함수 생성
  • return {"ping": "pong"}: 핑퐁 반환
  • 작동 방식:
    • @ 뒤에 있는 app (앞서 app=FastAPI() 선언하여 가능)이라는 FastAPI 서버에 root path로 개인 요청을 보내게 되면 아래에 있는 health_check_handler() 함수가 실행되어서 해당 API 요청을 처리할 것
    • health_check_handler() API는 핑퐁을 반환해주는 기능을 지님

4. FastAPI 웹 서버 띄워서 기능 확인하기

(todos)$ cd /c/Users/관리자/Desktop/projects/todos/src
(todos)$ uvicorn main:app
INFO:     Started server process [18956]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
  • $ cd /c/Users/관리자/Desktop/projects/todos/src: 기능을 확인하기 위해 src 경로를 기준으로 작업을 진행할 것이기에 src로 이동
  • $ uvicorn main:app: uvicorn 사용하여 main에 app을 매핑 즉, main.py에 있는 app 객체를 이용하겠다는 의미
    • (후에 추가)
      • uvicorn main:app --reload
      • --reload 옵션을 주면 파일을 수정하고 저장하면 저절로 업데이트가 되서 uvicorn을 껐다 키지 않아도 됨. 그래서 앞으로는 --reload 옵션을 줄 것임!
    • 위에까지만 써도 괜찮음
    • 뒤에 port 추가 가능하나 우리는 기본 8000 port를 사용하도록 하겠음 (강사님 )
    • 실행 시 로그 메시지 출력됨
      • 로그 내용: local host(127.0.0.1)에 8000번 port로 앱이 뜸
    • http://127.0.0.1:8000을 ctrl + 마우스 좌클릭 또는 브라우저에 입력 시 {"ping": "pong"}이 출력 되는 것 확인 가능
    • http://127.0.0.1:8000/docs라는 path로 이동 시
    • FastAPI가 자동으로 swagger 문서를 생성해 놓은 것 확인 가능 
    • Health Check Handler가 매핑돼있다는 정보 확인 가능

5.FastAPI 웹 서버 종료하기

  • 웹 서버 실행 후 코드 변경 시 변경사항을 SwaggerUI에 반영하기 위해선 웹 서버 재시작 (uvicorn 종료 후 다시 실행) 필수
  • 종료 방법: Ctrl + C

6.전체 ToDo 조회하는 API 생성하기

1) 데이터를 담을 딕셔너리 생성

  • 현재 데이터베이스와 연동되어있지 않기에 메모리상에서 딕셔너리 생성하여 거기서 데이터 관리하도록 할 것
  • main.py에 아래를 추가
# todos > src > main.py
...

todo_data = {
	1: {
    	"id": 1,
        "contents": "실전! FastAPI 섹션 0 수강",
        "is_done": True,
    },
    2: {
    	"id": 2,
        "contents": "실전! FastAPI 섹션 1 수강",
        "is_done": False,
    },
    3: {
    	"id": 3,
        "contents": "실전! FastAPI 섹션 2 수강",
        "is_done": False,
    },
}
  • todo_data라는 딕셔너리 생성
  • key와 value를 갖게 될 것
    • key → 개별 todo를 식별할 수 있는 식별자로 int 값 정해주기 (위에선 1, 2, 3)
      • 각 key 당 딕셔너리의 value를 갖게 될 것
    • value → 하나의 todo를 모델링 해주기
      • "id"라는 컬럼에 앞에 key와 동일한 int 타입의 값 설정해주기
      • "contents"라는 컬럼에 하나의 todo가 갖는 str 타입의 실제 내용 설정해주기
      • "is_done"라는 컬럼에 todo의 완료 여부를 확인하는 bool 타입의 값 설정해주기
  • 위 예시에선 3개의 item들을 갖는 ToDo 데이터 생성

2) API 요청에 데이터 반환하도록 설정

  • main.py에 아래를 추가
# todos > src > main.py
...

@app.get("/todos")				# @app.get("/path")
def get_todos_handler():			# def 핸들러명():
	return list(todo_data.values())		# return 반환값
  • ToDo API를 추가하기 위해선 앞에서 한 것과 같이 해야 됨
  • @app.get("/todos"): app의 GET method에 path (i.e., "/todos") 매핑해주기
    • 일반적으로 REST API에서는 자원(resource)를 복수형으로 적기에 ToDos라는 이름의 path를 지정할 것
  • def get_todos_handler():: todos API를 핸들링하는 핸들러의 역할을 하는 함수 생성
  • returb list(todo_data.values()): todo_data의 각 key의 value들의 값들을 추출해서 list에 담긴 것을 반환

7. 변경된 SwaggerUI 및 화면 확인

  • 코드 변경 후 SwaggerUI에 변경사항 반영하기 위해선 uvicorn 종료 및 재시작 필수
  • terminal에서 ctrl + C 입력하여 종료 후 아래를 입력
(todos)$ uvicorn main:app
INFO:     Started server process [13812]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

 

1) API 확인

  • http://127.0.0.1:8000을 ctrl + 마우스 좌클릭 또는 브라우저에 입력 시 {"ping": "pong"}이 출력 되는 것 확인
  • http://127.0.0.1:8000/todos을 브라우저에 입력 시
  •  

2) Swagger 문서 확인

  • http://127.0.0.1:8000/docs을 브라우저에 입력 시
  •  
  • SwaggerUI 반영된 것 확인 가능
  • ToDos  API가 추가된 것 확인 가능 
    • 안보일 경우 새로고침 해보기
     
  • /todos의 drop down 버튼 클릭 시
  • 200번대의 response가 응답된다는 것을 API 문서에서 확인 가능 
  • 현재는 따로 설정한 값들이 없기에 단순한 형태로만 보임

3) ToDos API 호출

  • Try it out 버튼 클릭 > Execute 클릭 시 
  •  
  • 사진 1
  • 위 사진 (사진 1) 설명: localhost 8000번에 todos라는 path로 get 요청이 감
  • 사진 2
  • 위 사진 (사진 2)설명: 200번대의 response가 위와 같은식으로 응답 됨
  • 작업한 api가 잘 동작됨을 확인 가능 

8. query parameter

1) 필수 값으로 설정

  • query parameter: get 요청 뒤 path의 가장 끝부분에 ? 형태로 작성 가능
  • 예시: "/todos?order=DESC"에서 하이라이트 된 부분
    • order 값을 통하여 조회수에 추가적인 어떤 정렬 (DESC - descending으로 내림차순 정렬)을 할 수 있음
    • order=DESC 대신 query=apple 같은 것으로 apple이 들어간 item만 찾는 것 등을 할 수 있음
  • FastAPI에서는 query parameter를 인자로 전달하여 이용함
# todos > src > main.py
...
@app.get("/todos")
def get_todos_handler(order: str):
	rt = list(todo_data.values())
    if order == "DESC":
    	return rt[::-1]
    return rt
  • order라는 str 값을 인자로 전달하여 query parameter로 이용하기
  • order가 DESC라면 rt를 역정렬해서 반환
  • 아닐 시 그냥 rt(todo_data의 value값들의 리스트 형태)를 오름차순으로 반환

2) API 확인

  • uvicorn 재시작: ctrl + C 후 uvicorn main:app을 터미널에 입력
  • 브라우저에 http://127.0.0.1:8000/todos?order=DESC 입력 시
  • 변경된 api 잘 작동하는 것 (order=DESC라는 쿼리 파라미터를 todos path 뒤에 ? 후 적어줬을 때 역정렬된 todo_data 값들이 출력되는 것) 확인 가능

3) Swagger 문서 확인

    • 브라우저에 http://127.0.0.1:8000/docs 입력 시

    • 이 중,

  • query parameter에 order가 추가된 것 확인 가능
  • Try it out 클릭 > (order에 값 안 넣고) Execute 클릭 시
  • 앞서 main.py에서 order을 필수값으로 넣었기에 에러가 남
  • order 값에 ASC 값을 입력 후 Execute 클릭 시
  • 정상적으로 오름차순 정렬이 되어 반환되는 것 확인 가능
  • order 값에 DESC 값 입력 후 Execute 클릭 시
  • 정상적으로 내림차순 정렬이 되어 반환되는 것 확인 가능

4) optional 값으로 설정

# todos > src > main.py
...
@app.get("/todos")
def get_todos_handler(order: str | None = None):
	rt = list(todo_data.values())
    if order and order == "DESC":
    	return rt[::-1]
    return rt

 

  • def get_todos_handler(order: str | None = None): order 값을 str 값 또는(or) None을 받을 수 있도록 하고, = None을 통하여 기본값 (default값)을 None이라고 설정
  • if order and order == "DESC":: order 값이 있고 order 값이 DESC인 경우 다음을 실행

5) API 확인

  • uvicorn 재시작: ctrl + C 후 uvicorn main:app을 터미널에 입력

6) Swagger 문서 확인

  • 브라우저에 http://127.0.0.1:8000/docs 입력 후 /todos path에서
    • Try it out 클릭 > (order 값에 아무것도 안 넣고) Execute 클릭 시
    •  
    • 오름차순 정렬로 잘 출력되는 것 확인

 

 

이때까지의 코드들:

# .../todos/src/main.py 내용

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def health_check_handler():
    return {"ping": "pong"}

todo_data = {
    1: {
        "id": 1,
        "content": "실전! FastAPI 섹션 0 수강",
        "is_done": True,
    },
    2: {
        "id": 2,
        "content": "실전! FastAPI 섹션 1 수강",
        "is_done": False,
    },
    3: {
        "id": 3,
        "content": "실전! FastAPI 섹션 2 수강",
        "is_done": False,
    },
}

@app.get("/todos")
def get_todos_handler(order: str | None = None):
    rt = list(todo_data.values())
    if order and order == "DESC":
       return rt[::-1]
    return rt

'Web 개발 > FAST API (인프런 강의 내용)' 카테고리의 다른 글

1 실습4 PATCH API todo 수정  (0) 2024.04.16
1 실습3 POST API todo 생성  (0) 2024.04.15
1 실습2 GET API 단일조회  (0) 2024.04.09
1 FastAPI 알아보기  (0) 2024.03.26
0 오리엔테이션  (0) 2024.03.26