FastAPI 서버를 만들기 위해 필요한 사전지식

조정훈·2024년 4월 12일

REST

자원(Resource) - URI
행위(Verb) - HTTP METHOD, 어떤 리소스에 접근을 어떻게 할지?
표현(Representations) - 파라미터, 리퀘스트 바디 같은것들이 포함되서 날아간다

이러한 REST 제약조건을 모두 충족한다면 해당 API는 RESTful 하다고 표현한다.
-> RESTful하게 만드는게 무조건적으로 좋은건 아님. 구현을 하다 보면 제약조건을 지키지 못하는 케이스도 생긴다(안 지키면 쉽게 풀 수 있는 그런문제들..) 너무 매몰되지는 말자.



URI & URL

  • URI : 리소스를 식별하는 문자열. URL보다 큰 개념
  • URL : 리소스의 위치를 나타내는 문자열



HTTP

HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는 프로토콜
웹에서 이루어지는 모든 데이터 교환의 기초, 클라이언트 - 서버 프로토콜
‘통신하는 방식의 약속’

HTTP header

HTTP 요청이나 응답을 보낼 때 부가적인 정보를 헤더에 담아 보낼 수 있다.
공통으로 포함되는 항목도 있고, 요청 / 응답에 따라 별도로 포함되는 항목이 존재한다.

-> 구글에 GET 요청을 보냈고, http로 통신하겠다. text/html~ 의 정보로 돌려주겠다. gzip같은걸로 압축해서 보내줄거고, 선호 언어는 한글-영어 순으로 해줘라~ 등등
이런 요청들을 해석해서 그 요청에 맞게끔 응답을 돌려준다.

HTTP Method

  • POST (Create)
    새로운것을 생성할 때

  • GET (Read)
    POST로 생성한 것을 가져올 때

  • PUT / PATCH (Update)
    POST로 생성한 것을 수정할 때 (전부/일부)

  • DELETE (Delete)
    POST로 생성한 것을 삭제할 때



Stateful / Stateless

  • Stateful
    Server side에 Client와 Server의 동작, 상태 정보를 저장하는 형태, 세션 상태에 기반하여 server의 응답이 달라진다.

    통신했던 서버랑 계속 통신해야 하므로 만약에 서버 증설시 그 요청을 다른곳으로 보내주는 별도의 라우팅을 해주는 별도의 서버가 필요하다. stateful로 짤 수 밖에 없는 환경도 있다. ex) 실시간 채팅방, 실시간 스트리밍 등 . 여기서 서버는 영상을 쏴주는 역할만 한다 이러한 경우가 아니면 대부분 stateless로 짠다. stateful은 scale in/out 시에 문제가 발생한다. 만약 사람이 몰려서 서버를 10대를 띄웠는데 사람이 슬슬 빠지는 상황이라 서버를 줄여도 된다. 그런데 내가 7번서버에 붙여졌으면 7번서버를 내리기 전에 나한테 보내주던 작업을 다른 서버로 이관을 하고 7번서버를 내려야한다.(scale in) 서버를 줄일 때 이렇게 복잡한 상황이 생긴다.

  • Stateless
    Client와 Server의 동작, 상태 정보를 저장하지 않는 형태, server의 응답이 client와의 세션 상태와 독립적이다.

    트래픽이 많이 들어올 경우 서버를 증설해야된다. 그런데 여기서 각 서버마다 동시에 썼던 정보를 들고 있게되면 한번 요청했던 서버랑만 통신을 해야한다. 그런데 stateless하면 어떤 서버에 가도 상관이 없다. 그래서 트래픽 분산에 좀 더 용이하다.



Json

경량의 Data 교환방식. 사람이 읽기 용이하고 기계가 분석하고 생성함에도 용이 key / value 형태의 쌍으로 구성 Rest API에서 Body로 사용하는 대표적인 데이터 형식



Status Code

