[EATceed] CH03. 2024년 상반기 개발 진행 과정
Econovation 동아리 프로젝트: EATceed, 저체중인 사람들을 위한 건강한 체중증가 도움 애플리케이션
교내 개발 동아리 Econovation의 마지막 학기에 저번 학기에 이어서 EATceed 프로젝트를 진행했다.
EATceed에 대한 자세한 내용은 해당 글을 참고하면 된다.
[EATceed] 2. 프로젝트 소개
기능 변경 회고록을 진행하여 기능 변경과 추가에 대해 고민을 하였다. 이에 따라 다음과 같이 정리해보았다. 1. 음식 분류 모델을 이용한 음식 등록2. 사용자의 신체정보, 특이사항,섭취 영
wwns1411.tistory.com
Version1과는 다르게 Version2에서는 AI 기능을 담당할 뿐만 아니라 기능들을 애플리케이션에서 잘 수행될 수 있도록 서포트하는 작업에도 많은 노력을 기울였다. 해당 프로젝트를 진행하면서 전반적인 백엔드 지식을 알게 되었고, 이를 프로젝트에 적용했다. AI 서버를 구축하고 배포까지 진행했기 때문에 이에 필요한 많은 요소들을 배웠다.
프로젝트를 통해 얻은 스킬셋은 다음과 같다.
1. FastAPI : AI 기능의 API 서버 구축
2. Docker : 개발과 배포의 편리성을 위한 Docker 사용
3. AWS : 프로젝트 아키텍처의 AI와 BE 서버 분리로 인한 EC2 서버 구축
본문에서도 마찬가지로 기술적인 이야기는 하지 않고 새롭게 적용했거나, 발생한 이슈에 따른 문제 해결 과정을 위주로 작성하고자 한다.
함수화? 모듈화? 그게 뭔데?
EATceed 버전1 즉, 저번 학기에는 백엔드를 처음해봐서 그런지 일단 구현하는데 급급하였다. 그러다 보니 코드를 보면 난잡하기 그지없다. 다음은 main.py에 모든 내용을 집어넣는 깔끔하지 못한 코드의 예시이다(My code..😅)
코드를 보면 기능 별로 분리가 되어있지 않고, 사용자 인증하는 함수인 get_curren_member와 api 기능을 하는 chat 함수가 main.py라는 동일한 파일에 존재한다. main.py의 코드 중 일부만 캡처해서 그러지 모든 기능이 main.py에 존재한다..
2024년 겨울방학 때 기능 별로 분리해야지 리팩토링과 디버깅하기 용이하기 때문에 함수화와 모듈화를 진행해야한다는 글을 읽었다. 이때부터 코드를 작성할 때 함수화와 모듈화에 초점을 두기 시작했다.
왼쪽 디렉토리 구조를 보면 기능 별로 파이썬 스크립트를 분리해놨음을 알 수 있다. 예를 들어 api, database, authentication, router 등 각각의 기능에 맞게 스크립트가 디렉토리에 위치해있다. 이렇게 하다보니 최종적으로 실행하는 main.py는 정말 간단하게 표현이 된다.
함수화, 모듈화를 통해서 EATceed 프로젝트 뿐만 아니라 인턴 과정에서 LSTM 모델 분석하는 업무에서 많은 도움을 얻었다.
LSTM 모델 파이프라인 또한 함수화, 모듈화 되어있어 기존이었다면 코드를 분석하는 시간이 오래걸렸겠지만 빠르게 파악할 수 있었다.
AWS 비용을 줄이기 위해 짠돌이가 되어보자
EATceed 프로젝트 간단한 소개
EATceed 프로젝트는 앱 출시가 목표이므로 배포까지 진행해야 한다. 프로젝트에서 Docker를 사용하여 AWS EC2 서버에 올리고 실행하는 방식을 채택했다.
EATceed의 AI 기능은 식습관 분석 기능과 음식 이미지 판별 기능이 존재한다. 음식 이미지 판별 기능같은 경우는 팀원이 Torchserve를 사용하였기 때문에 팀원이 Dockerfile을 작성을 하였고, 식습관 분석 기능에 사용되는 FastAPI 관련 Dockerfile은 내가 작성을 했다. 두 기능에 관한 최종 디렉토리는 동일했기 때문에 docker-compose.yml을 구성을 해서 각 기능의 Dockerfile을 실행되도록 구성을 하였다.
최종 디렉토리는 AI 디렉토리이고 음식 이미지 판별 기능은 food_classfication, 식습관 분석 기능은 server에 존재하며 각각의 디렉토리에는 Dockerfile이 구성되어있다. 다음은 docker-compose.yml을 빌드한 후 Docker Dashboard의 Images 확인 결과이다.
food_classfication의 디스크 용량이 4.78GB라는 아주 큰 수치가 나왔다.. 팀원에게 필요하지 않은 라이브러리를 제거해주고 최대한 용량을 줄여달라고 바로 요청을 했고 이에 대한 결과는 다음과 같다.
4.78GB에서 2.55GB로 거의 2배 줄어들었음을 확인할 수 있다. 실행한 후 docker-compose stats 명령어를 통해 메모리 사용량을 확인하였다.
요청이 들어오지 않았을 때 두 개의 프로세스의 메모리 사용량은 약 1.3GB이다. 다음으로 AWS EC2 인스턴스에 따른 성능과 가격을 확인해보자.
인스턴스를 업그레이드시키면 메모리가 2배 늘어나고 이에 따라 요금(온디맨드 요금/시간) 또한 2배가 증가함을 알 수 있다.
그러면 현재 요청이 들어오지 않았을 때 약 1.3GB 정도 메모리를 사용하니 t3.small을 사용하는 게 적절하다. 하지만 여기서 비용을 어떻게든 줄이고 싶은 짠돌이 본능이 나와서 비용을 줄일만한 방법을 찾아보았다.
EC2 메모리 늘려서 비용 절감 시도
메모리를 늘리고 싶지만, 추가적인 비용(학생이다보니..)을 쓰기 싫어 대안으로 Swap 메모리를 설정했다.
Swap 메모리 개념은 이번 학기 운영체제 과목을 수강하면서 알게 되었다. 간단하게 말해서 스왑 메모리는 주 메모리의 한계(용량)를 극복하기 위해서 사용되는 보조 메모리이다. 현재 실행되지 않는 프로세스를 임시로 디스크 공간에 배치시키고, 빈 공간(메모리)에 다른 프로세스스를 적재해서 실행하는 방식을 Swapping이라고 한다.
Swapfile을 구성하는 방법을 간단하게 작성하면 다음과 같다.
# 메모리 용량 및 디스트 용량 확인
free -h
df -h
# 스왑 메모리 설정 전에 스왑 파티션 or 스왑 파일 생성(1Gib)
sudo fallocate -l 1G /swapfile
# swapfile 권한 변경
sudo chmod 600 /swapfile
# 스왑 파일 생성
sudo mkswap /swapfile
# 스왑 메모리 활성화
sudo swapon /swapfile
위의 명령어를 수행하고 free -h 명령어로 확인하면 다음과 같은 결과를 얻는다.
Swap: 1.0Gi가 설정되었음을 확인할 수 있다.
참고로 위의 명령어는 EC2 인스턴스 재부팅을 한 뒤 명령어를 통해 확인한 것이다.
EC2 인스턴스를 재부팅을 해도 동일하게 스왑 메모리를 할당하도록 하는 방법은 다음과 같다.
# 설정 파일
sudo vim /etc/fstab
# /etc/fstab에 작성
/swapfile swap swap defaults 0 0
그러면 장기적인 관점에서 바라볼 때 비용을 얼마나 줄였을까?
Swapfile을 구성하면 프로젝트에서 선택한 인스턴스인 t3.micro는 t3.small과 2GiB로 동일하다고 할 수 있다.
온디맨드 요금으로 비용 절감을 확인해보면 다음과 같다.
- t3.micro : $0.0104
- t3.small : $0.0209
- 시간당 절감액: $0.0105
- 연간 절감액: $91.98
1년 동안 서버를 실행시켰다고 가정했을 때 $91.98, 한국 돈으로 약 12만원 정도 절감할 수 있다.
이번 경험을 토대로 다른 프로젝트에서 배포를 진행할 때도 적용해야겠다는 생각을 했다.