본문 바로가기
Back-end/Fastapi

#2. Fastapi로 모델 서빙부터 DevOps 까지 : Router 설정

by hsloth 2024. 4. 17.

 

본 포스팅은 AI 개발자 분에게 Fastapi을 이용해 간단한 모델을 서빙해보고, AWS에 올려 서버 배포 및 CI/CD 자동화까지 하는 것을 경험시켜주기 위해 제작되었습니다.

 

해당 포스팅부터 본 시리즈의 이름을 "Fastapi 배우기" -> "Fastapi로 모델 서빙부터 DevOps 까지"로 변경하였습니다. 

 

 

이전 시간에서는 간단하게 Fastapi의 서버 설정 방법에 대해서 배워보았다.

https://suloth.tistory.com/127

 

#1. Fastapi 배우기 : 초기 설정

본 포스팅은 SKT FLY AI Challenge를 하면서 모델 서버 구축을 위해 혼자서 Fastapi에 대해 공부하는 포스팅입니다. 틀린 부분이 있거나, 이상한 부분이 있다면 지적해주시면 감사하겠습니다. 일단 먼저

suloth.tistory.com

 

SKT FLY AI는 끝났지만... Fastapi공부를 천천히라도 조금씩 해보려고 한다.

모델 서빙하는 방법이나 devops를 주변 AI 개발자 분들에게 알려줄 겸... 적어보는 글로 취지가 바뀌었다...!

 

(이 글은 강좌 글이 아닌, 제 개인적인 경험을 적는 메모장같은 느낌의 포스트이기 때문에 반말로 작성하는 것을 이해해주시길 바랍니다...!)

 

 


Router


먼저, 라우터에 대해서 알아보자.

사전에는 "네트워크에서 데이터의 전달을 촉진하는 중계 장치"라고 정의되어 있다. 맞는 말이지만 어려울 수 있다.

간단하게 생각해보자.

Route는 길, 경로라는 뜻을 가진다.

그렇다면 Router는? 길, 경로를 만들어주는/이어주는 녀석이라고 생각할 수 있다.

여기서 말하는 길은 URL을 의미한다고 생각하면 편하다.

 

만약, 내가 /user라는 URL 경로를 연결하고 싶다면 어떻게 해야할까?

먼저, src폴더 아래에 routers 폴더를 만들어주고, index.pyuser.py 파일을 만들자.

 

user.py는 /user경로에 대한 함수(/user 경로로 요청이 들어오면 실행되는 함수)들을 모아놓은 파일이 될 것이고

index.py는 모든 Router를 모아놓은 파일이 될 것이다.

 

__pycache__ 폴더는 무시하자.

 

나는 /user 경로로 GET 요청이 들어오면 "유저입니다"를 사용자에게 보여주고 싶다.

그러기 위해서는 user.py를 다음과 같이 작성해주자.

# user.py
from fastapi import APIRouter

user_router = router = APIRouter()

@router.get("/")
async def getUser():
  return "유저입니다."

 

먼저, fastapi 라이브러리에서 APIRouter를 불러와주자.

APIRouter는 fastapi에서 "길을 만들어주는/이어주는 녀석" 이라고 생각하면 된다.

길을 이어주는 녀석을 불러와서 router라는 변수에 저장하고, @router.get("/")를 이용해 "/" 경로를 붙여준다고 보면 된다.

 

@router.get("/")

@가 들어가는 녀석들은 데코레이터라고 불린다.

데코레이터란, 이름답게 무언가 꾸며주는 함수이다.

여기서 @router.get("/")는 바로 아래에 있는 getUser() 함수를 꾸며준다.

GET 요청이 "/" 경로로 들어오면, getUser 함수를 실행시켜 주게끔 한다.

 

그리고 getUser함수가 실행되면 "유저입니다." 라는 문자열을 사용자에게 리턴하게 된다.

 

지금까지 작성한 코드만 보면 현재 상황은 이렇다.

두 길이 이어지지 않고 끊겨있다.

우리가 user.py에서 만든 길은 Fastapi 서버에 적용되지 않고 따로 놀고있다.

 

우리는 main.py를 실행시켜 Fastapi 서버를 연다.

그래서 길을 만들면, 해당 길을 붙여줘야한다.

 

길을 붙여주기 위해서는 다음 함수를 사용한다.

app.include_router(router, prefix=prefix)

혹은 router.include_router

 

그러면 이제 길을 붙여보도록 하자.

먼저 index.py 파일에 다음과 같이 코드를 작성하자.

# index.py
from fastapi import APIRouter
from src.routers.user import user_router