HTTProtocol에서 서버는 받은 요청에 대해 응답을 보낼 때 상태 코드를 같이 보낸다.

  • 1xx(조건부 응답)
    요청을 받았으며 작업을 계속한다.

  • 2xx(성공)
    클라이언트가 요청한 동작을 수신하여 이해했고, 승낙했으며 성공적으로 처리했음을 가리킨다.

  • 3xx(리다이렉션 완료)
    클라이언트는 요청을 마치기 위해 추가 동작을 취해야 한다.

  • 4xx(요청 오류)
    클라이언트에 오류가 있음을 나타낸다.

  • 5xx(서버 오류)
    서버가 유효한 요청을 명백하게 수행하지 못했음을 나타낸다.

전부 외울 필요는 없다(하다보면 외워짐). 몇번대 오류가 뭘 의미하는지 정도만 알고 가자



IP & Port

  • IP (Internet Protocol)
    컴퓨터 네트워크에서 장치들이 서로를 인식하고 통신을 하기 위해서 사용하는 특수한 번호

  • IP version 4 주소 (IPv4)
    32개의 비트(0/1)로 표현되는 주소로 최대 232개의 주소를 표현
    보통 0~255 사이의 십진수 네개를 사용하고 ‘.’ 기호로 구분한다.
    일부 번호는 특별한 용도로 사용된다.
    127.0.0.1은 ‘localhost’로 자기 자신을 가리킨다.
    일반적으로 ip주소라고하면 이걸 말함

  • IP version 6 주소 (IPv6)
    IPv4 주소로 모든 단말에 주소를 부여하기 어려워짐에 따라 주소 길이를 128개의 비트로 표현하는 주소
    보통 두 자리 16진수 여덟 개를 쓰고 ‘:’ 기호로 구분한다.

  • Port
    IP로 하드웨어를 식별한다면, Port는 하드웨어 내에 있는 특정 프로세스를 식별하는 번호

  • Port의 세 종류
    0번 ~ 1023번: well-known port
    HTTP: 80번, SSH: 22번 등
    1024번 ~ 49151번: registered port
    우리가 마음대로 사용해도 되는 포트 번호 범위
    49152번 ~ 65535번: dynamic port
    동적으로 할당해도 되는 포트 번호 범위



Compute Bound & IO Bound

Compute Bound vs. IO Bound: 핵심 개념과 차이점 이해하기
컴퓨팅 분야에서 컴퓨터 바운드(Compute Bound)IO 바운드(IO Bound)는 프로세스의 성능을 결정하는 중요한 요소다. 두 가지 개념을 이해하면 시스템 성능 병목 현상을 파악하고 개선하는 데 도움이 된다.

작성한 코드가 계산 작업에 CPU를 많이 사용한다면, 이를 Compute Bound 혹은 CPU Bound 작업이라고 한다. CPU코어를 많이 쓸수록 빨라짐

  • 대표적으로 모델 학습 혹은 모델 예측 등이 있다.
  • CPU Core를 많이 사용할수록 빨라지는 작업들

작성한 코드에 Input/Output이 많이 발생하는 작업이 많다면 이를 I/O Bound 작업이라고 한다. I/O 작업(데이터 읽기/쓰기, 네트워크 통신 등)에 많은 시간을 소비하며, CPU 사용률은 비교적 낮다.

  • 파일 읽기 쓰기, 데이터베이스 데이터 읽기 쓰기, API 요청 등이 있다.
  • 동시에 많은 작업들을 요청하고 되돌려 받아야 빨라지는 작업들

CPU코어가 많이 쓸 필요가 없고 멀티스레드같이 별도의 쓰레드로 요청을 많이 던져놓고 기다리면 효율적인 작업



Multi Processing & Threading

Process vs Thread

프로세스는 하나의 프로그램 단위라고 이해하면 쉽다.
프로세스 = 사람, 쓰레드 = 작업대 라고 생각하자.
우리가 실행하는 파이썬은 하나의 Main Thread를 가진 Process로 실행된다.
상황에 따라 Multi Processing 또는 Multi Threading을 사용할 수 있다.
Thread는 일을 하는 단위로 이해하면 쉽다.

Multi-Processing vs Multi-Threading

