INSK를 배포하기로 결정했을 때, 목표는 명확했다.
“서비스처럼 보이는 결과물”이 아니라, 운영 환경에서 실제로 돌아가는 구조를 만드는 것이었다.
개발 단계에서는 로컬 환경에서 모든 기능이 정상 동작했다.
하지만 그 상태로는 이 프로젝트가 어디까지 갈 수 있는지 판단할 수 없었다.
그래서 비교적 이른 시점에 배포를 먼저 경험해보기로 했다.
INSK의 배포 구조
- Compute
AWS EC2 단일 인스턴스
- Database
AWS RDS (MySQL)
- Cache
Redis
- Web / Reverse Proxy
Nginx
- Application
Spring Boot (API + 배치 작업)
- 배포 방식
Docker 기반 컨테이너화
GitHub Actions 기반 CI/CD
배치 작업은 @Scheduled 기반으로 애플리케이션 내부에서 함께 실행되도록 구성했다.
API 서버와 배치 서버를 분리하지 않은 구조였다.
이 시점에서는 빠른 배포와 단순한 운영을 우선 기준으로 삼았다.
당시의 판단 기준은 현실적이었다.
하나의 인스턴스로도 충분한 트래픽 규모
비용을 통제할 수 있는 구조
배포 파이프라인을 직접 구성해보는 경험
API와 배치 로직을 한 흐름에서 관리
특히 뉴스 수집·요약·분류 파이프라인을
“서비스 외부 작업”이 아니라 서비스 내부 책임으로 두고 싶었다.
그래서 배치 작업 역시 Spring 애플리케이션 안에 포함시켰다.
배포를 마친 뒤에야
이 구조가 여러 전제 위에 서 있다는 걸 인식하게 됐다.
서버는 쉽게 죽지 않는다
배치 작업은 대부분 정상 종료된다
LLM API 호출은 거의 실패하지 않는다
API 요청은 동시에 몰리지 않는다
Redis는 캐시일 뿐, 없어도 치명적이지 않다
배포 중 트래픽은 거의 없다
이 전제들은 문서로 정리한 적도, 검증한 적도 없었다.
'그럴 것이다'라는 가정 위에서 구조를 쌓아 올린 것이었다.
배포 자체는 비교적 수월하게 끝났다.
CI/CD 파이프라인도 정상적으로 동작했고, 서비스는 외부에서 접근 가능했다.
하지만 운영 환경에 올린 순간부터,
개발 환경에서는 느끼지 못했던 문제들이 하나씩 드러나기 시작했다.
배포는 성공했지만 애플리케이션이 기동되지 않는 경우
배치 작업이 조용히 멈춰 있는 상태
캐시 적용 이후 데이터 정합성이 어긋나는 문제
외부 API 실패가 전체 흐름을 중단시키는 상황
이 문제들은 대부분 코드 한 줄의 버그라기보다,
구조와 전제의 문제에 가까웠다.
이 시점에서 분명해진 사실이 하나 있었다.
이 구조는 ‘돌아가는 데에는 충분하지만’,
운영을 전제로 안전하다고 말하기에는 근거가 부족하다.
배포를 통해 알게 된 건
“어떻게 배포했는가”보다
“무엇을 당연하다고 가정하고 배포했는가”였다.
이 구조는 장애를 전제로 설계되지 않았고,
실패를 정상 흐름으로 받아들이지도 않았다.
그리고 이 문제들은
단순한 리팩토링이나 설정 수정으로 해결될 성격이 아니었다.
이 글은 배포 성공 사례를 정리하기 위한 기록이 아니다.
개발자 기준으로 세운 판단들이 운영 환경에서 어떻게 흔들리는지를 확인하기 위한 중간 정리다.
다음으로 정리할 트러블슈팅 아카이브는
이 구조에서 실제로 발생한 문제들을
사고 기록 형태로 남기는 문서가 될 것이다.
그 이후에,
이 전제들을 하나씩 부수는 재설계를 시작하겠다.