
네이버 부스트캠프를 마치고, 깊이 있는 기술적 고민과 긴 호흡의 프로젝트에 대한 갈증을 해소하고자 지원했던 8개월 간의 SW 마에스트로 과정을 수료했다.
SW 마에스트로 과정 동안의 기억이 휘발되기 전에 내가 느끼고 배웠던 것들을 기록하고자 한다.
SW 마에스트로의 시작은 팀빌딩이었다. 신기하게도 OT 첫날, 네이버 부스트캠프에서 함께 프로젝트를 했던 팀원을 우연히 다시 만났고, 서로 좋은 기억으로 남아있었기에 이번에도 함께하기로 했다.
3인 팀 구성이 원칙이었고 우리 둘은 모두 백엔드 개발자였기에, 프론트엔드를 담당해 줄 팀원 한 분이 필요했다. 하지만 프론트엔드 개발자의 비율이 낮았고, 다른 팀들의 팀빌딩 속도도 무척 빨라 적합한 팀원을 구하기가 쉽지 않았다.
여러 방면으로 팀원을 구하기 위해 노력하던 중, 한 연수생 분과 연락이 닿았다.
그분은 본래 백엔드를 공부해오셨지만, 개발 자체보다 '창업'에 더 큰 뜻을 품고 계셨다. 창업 과정에서 프론트엔드 경험도 쌓고 싶었고, 무엇보다 프로젝트의 성공을 위해 기꺼이 새로운 도전을 감수하겠다는 열정적인 분이셨다. 만들고 싶어 하는 아이템도 흥미로워 인기가 많았는데, 감사하게도 여러 2인 팀의 연락 속에서 우리를 선택해주셔서 무사히 팀빌딩을 마칠 수 있었다.
우리 팀이 구상 중이었던 아이템은 AI와 Cloud에 대한 깊은 인사이트가 필수적이어서 해당 분야에 전문성을 갖춘 멘토님들을 전담 멘토로 모시고자 했다.
다행히 우리가 구상 중인 아이템과 팀원들의 열정을 좋게 봐주신 덕분에, 1순위로 희망했던 멘토님들 모두를 전담 멘토로 모실 수 있었다.
우리가 구상했던 서비스는 AI 기반 클라우드 인프라 자동화 솔루션이었다.
이 아이디어는 스타트업에게 클라우드가 생존과 직결되지만, 전문 아키텍트나 데브옵스 엔지니어를 채용하기엔 비용 부담이 크다는 현실적인 문제에서 출발했다. 우리는 이 문제를 AI 기술로 해결하여, 전문 지식 없이도 클라우드 인프라를 효율적으로 설계하고 관리할 수 있는 솔루션을 만들고자 했다.
SW 마에스트로 기간 내 완성할 수 있는 현실적인 목표를 설정하고자, 멀티 클라우드 지원에서 AWS만 지원하는 것으로, 복잡한 아키텍처는 배제하고 간단한 3-tier 아키텍처로 범위를 좁혀나갔다.
그래서 나온 최종 목표는 사용자가 자연어로 요구사항을 입력하면, 1시간 안에 AWS의 Well-Architected Framework 기반 인프라를 설계하고 배포까지 완료하는 클라우드 솔루션을 구현하는 것이었다.
우리는 백엔드 팀원 모두가 가장 익숙한 MySQL 기반으로 데이터베이스를 구축하기로 결정을 했었다. 하지만, 설계 과정에서 Terraform 코드에 대한 형상 관리와 롤백 기능이 필요하다고 판단했고, 이를 위해 .tfstate 파일과 Terraform 코드를 저장해야 했다.
그러나, 이 두 파일의 경우에는 아키텍처에 따라, 필드 자체가 달라질 수 있는 비정형 데이터였기 때문에, 부분적으로 MongoDB를 도입하게 됐다.
MongoDB는 기본적으로 json 형식의 데이터를 저장할 수 있었고, tfstate는 원래 json 형식이라 문제가 없었지만, Terraform 코드를 어떻게 저장할지 고민이었다.
이에 저장 방식을 고민하던 중, Terraform 코드를 .tf.json 형식으로 변환해도 Terraform 엔진 기반으로 모든 기능을 사용할 수 있음을 알게 되었다.
하지만, 서로 다른 종류의 DB를 함께 사용하게 되면서, 두 DB를 모두 활용하는 API에서 원자성을 보장하지 못한다는 문제가 발생했다.
다양한 방식을 고려해보았으나, MySQL과 MongoDB를 함께 지원하는 트랜잭션 처리에 대해 일반적인 해결책이 없고 시스템 단위의 복잡한 구현이 필요했다. 우선 빠른 MVP 구현을 위해, 애플리케이션 레이어에서 예외처리를 통해 직접 롤백 로직을 구현하기로 결정하였다.
덕분에 Spring Data MongoDB 소스코드 뜯어보다가, Contribution도 했다.
우리 서비스의 핵심은 AI와의 상호작용이었다.
사용자의 요청을 AI 에이전트에게 안정적으로 전달하고, AI가 생성한 응답을 다시 사용자에게 끊김 없이 스트리밍하는 것에 대한 고민이 필요했다.
처음에는 메시지 브로커로 Redis의 Pub/Sub 모델을 고려했었으나, 데이터 유실 가능성이 문제였다. Pub/Sub은 메시지 발행 시점에 활성화된 구독자가 존재하지 않으면 해당 메시지가 즉시 소멸되는 구조였다. 이는 AI 에이전트 서버가 배포 중이거나, 일시적인 장애 또는 네트워크 문제로 재연결하는 상황에서 API 서버로부터 들어오는 중요한 작업 요청이 유실될 수 있음을 의미했다.
이에 반해, Redis Streams은 Pub/Sub과 달리 메시지를 메모리에 보관하므로, 컨슈머가 잠시 다운되었다가 복구되어도 중단된 시점부터 메시지를 다시 읽어올 수 있어, 요청 데이터의 유실을 원천적으로 방지할 수 있었다.
또한, 컨슈머 그룹 기능을 통해 여러 AI 에이전트 인스턴스가 분산하여 메시지를 처리할 수 있었고, 특정 메시지 처리가 완료되었음을 알리는 명시적인 ACK 기능은 처리 실패 시 재시도를 가능하게 하여, 메시지가 최소 한 번 이상 처리되는 것을 보장할 수 있었다.
실시간 알림과 같이 일부 메시지 유실이 허용되는 시나리오와 달리, 모든 요청이 처리되어야 하는 시스템이 었기에 Redis Streams를 도입하기로 결정했다.
클라우드 인프라에 대한 정보를 사용자의 클라우드 계정, AI Agent, API Server 등 다양한 시스템 사이에서 주고 받아야 했기에, 이를 위한 프로토콜 역할을 해줄 IaC를 선정해야 했다.
초기 MVP에서는 AWS만을 대상으로 하도록 결정했었기에 Cloud Formation과 AWS CDK 조합도 고려했었으나, 이후 멀티 클라우드(Azure, GCP)로의 확장 가능성과 커뮤니티의 크기를 고려하여 Terraform을 사용하기로 결정했다.
나는 백엔드 개발에서 크게 2가지 도메인을 담당했다.
첫번째 문제는 사용자 클라우드 계정의 리소스 제어 권한을 어떻게 받아올지였다.
가장 간단한 방법은 Access Key를 직접 받아 저장하고 활용하는 것이었지만, 클라우드 계정의 Access Key는 굉장히 민감한 정보이기 때문에, 고객 입장에서 큰 거부감이 있을 것이고, 이러한 민감 정보를 직접 관리하는 것은 우리에게도 부담이 크다고 판단했다.
경쟁사에서는 이 문제를 어떻게 해결했는지 조사해보니, 대부분 Access Key 방식을 제공은 하되 권장하지는 않았다. 대신, IAM role과 assumeRole API를 활용한 방식을 권장하고 있었다. 이 방식은 만료 기간이 설정된 임시 자격 증명을 발급받아 사용하므로 훨씬 안전했기 때문에 이 방식을 채택하여 보안성을 높였다.
두번째 문제는 Terraform 코드 내에 포함될 수 있는 민감 정보였다.
기업의 인프라는 굉장히 중요한 자산이다보니 보안성이 확보되어야 고객의 신뢰를 얻을 수 있다고 판단하여, AWS KMS를 활용한 E2EE를 도입하기로 결정했다.
자세한 내용은 별도 글로 정리해두었다.
AWS KMS를 활용한 E2EE
첫번째 문제는 사용자 클라우드 계정의 리소스를 어떻게 Terraform 코드와 .tfstate로 변환할 것인가였다.
초기 단계에서는 오픈소스를 도입해 빠르게 구현하고, 이후 내재화하는 것이 적절하다고 판단했다.
그래서, Terraformer라는 오픈소스를 통해, 인프라 리소스들을 Terraform 코드와 .tfstate로 변환하고, hcl2json라는 오픈소스를 활용해 Terraform 코드를 .tf.json 형식으로 변환하는 과정을 구현했다.
이때, Terraformer와 hcl2json 모두 CLI 프로그램이었기 때문에 Java의 ProcessBuilder 클래스를 활용했고, Enum 기반의 입력 값 검증을 통해 Command Injection에 대해 안전한 명령어 실행 환경을 구성했다.
두번째 문제는 한 사건으로부터 발견되었다.
우선, 배포 기능의 경우에는 .tf.json 형식에서도 apply 명령을 수행할 수 있었기에, MongoDB에서 꺼내온 최신 버전의 .tfstate와 Terraform 코드를 사용해 어렵지 않게 구현할 수 있었다.
하지만, 팀원이 우리 서비스의 AWS 계정을 대상으로 테스트를 수행하다가 모든 리소스를 다 날려버리는 사건이 발생했다. 해킹 당한 줄... IAM 하나만 있는 Terraform 코드를 배포했다가, 기존 리소스를 모두 삭제하고 IAM 하나만 남겨 버린 것이었다.
이 사건을 계기로, 실제 변경 사항을 적용하기 전에 반영될 결과를 미리 한번 보여주는 기능이 필요함을 인지하게 됐고, plan 명령어의 표준 출력을 읽어와 배포 수행 시 어떤 작업이 수행될지를 미리 보여주는 기능을 추가하게 됐다.
세번째 문제는 여러 Region의 리소스를 사용하는 프로젝트의 관리였다.
하나의 클라우드 계정에서 여러 프로젝트를 관리하는 것은 흔한 일이다보니, 어떤 리소스가 어떤 프로젝트에 속해 있는지 식별할 수 있어야 했고, Amazon Resource Group Tagging API 기반으로 우리 서비스에서 관리하는 Project의 ID를 Tag로 붙여 프로젝트 단위로 리소스를 구분했다.
여기서 문제는 한 프로젝트에 여러 Region의 리소스가 포함될 수 있다는 것이었다.
Terraformer는 내부적으로 각 클라우드 벤더의 SDK를 사용하고, SDK는 Region 단위로 리소스를 import하고 있었기 때문에 Terraformer 또한 마찬가지였다.
그래서, 모든 Region에 대한 import를 수행해야 했고, 응답 시간을 줄이고자 병렬 처리를 시도했으나, Region이 워낙 많다보니 컴퓨팅 자원 낭비가 심했다.
결국, Project 별로 사용자에게 사용 중인 Region을 입력 받아, 해당 Region에 대해서만 리소스를 가져오도록 구현하여 효율성을 높였다.
아무튼 가져와서 다이어그램으로 만들기 성공.
AI와 클라우드 자동화를 다루는 서비스 특성상, 우리 서비스 자체도 MSA 구조를 갖춰야 했다. 또한, 멀티 클라우드로의 확장 가능성을 고려하면, 유연하게 확장 가능한 구조가 필수적이었다.
이를 위해 기존 5개의 EC2로 구성되어있던 초기 인프라를 EKS 기반의 K8s 환경으로 재구축하게 되었고, 이를 내가 담당하게 되었다.
자세한 내용은 별도 글로 정리할 예정이다.
2025년을 대부분 쏟아 부었던 활동인 만큼, 잘 마무리 하고 싶은 마음이 컸다.
최종 발표에서 예상치 못한 오류로 준비한 모든 것을 보여드리지 못한 것에 조금 아쉬움이 남기는 하지만...
깊은 기술적 고민을 감안해주셨는지, 단기 해외 연수자로 선정도 되고 ... 어떻게 됐지 ?

수료생 인터뷰도 하고...

나름 유종의 미를 거둔 것 같다.
처음 목표했던 긴 호흡의 프로젝트와 그 과정에서의 깊은 기술적 고민을 모두 경험할 수 있었다.
특히, Cloud와 AI 분야에서 많은 경험과 깊은 고민을 할 수 있었다.
덕분에, 다음 달 부터 Microsoft Korea에서 Cloud & AI Solution Engineer로 인턴십을 하게 됐다. 공짜 해외 연수 못가는 건 좀 아쉽다.
좋은 기회를 얻게 된 만큼
마지막에 대한 아쉬움을 뒤로하고, 새로운 시작을 위해 다시 달려보겠다.