파이썬의 경우 GIL이라는 제약조건으로 인해 하나의 파이썬 프로세스는 하나의 CPU Core를 사용할 수 있다.

  • GIL (Global Interpreter Lock)
    단일 스레드에서만 바이트코드를 실행할 수 있도록 하는 제약 조건. 이는 여러 CPU 코어를 사용할 수 있는 멀티코어 시스템에서도 파이썬 해석기가 한 번에 하나의 스레드만 실행할 수 있도록 제한하는 것을 의미.GIL 제약 조건은 파이썬의 장점 중 하나인 간결성과 안전성을 유지하기 위해 필요한 설계 결정이지만, 멀티코어 시스템에서 성능 저하를 초래할 수 있다는 단점도 가지고 있다.

    바이트코드
    특정 하드웨어가 아닌 가상 머신에서 실행되는 프로그램을 위한 이진 표현. 컴퓨터가 직접 실행할 수 있는 기계어와는 달리, 바이트코드는 가상 머신이 해석하여 실행합니다. 파이썬 바이트코드는 CPython 가상 머신에서 실행됩니다. CPython은 파이썬 프로그래밍 언어의 기본 구현입니다.

정확하게는 하나의 파이썬 Process는 한 시점에 하나의 Thread에서만 실행 될 수 있다.
따라서 파이썬에서 CPU Bound 작업을 진행하는 경우 Multi-Processing을 사용하는 방법이 있다. 다른 언어에서는 Multi Threading으로도 다중 코어를 사용할 수 있다. (물론 동기화 문제가 발생할 수 있다.)

파이썬에서 I/O Bound 작업을 진행하는 경우 비동기 프로그래밍 혹은 Multi-Threading을 사용하는 방법이 있다.
Multi-Threading의 경우 작업을 진행하는 단위가 여러 개이므로 I/O Bound 작업인 경우 각각의 Thread 들이 서로 응답이 오기까지 대기하면서 동시에 작업을 진행할 수 있다. I/O Bound 작업 요청을 보내놓고 기다리는거를 블로킹 당했다고 한다. 그래서 블로킹 당하지 않은 스레드로 가서 처리한다. 이걸 쓰레드 컨텍스트 스위칭이라 한다.

쓰레드 컨텍스트 스위칭
쓰레드 컨텍스트 스위칭은 멀티스레딩 환경에서 여러 쓰레드가 CPU를 효율적으로 활용하도록 제어하는 핵심적인 개념이다. 마치 운전대를 번갈아 잡고 자동차를 운전하는 것처럼, 여러 쓰레드가 순서대로 CPU를 사용하도록 전환하는 과정이라고 생각하면 된다.



Blocking vs Non-Blocking

blocking과 non-blocking의 차이는 제어권이 어디 있느냐에 있다.

  • Blocking
    제어권을 호출한 함수쪽에 빼앗기기 때문에 기존 함수는 호출한 함수가 끝날때까지 기다려랴 한다.

  • Non-Blocking
    그러나 Non-Blocking의 경우 여전히 제어권을 기존 함수가 가지고 있기 때문에 호출된 함수가 끝나지 않더라도 기존 함수에서 작업이 끝났는지를 계속 확인하거나 다른 작업을 진행할 수 있다.



동기 vs 비동기

동기와 비동기의 차이는 작업 완료 여부를 어디에서 확인하냐에 있다.

  • 동기
    호출한 함수에서 직접 작업 완료를 반환해준다.

  • 비동기
    호출 시 전달받은 Callback 함수를 통해 작업완료를 반환한다.(되돌아가라고 Callback 함수를 호출)

    -> I/O 작업은 일반적으로 비동기적입니다. 즉, I/O 작업을 요청하면 즉시 결과를 받지 못하고, 작업이 완료될 때까지 기다려야 합니다. 마치 운전자가 신호등이 노란색으로 바뀌면 다른 길로 우회전할지 결정하기 전에 신호가 녹색으로 바뀌기를 기다려야 하는 것과 같습니다. 비동기로 짜면 i/o작업 요청하고 바로 다른 작업을 할 수 있기 때문에 cpu를 사용률을 향상 시킬 수 있다.(효율적)
    멀티스레딩으로도 i/o bound작업을 할 수 있지만 스레드 개수보다 작업이 많다면 여전히 기다려야한다.

일반적으로 개념상 동기-blocking / 비동기-nonblocking 으로 짜는게 자연스럽다.

0개의 댓글