Serving 패턴
디자인 패턴
- 과거부터 문제를 해결한 사람들이 반복된 내용을 패턴으로 정리
- 코드의 재사용성, 가독성, 확장성 등을 향상시키기 위한 목적으로 도입
- 주로 객체 지향 프로그래밍에서 사용되지만 다른 프로그래밍 패러다임에서도 유용
- 개발 과정의 커뮤니케이션에서 이런 패턴을 사용하기도 함
- 예시) 이번 서빙은 Batch 패턴으로 구현하시죠!
- 안티 패턴 : 보통 좋지 않다고 알려진 패턴
머신러닝 디자인 패턴
- 머신러닝의 특수성으로 별도의 디자인 패턴이 생김
- 일반적인 소프트웨어 개발: Only Code
- 머신러닝 개발의 특수성 : Data, Model, Code
머신러닝 서비스를 개발하다 고민하는 특수한 포인트
- 대용량 Model Load
- Model 관리
- 데이터를 대량으로 가져와서 전처리
- 데이터를 통계적으로 확인해서 이상치 제외
- 예측 요청 후 반응 시간이 오래 소요될 수 있음(모델이 연산하는 과정 이슈)
- 학습, 예측, 운영하면서 생기는 노하우 => 패턴화
- 지금도 계속 변하고 있을 머신러닝 디자인 패턴 (LLM 이후에도 LLMOps 분야에서 계속 새로운 시도가 생기고 있을 것)
- 상황에 따라 다르기에 이런 방법들이 항상 Best는 아니지만 구현하기 전에 참고할 수 있음
- 소개하는 여러 패턴을 합쳐서 하나의 패턴으로 만들 수도 있음
Serving 4가지 패턴
- Batch Serving
- Batch 패턴
- Online Serving
- Web Single 패턴
- Synchronous 패턴
- Asynchronous 패턴
Batch Serving
Batch 패턴
- 추천 모델이 있을 때, 가장 간단하고 최저의 비용으로 운영 환경에 배포하기 위해서는 어떻게 해야 할까?
- 주기적으로 이 추천 모델에 사용자 데이터를 Input Data로 넣어서 예측하고, Output 으로 나오는 사용자 별 추천 결과를 DB에 저장하기
- 추천 결과를 활용하는 서버쪽에서는 이 DB에 주기적으로 접근해 추천 결과를 노출
실시간성이 필요 없는 경우에 주기적으로 예측 결과를 DB에 저장하고, 활용하는 쪽은 DB에서 결과를 읽어와서 사용
Job Management Server
- 작업을 실행하는 서버
- Apache Airflow 등을 주로 사용
- 특정 시간에 주기적으로 Batch Job을 실행시키는 주체
Job
- 어떤 작업 실행에 필요한 모든 활동
- Job이 실행되는 과정에 Model Load, Data Load도 포함
- Python Script를 그냥 실행시키는 경우도 있고, Docker Image로 실행하는 경우도 존재
Data
- 서비스에서 사용하는 DB(AWS RDS 등) 또는 데이터 웨어하우스에 저장
- 서비스 서버에서도 데이터를 불러오는 스케줄링 Job이 존재 => 특정 시간 단위로 가져옴
Usecase
- 예측 결과를 실시간으로 얻을 필요가 없는 경우
- 대량의 데이터에 대한 예측을 하는 경우
- 예측 실행이 시간대별, 월별, 일별로 스케줄링해도 괜찮은 경우
장점
- 기존에 사용하던 코드를 재사용 가능
- API 서버를 개발하지 않아도 되는 단순함
- 서버 리소스를 유연하게 관리할 수 있음(오래 걸릴 Job에 서버 리소스 추가 투입)
고민할 점
- 별도의 스케줄러(예 : Apache Airflow) 필요
Online Serving
Web Single 패턴
Web : 웹 기반 애플리케이션 Single : 단일, 하나의 요청을 처리
- 배치 단위로 서빙을 하면 결국 결과 반영까지의 시간 텀이 존재하기 때문에, 이를 더 실시간에 가깝게 하려면 어떻게 해야 할까?
- 모델이 항상 Load 된 상태에서 예측을 해주는 API 서버를 만들고, 추천 결과가 필요한 경우 서비스 서버에서 이 예측 서버에 직접 요청하면 어떨까?
API 서버 코드에 모델을 포함시킨 뒤 배포, 예측이 필요한 곳(클라이언트, 서버 등)에서 직접 Request 요청
예측/추론 Server
- FastAPI, Flask 등으로 단일 REST API 서버를 개발 후 배포
- 예 : POST api-server-url/predict로 예측
- API 서버가 실행될 때 모델을 로드
- API 로직 내에 전처리도 같이 포함
Client
- 앱에서 직접 요청할 수도 있고, 앱이 서비스 서버에 요청하고 서비스 서버가 예측 서버에게 또 요청할 수도 있음(개발을 어떻게 했는지에 따라 다름)
- 웹페이지라면 브라우저에서 요청
Data
- 요청할 때 같이 데이터를 담아 요청
- 상황에 따라 데이터의 용량 제한이 있을 수 있음
Load Balancer
- 트래픽을 분산시켜서 서버에 과부하를 걸리지 않도록 해줌
- Nginx, Amazon ELB(Elastic Load Balancing) 등을 사용
Usecase
- 예측 서버를 빠르게 출시하고 싶은 경우
- 예측 결과를 실시간으로 얻을 필요가 있는 경우
- Web Single 패턴을 기본으로 삼고 이어지는 패턴들을 적용
장점
- 보통 하나의 프로그래밍 언어로 진행
- 아키텍처의 단순함
- 처음 사용할 때 좋은 방식
고민할 점
- 구성 요소 하나(모델, 전처리 코드 등)가 바뀌면 전체 업데이트가 필요
- 모델이 큰 경우, 로드에 시간이 오래 걸릴 수 있음
- 요청 처리가 오래 걸리는 경우, 서버에 부하가 걸릴 수 있음
Synchronous 패턴
Synchronous : 동기식
하나의 작업이 끝날 때까지 다른 작업을 시작하지 않고 기다리고, 작업이 끝나면 새로운 작업을 시작하는 방식
- FastAPI로 모델을 Web Single 패턴으로 구현했다고 했을 때, 클라이언트는 API 서버로 요청을 한 뒤 이 요청이 끝날 때까지 기다려야 함
- Web Single 패턴을 동기적(Synchronous)으로 서빙
- 기본적으로 대부분의 REST API 서버는 동기적으로 서빙
장점
- 아키텍처의 단순함
- 예측이 완료될 때까지 프로세스가 다른 작업을 할 필요가 없어서 Workflow가 단순해짐
고민할 점
- 예측 속도가 병목이 됨 (동시에 1000개의 요청이 올 경우 대기 시간이 길어지거나 Drop 혹은 Timeout)
- 예측 지연으로 사용자 경험이 악화될 수 있음
Usecase
- 예측의 결과에 따라 클라이언트의 로직이 즉각적으로 달라져야 하는 경우
- 예시) 예측 결과가 강아지냐, 고양이냐에 따라 클라이언트에서 보여주어야 하는 페이지가 다른 경우 Predict Output => 강아지 => 강아지 관련 Page => 고양이 => 고양이 관련 Page
Asynchronous 패턴
Asynchronous : 비동기식
- 하나의 작업을 시작하고, 결과를 기다리는 동안 다른 작업을 할 수 있음
- 작업이 완료되면 시스템에서 결과를 알려줌
- 음식점에서 진동벨을 사용하는 경우가 비동기식과 유사
등장 배경
- Synchronous 패턴으로 서빙하니까, API 서버에서 이제 수많은 요청을 감당할 수가 없어짐
- API 서버가 계속 부하가 걸려서 모든 요청에 대한 응답이 느려지기 시작
- 응답이 느려지니, 클라이언트에서도 응답 받은 이후의 로직을 진행하지 못함
- API 서버의 cpu와 memory를 증가하면 해소가 되긴 하겠지만, 단기간의 해결이고 요청이 늘어나며 결국 똑같아짐
어떻게 해야 할까?
- API 서버의 부하가 늘지 않게 요청을 하며 다 처리할 수 있어야 함
- 클라이언트는 당장 결과를 받지 않더라도, 최종적으로 결과를 받아야 함
Queue
- 클라이언트와 예측 서버 사이에 메시지 시스템(Queue)을 추가
- 대표적인 메시지 프레임워크 : Apache Kafka
- 지하철 물품 보관소와 유사한 역할
- Push : 메시지 저장
- Pull : 메시지를 가지고 와서 작업(예측) 수행
Usecase
- 예측과 클라이언트 진행 프로세스의 의존성이 없는 경우
- 예측 요청을 하고 응답을 바로 받을 필요가 없는 경우
- 예측을 요청하는 클라이언트와 응답을 반환하는 목적지가 분리된 경우
장점
- 클라이언트와 예측 프로세스가 분리 => 관계가 의존적이지 않음
- 클라이언트가 예측을 기다릴 필요가 없음
고민할 점
- 메시지 Queue 시스템을 만들어야 함
- 전체적으로 구조가 복잡해짐
- 완전한 실시간 예측엔 적절하지 않음(메시지를 가져갈 때 시간이 소요될 수 있음)
요약
디자인 패턴 = 템플릿 머신러닝 디자인 패턴 : 머신러닝의 특수성(Data, Model, Code)으로 생긴 패턴
- 모든 패턴을 외울 필요는 없고, 어떤 맥락에 쓰면 좋은지 이해하기. 개발하기 전에 떠올리기
Serving의 유형 별 패턴
- Batch Serving
- Batch 패턴
- Online Serving
- Web Single 패턴
- Synchronous 패턴
- Asynchronous 패턴
Anti Serving 패턴
Anti Serving 패턴은 권장되지 않는 Serving 패턴, 즉 주의해야 할 패턴
Online Bigsize 패턴
실시간 대응이 필요한 온라인 서비스에 예측에 오래 걸리는 모델을 사용하는 경우
(예시) 서버가 실행되는데 몇 분씩 소요되고, 요청에 대해 응답이 몇 초씩 걸릴 경우
문제
- 일반적으로 Bigsize 모델은 배포할 때 서버 실행과 서빙이 느림
- 속도와 비용 Tradeoff를 조절해 모델 경량화하는 작업이 필요
대안
- 실시간이 아닌 배치로 변경하는 것도 가능한지 검토
- 중간에 캐시 서버를 추가하고, 전처리를 분리하는 것도 Bigsize를 탈피하는 방법
All-in-One 패턴
하나의 서버에 여러 예측 모델을 띄우는 경우 (예시) predict1, predict2, predict3으로 나눠서 하나의 서버에서 모두 실행하는 경우
문제
- 라이브러리 선택 제한이 존재함
- 장애가 발생할 경우(서버가 갑자기 다운) 시스템이 마비됨 (SPOF, Single Point Of Failure)
대안
- 모델 별로 서버를 분리하여 배포 (Microservice 패턴)
요약
- Online Bigsize 패턴 : 예측이 오래 걸리는 모델을 사용하는 경우
- All-in-one 패턴 : 하나의 서버에 여러 예측 모델을 띄우는 경우
'Study - AI > Product Serving' 카테고리의 다른 글
1. ML Model Serving (2) | 2024.12.11 |
---|