index_router = router = APIRouter()

router.include_router(user_router, prefix="/user")

여기서 주의할 점은 user_router를 import할 때, 절대경로를 사용하는데, from절에서 src파일부터 시작해야된다는 것이다.

상대경로를 사용하거나 src부터 시작하지 않으면 경로를 찾을 수 없다며 에러를 뱉는다.

 

위의 코드를 해석하자면,

나는 APIRouter를 불러와서 router 변수에 저장할건데,

APIRouter에 있는 router.include_router 함수를 사용해서 아까 만든 user.py파일에 있는 user_router를 불러와서 "/user" 경로로 이어 붙일 거야. 라는 뜻이다.

 

그림으로 보자면, 

index.py가 user라는 경로를 통해서 user.py에 있는 user_router를 붙여주었다(이어주었다).

따라서 이제 GET /user/ 라는 URL을 통해서 user.py의 getUser 함수를 실행시킬 수 있게 되었다.

하지만, 아직도 Fastapi Server와는 연결되지 않았다.

 

이제 Fastapi 서버와 index.py를 연결하기만 하면 된다. (index.py는 Router들을 모아놓는 파일이기 때문에 user.py와 main.py를 매개한다. 귀찮으면 main.py에서 바로 app.include_router 함수를 사용해서 user_router를 붙여줘도 된다.)

 

main.py로 가서 index_router를 연결해주자.

# main.py
from fastapi import FastAPI
from src.routers.index import index_router

app = FastAPI(docs_url="/docs", openapi_url="/open-api-docs")

# /api라는 경로로 index_router를 붙인다.
app.include_router(index_router, prefix="/api")

# / 라는 url로 GET 요청이 들어오면 getHello함수를 실행시키겠다.  
@app.get("/")
async def getHello():
  return "Hello, World"

 

여기서는 APIRouter를 불러오지 않고 app자체에 include_router함수를 사용한다.

app이라는 변수 = Fastapi 서버 라고 보면 되는데, 이 app에 router를 붙여줘야 서버에 연결되기 때문이다.

나는 /api 경로를 통해 index_router를 탈 수 있도록 해주었다.

 

최종 그림이다.

이제는 http://host:port/api/user/ 로 GET 요청이 들어온다면, user.py에 있는 getUser함수가 실행되면서 사용자에게 "유저입니다." 라는 문자열을 리턴할 것이다.

 

자, 이제 서버를 실행시켜보자.

먼저 터미널에서 가상환경을 실행시키고

서버를 실행시키자.

 

 

가상환경 실행시키는 방법이 생각나지 않는다면? 아래 포스팅의 1번을 봐보자.

서버를 실행시키는 방법이 생각나지 않는다면? 아래 포스팅의 6번을 봐보자.

https://suloth.tistory.com/127

 

#1. Fastapi 배우기 : 초기 설정

본 포스팅은 SKT FLY AI Challenge를 하면서 모델 서버 구축을 위해 혼자서 Fastapi에 대해 공부하는 포스팅입니다. 틀린 부분이 있거나, 이상한 부분이 있다면 지적해주시면 감사하겠습니다. 일단 먼저

suloth.tistory.com

 

서버를 성공적으로 열었다.

 

그리고 이제 브라우저 주소창에 "http://127.0.0.1:3000/api/user/" 를 작성해보자.

 

다음과 같은 화면이 뜨는 것을 볼 수 있다. (브라우저마다 다르다)

 

혹은 "http://127.0.0.1:3000/docs" 주소로 들어가면 스웨거가 나올텐데,

 

여기서 Try it out -> Execute를 누르면 Swagger에서 자동으로 요청을 보내주어 응답을 받게 된다.

 

 

Fastapi는 Swagger를 알아서 자동으로 만들어주기 때문에 생산성 측면에서 매우 좋다...!


과제


과제가 있다!!! (간단하다 ㅎ)

 

지금 우리가 만든 것은 /user 경로로 GET 요청이 들어오면 "Hello, World" 를 사용자에게 리턴하는 것을 만들었는데

이번에는 여러분들이 직접 /post 경로로 GET 요청이 들어오면 "Hello, Post"를 사용자에게 리턴하도록 만들어보자.

 

힌트를 주자면, routers에 post.py를 만들어서 길을 만들어주고, 그 안에 GET요청에 대한 함수를 만들어준 뒤

index.py에서 /post 경로로 post.py파일에 있는 router를 탈 수 있도록 이어주면 된다. ㅎㅎ

위에서 한 것과 크게 다르지 않으니 한 번 해보는 걸 추천한다.