실제 회사에서는 앱/웹 서비스의 서버가 존재하며 머신러닝 서비스를 위한 별도의 서버가 존재할 수 있다. 서비스 서버와 머신런이 서버가 분리되어 있다면 서비스 서버는 해당 서버가 가지고 있는 데이터를 머신러닝 서버에 예측 요청하며 통신을 하게 된다. 혹은 서비스 서버안에 머신러닝 파트가 있다면 그 안에서 프로세스를 실행함으로 예측을 수행할 수 있다.
모놀리식 아키텍쳐(Monolithic Architecture)는 하나의 큰 서버의 형태로 모든 범주들을 하나의 서버에서 처리되는 구조이다.
마이크로서비스 아키텍쳐(MSA, Mocroservice Arichitecture)는 주요 범주들을 개별 서버로 구성하고 서로 통신하는 구조이며 모놀리식 아키텍쳐는 배포과정에서 문제가 되었던 속도나 side effect면에서 이슈가 있었기 때문에 서버를 분리하는 MSA방식을 선호한다.
하나의 범주, 예를들어 레스토랑 서버도 주문 API, 결재 API 등 다양한 API가 존재할 수 있다.
REST API는 정보를 주고 받을 때 널리 사용되는 하나의 형식이다. 만약 개발할때 API를 임의로 만든다면 새로운 개발자는 해당 API가 무엇을 의미하는지 알기 어려울 수 있다. 따라서 REST한 형식을 따르면서 누구나 요청 모습 자체로 행위를 추론할 수 있도록 한다.
REST는 Representational State Transfer의 약자로 Resource, Method, Representation of Resource로 구성되어 있다. Resource는 Unique한 ID를 가지는 리소스를 의미하며 대표적으로 URI를 예로 들 수 있다.
기본적인 데이터 처리 작업에 사용되는 CRUD(Create, Read, Update, Delete)가 가능하며 GET, POST, PUT, PATCH, DELETE의 Method를 사용한다.
URL vs. URI
URL은 Uniform Resource Locator로 인터넷 상 자원의 위치를 뜻한다. URI는 Uniform Resource Identifier로 인터넷 상 자원을 식별하기 위한 문자열의 구성으로 URI는 URL을 포함하게 되며 URI가 더 포괄적인 범위이다.
GET : 정보를 요청하기 위해 사용 (Read)
POST : 정보를 입력하기 위해 사용 (Create)
PUT : 정보를 업데이트하기 위해 사용 (Update)
PATCH : 정보를 업데이트하기 위해 사용 (Update)
DELETE : 정보를 삭제하기 위해 사용 (Delete)
GET vs. POST
GET은 어떤 정보를 가져와서 조회하기 위해 사용되는 방식으로 URL에 변수(데이터)를 포함시켜 요청하는 구조이다. 데이터를 Header(헤더)에 포함하여 전송하며 URL에 데이터가 노출되어 보안에 취약하다. 또한 캐싱을 할 수 있기 때문에 비교적 빠른 속도로 조회할 수 있다.
POST는 데이터를 서버로 제출해 추가 또는 수정하기 위해 사용되는 방식으로 URL에 변수(데이터)를 노출하지 않고 요청한다. 데이터를 Body(바디)에 포함하여 전송하고 URL에 데이터가 노출되지 않아 기본 보안은 되어 있다.
GET : localhost:8080/login?id=lucas
POST : localhost:8080/login
HTTP 통신은 request하고 response를 받을 때 정보를 패킷(Packet)에 저장한다. 여기서 Packet의 구조는 Header와 Body로 구성되어 있다.
Header는 보내는 주소, 받는 주소, 시간 등의 정보가 포함되어 있고 Body에는 실제 전달하려는 내용이 포함되어 있다.
클라이언트 요청에 따라 서버가 어떻게 반응하는지를 알려주는 Code이다.
Status Code | 설명 |
---|---|
1xx(정보) | 요청을 받았고, 프로세스를 계속 진행함 |
2xx(성공) | 요청을 성공적으로 받았고 실행완료함 |
3xx(리다이렉션) | 요청을 완료를 위한 추가 작업(인증...)이 필요 |
4xx(클라이언트 오류) | 요청 문법이 잘못되었거나 요청을 처리할 수 없음 |
5xx(서버 오류) | 서버가 요청에 대해 실패함 |
디테일한 Code의 설명은 검색을 통해 자세히 알아볼 수 있다.
동기(Sync)는 서버에 요청을 보냈을 때 응답이 돌아와야 다음 동작을 수행하는 방식이며 비동기(Async)는 요청을 보낼 때 응답 상태와 관계 없이 다음 동작을 수행하는 방식이다.
IP(Internet Protocol)는 네트워크에 연결된 특정 PC의 주소를 나타내는 체계이다. 4덩이의 숫자로 구성된 IP 주소 체계를 IPv4라고 한다. 각 덩어리마다 0~255로 나타낼 수 있으며 IP 주소는 4byte로 표현되기 때문에 총 개의 IP주소를 표현할 수 있다. 현재 개인 PC 보급으로 IPv4로 할당할 수 있는 함계점에 진임하여 IPv6가 나온 상태이다.
대표적인 IP는 용도가 정해져 있는데 localhost, 127.0.0.1은 현재 사용 중인 local PC를 의미하고 0.0.0.0, 255.255.255.255는 로컬 네트워크에 접속된 모든 장치와 소통하는 주소를 의미한다.
IP주소 뒤에 나오는 일련의 숫자로 PC에 접속할 수 있는 통로(채널)이다. 사용중인 포트는 중복할 수 없으며 Jupyter Notebook의 경우 8888을 사용한다. Port는 0~65535까지 존재하며 0~1024는 통신을 위한 규약에 정해져 있으며 대표적으로 22는 SSh, 80은 HTTP, 443은 HTTPS와 통신하는 통로이다.
FastAPI의 가장 큰 특징은 High Performance이다. Node.js, go와 대등한 성능이라고 알려져 있다.
두번째로 사용하기 쉽다는 점이다. Flask는 쉬운 사용법 대신 속도를 내지 못했다면 FastAPI는 Flask와 비슷한 구조로 MSA에 적합한 사용이 가능하다.
마지막으로 높은 생산성인데 Swagger 자동 생성하고 Pydantic을 이용한 Serialization이 쉽다.
장점
아쉬운점
FastAPI와 uvicorn을 이용해서 간단한 웹서버 실습을 진행한다.
app을 생성하고 app에 /에 접근할 경우 read_root함수를 실행시키는 코드이다.
위의 코드를 저장하고 CLI환경에서 아래와 같은 명령어를 사용한다.
>>> uvicorn simple_webserver:app --reload
localhost:8000에 웹서버가 실행되고 있는것을 확인할 수 있다.
만약 터미널에서 uvicorn을 작성하기 싫다면 파일에 아래와 같이 추가할 수 있다.
>>> python3 simple_webserver.py
웹서버가 실행중일때 localhost:8000/docs
또는 localhost:8000/redoc
로 이동하면 Swagger를 확인할 수 있다.
Swagger를 단순히 문서로 받아들이고 넘어가지 말고 유용한 이유를 알아보자.
우리가 만든 API는 다양한 클라이언트에서 호출할 수 있는데 그때마다 어떤 형식으로 Request를 해야하는지에 대한 대답을 하기 번거롭고 협업이 힘들기 때문에 이 docs를 확인하여 원하는 API사용법을 빠르게 알 수 있는 장점이 있다.
또는 이 문서를 기준으로 RESTAPI 설계 및 문서화할 때 사용할 수 있으며 구축된 프로젝트를 유지보수하는 경우에도 활용할 수 있다.