Overview
- 크라우드웍스에서 초기 6개월 동안 프로젝트 를 수행하면서 개발자와 비개발자들이 프롬프트 엔지니어링과 서비스 개발에 걸쳐 가지고 있던 요구 사항을 종합하고 AWS 생태계 내에서 지속 가능한 해결책을 도출하려고 노력했습니다.
- 3단계로 나누어진 프로젝트에서 첫 번째 단계로 Queue consumer service와 프롬프트 운영 프로세스를 Python으로 개발했습니다.
- 3단계 전체에서 CloudFormation을 기반으로 하는 AWS CDK 와 Copilot CLI 를 조합한 ECS 서비스 2개를 중심으로 다양한 AWS 리소스를 생성했습니다.
Technology
CloudFormation Stacks
Copilot CLI + AWS CDK
- VPC 구성과 같은 정형화된 초기 설정과, 컨테이너 이미지만을 변경하는 빈번한 코드 배포는 Copilot CLI를 이용했습니다.
- Copilot CLI는 AWS가 직접 개발에서 권장하는 ECS 서비스 배포 방식입니다.)
- ECS 서비스가 의존하는 추가적인 AWS 리소스들은 CDK로 정의해서 별도로 배포했습니다.
- 이때 Copilot CLI로 배포한 CloudFormation stack에 YAML patch override
를 이용해 export를 추가하고, 이를
Fn.importValue()함수로 import해서 CDK가 의존성을 가질 수 있도록 구성했습니다.
Monorepo & Build settings
Monorepo Layout
# Repository cw-d-service
├── cdk
├── copilot
├── d-chat-api # ECS Service 1
│ ├── chat_api
│ │ ├── __init__.py
│ │ └── main.py # imports models
| ├── Dockerfile
| ├── pyproject.toml # installs models
│ └── tests
├── d-worker # ECS Service 2
│ ├── comment
│ │ ├── __init__.py
│ │ └── comment.py # imports models
| ├── Dockerfile
| ├── pyproject.toml # installs models
│ └── tests
├── docker-bake.hcl # Builds 3 container images
├── Makefile
└── models # Shared package
├── Dockerfile
├── models
│ └── api_model.py
├── pyproject.toml # Common dependencies
└── tests
- cdk와 copilot 폴더에는 IaaS 구성에 필요한 TypeScript 파일과 YAML 파일이 있음
- 2개의 Copilot service
의 Python 소스 코드가 worker와 chat-api 폴더에 존재
- 각각 테스트 폴더를 포함함
- 각각 컨테이너 이미지를 생성할 수 있음
docker-bake.hcl파일을 이용한 High-level build 기능으로 Monorepo 전체를 빌드하고 3개의 컨테이너 이미지 Artifact를 생성할 수 있음- 테스트, 빌드, 배포는 Makefile에 적힌 명령어로 모두 수행할 수 있음
Python Development
- Strong typing을 강제할 수 있는 pyright language server 설정을 권장하고 TDD를 도입해 프로젝트 전체를 구동하거나 배포하기 전에 기능 단위로 개발할 수 있도록 했습니다. 그 결과 Edge case를 폭넓게 고려하는 개발을 효율적으로 진행할 수 있었으며, 크라우드웍스 최초의 B2C 프로젝트에 안정적인 서비스를 가능케 했습니다: 기사 링크
- 사용자에게 추천하는 식품들의 후보는 DB화해 고객사가 정확하게 제어할 수 있도록 하는 기능을 개발했습니다.
- 복수의 LLM API key를 사용해야 할 경우, 키의 Tier를 고려해 사용량을 제거하고 추가/삭제할 수 있는 관리 체계를 개발했습니다. 기존에는 요청마다 API key를 임의로 선택하는 로직을 사용해 애플리케이션 전체에 코드나 설정 변경이 필요했으나, 이 프로젝트에서는 컨테이너 1개 당 API 키를 1개씩만을 할당해 모니터링과 운영을 용이하게 했습니다. ECS 컨테이너는 초기화 시 ECS task metadata API 와 ECS API를 통해 API key의 사용 현황을 확인하고 가장 적게 사용된 것을 선택합니다.
- AWS X-Ray tracing과 OpenTelemetry를 도입해 dev stage에서의 프롬프트 실험을 용이하게 하고 prod stage를 모니터링했습니다. X-Ray console에서 API Gateway, SQS, ECS task, SNS로 이어지는 구간 별 성능을 파악할 수 있었고, OpenTelemetry instrumentation OpenAI 을 적용해 생성 결과와 토큰 사용량을 추적했습니다: 자세한 사용 방식과 코드
Lessons
- 신문 PDF 정형화 프로젝트 에서 수백 개 단위의 AWS 리소스를 IaaC 없이 진행하며 많은 어려움을 겪었는데, 이번 프로젝트에서는 dev, prod 환경을 git에 커밋된 그대로 재현할 수 있었습니다.
- 크라우드웍스에서는 데이터 담당 개발자뿐만 아니라 비개발자들이 기획과 QA를 담당했습니다. 이 팀원들이 개발에 기여할 수 있도록 프로세스를 만들고 고객과 커뮤니케이션하는 데 참여할 수 있었습니다.
- Python typing을 본격적으로 적용한 첫 프로젝트였는데, TypeScript와 비교해서 장단점이 눈에 보였습니다. Python typing은 TypeScript와 달리 언어 표준에 의한 구현이다 보니
satisfies, const 등의 키워드를 통한 정밀한 제어가 부족하다고 느꼈으나, pydantic 과 같이 사용했을 때의 강력한 기능은 매우 유용했습니다.