안녕하세요, 요즘 이론 공부하는게 왜 이렇게 재밌죠... 근 5개월정도 글을 안쓰다가 오랜만에 쓰니까 글감이 폭발하는 것 같습니다. 이번 포스팅에선 AI 엔지니어링을 하면서 규모가 조금만 커져도 바로 고민해볼만한 "AI 엔지니어링과 EDA"라는 주제로 포스팅을 적어볼까합니다.
웹 백엔드에서의 EDA
EDA는 흔히 Event Driven Architecture의 약자로 쓰이고 메세지 브로커를 도입하면서 특정 행동을 로직에서 뜯어내고 싶을 때 주로 사용합니다. 저는 이 단어를 보면서 너무 "이벤트"에 매몰되기 쉬운 단어 선택이라고 생각합니다.
우선 AI 엔지니어링말고 웹 백엔드 관점에서 EDA를 먼저 짚고 넘어가도록 하겠습니다.
우리가 웹 백엔드에서 EDA를, 많은 경우 카프카를 선택하게 되는 경위는 뭘까요? 어떤 문제가 발생하면 EDA를 찾게되는걸까요?
제가 생각하는 문제의 원인은 느려터진 RDBMS의 쓰기 속도입니다. 이쯤에서 RDBMS의 쓰기를 뜯어보자면 다음과 같습니다.
- RDBMS는 일관성과 무결성에 특화된 데이터베이스입니다.
- RDBMS는 쓰기 작업을 진행할 때 서로 다른 트랜잭션간 일관성을 위해 Lock을 획득하는 과정이 있습니다. 이 락을 획득하지 못하면 쓰기 작업이 불가능합니다.
- RDBMS의 기본 자료구조인 B-Tree는 데이터가 자신이 누울자리를 직접 찾아 눕는 구조입니다. 현대 RDBMS의 B+Tree의 경우 쓰기 작업으로 인해 리프 노드가 찢어지게 되면 (페이징이 분할되면) 데이터를 다시 정렬하는 작업이 필요합니다.
- 만약 RDBMS에서 트랜잭션 도중 에러 발생이나 모종의 이유로 인해 롤백해야 하는 경우를 대비해 Undo 로그에 로그를 작성합니다.
- 만약 RDBMS에서 프로세스 자체가 다운되거나 했을 경우 데이터의 유실을 막기 위해 Redo 로그에 로그를 작성합니다. (ACID에서 D에 해당하는 내용이죠)
RDBMS가 이런식으로 진화하게 된 데에는 여러가지 이유가 있지만 그 중 가장 큰 비중을 차지한다고 생각하는 점은 바로 읽기 작업과 쓰기 작업의 비율이라고 생각합니다.
대부분의 웹 서비스는 읽기 작업이 압도적으로 많고 쓰기 작업이 압도적으로 적기 때문에 이런 전략을 취하는 것은 당연하다고 생각합니다. 다만, 저녁시간의 배달의민족이나 설날 / 추석 시즌의 쿠팡의 데이터베이스 쓰기 작업은 정말 어마어마하겠죠.
이걸 동기식으로 처리하면 쓰기 작업이 다 완료될 때까지 기다려야하는 문제가 발생했습니다. 쓰기 작업이 진행되던 도중에 사용자가 브라우저를 내린다거나 앱을 종료하는 순간 큰 문제가 발생할 것이 뻔했죠. 그래서 개발자들은 이런 큰 리소스를 사용해야하는 쓰기 작업을 뜯어내고싶었습니다.
그래서 등장한 것이 바로 EDA입니다.
AI 엔지니어링과 EDA
이제 AI 엔지니어링 얘기로 돌아와서, LLM을 품고 있는 컴퓨터는 쓸 수 있는 자원이 정해져있습니다. 그것을 쿠버네티스 파드로 띄우던 온디맨드로 띄우던말이죠. 이 때 가장 큰 문제는 OOM입니다. 특히 LLM은 늘어나는 맥락으로 인해 KV Cache가 엄청나게 빠르게 늘어나고 이는 유저가 몇명만 붙어도 금방 OOM으로 이어질 수 있습니다.
또한, 채팅 내역을 관리해야하는 상황에서 데이터베이스에 채팅 내역을 저장하면 쓰기 작업에 대한 오버헤드를 무시할 수 없었죠. 물론 NoSQL을 사용하면 RDBMS에 비해 어느정도 쓰기 작업에 대한 오버헤드를 줄일 수 있었지만 여전히 부담스러운 것은 사실이었죠.
이때 EDA가 등장하게 됩니다.
메세지 브로커의 큐에 작업들을 넣어놓고 LLM이 처리할 수 있는 정도만 뽑아다 쓸 수 있는 버퍼가 생기게 된 것이고 쓰기 작업 또한 큐에 집어넣어 뒤로 미룰 수 있었으니 누이좋고 매부좋고 모두가 행복해지기 시작했죠. 그뿐만아니라 수평확장의 악마답게 수평으로 확장하기도 매우 편해졌습니다.
그뿐만아니라 배포의 관점에서 봤을 때 AB 테스트를 쉽게 할 수 있다는 장점도 있는데요. 신규 버전의 B를 같은 Consumer Group으로 묶어버리면 아무도 모르게 AB테스트를 할 수 있고 이는 카나리 배포와 비슷한 맥락을 공유하죠.
마지막으로 쓰기 작업을 로직에서 뜯어냈으니 결과론적인 일관성 (Eventual Consistency)를 얻을 수 있었고 딱히 일관성이 중요하지 않은 AI 엔지니어링에서 빛을 발하게 됐습니다.
EDA의 단점
EDA의 단점은 웹백엔드에서 EDA를 도입했을 때의 단점과 일맥상통합니다. 크게 본다면 관리포인트의 증가이고 작게 본다면 다음과 같습니다.
메세지 브로커를 관리해라
우선 메세지 브로커 그 자체를 관리해야합니다. 카프카나 RabbitMQ, Redis Stream이 바로 그것이죠. 특히 많이 사용되는 카프카의 경우 etcd나 구버전의 경우 zookeeper도 관리해야하는데 이런 관리포인트의 증가는 개발자 입장에서 기술적 부채가 되기 쉽습니다.
카프카 클러스터가 늘어나면 또 어떻게 관리해야할지 Consumer Group은 어떻게 관리해야할지, Scalability는 어떻게 해야할지 정말 막막해집니다.
메세지 실패 시 재처리 로직 개발
단순히 메세지만 실패하면 DLQ를 직접 만들어 완화할 수 있지만 이게 트랜잭션이랑 같이 엮이기 시작하면 꽤나 골치아파집니다.
메세지는 정상적으로 갔다 -> 근데 백엔드에서 에러가 발생했다 -> 쓰기 작업이 롤백됐다
그럼 재시도 해야지!
어떻게..?
메세지가 정상적으로 가서 카프카 입장에선 DLQ에 저장할 필요도 없었고 정상 처리된 메세지인데 어떻게 다시 보낼까요?
그럼 또 Outbox Pattern이니 뭐니 하면서 또 추가 개발이 들어가야합니다. 이것도 상당한 리스크이죠.
https://coding-review.tistory.com/566
메세지 브로커의 근심과 걱정
마이크로 서비스와 메세지 브로커는 뗄 수 없는 사이입니다. 서로 다른 도메인이 여러개의 서버로 나눠져 있는 상황에서 모든 서버에 동일하게 데이터를 전달해야 하는 경우에 메세지 브로커만
coding-review.tistory.com
LLM의 맥락을 유지해라
LLM의 맥락을 유지하기 위해 Langchain의 자체적인 메모리 저장도 도움이 되겠지만 결국 긴 맥락을 유지하기 위해서 Redis같은 경량 인메모리 데이터베이스가 필요하기 마련입니다.
그럼 Redis가 죽으면 어떡해요? 죽는걸 냅둘 수는 없으니 또 HA 기술인 Sentinel이니 Cluster니 이것저것 덕지덕지 바르게 됩니다. 그 과정에서 생기는 문제는 또 덤이구요.
https://coding-review.tistory.com/542
나는 왜 Redis Cluster 대신 Redis Sentinel을 사용하였는가.
이번 포스팅에선 Redis Cluster에 대해서 깊이있게 공부해볼겸 왜 제가 Redis Cluster 대신 Redis Sentinel을 사용하게 되었는지 정리해보는 시간을 가져볼까합니다. Redis ClusterRedis Cluster는 Redis Sentinel의
coding-review.tistory.com
따라서...
결국 AI 엔지니어링의 끝은 웹 백엔드와 닿아있는 것 같습니다. 결국 얼마나 안정적으로, 적은 컴퓨팅 자원으로, 응답속도를 고려하면서 잘할 수 있는지가 주된 관건이 되겠지요.
요즘 드는 생각이지만 AI 엔지니어링이라고 거창하게 말을 붙였지만 사실 웹 백엔드에서 관리포인트만 하나 늘어난 기분입니다. 쿠버네티스가 그랬고 카프카가 그랬고 Istio가 그랬고 데이터베이스가 그렇죠... 다 하나같이 어마무시하게 큰 기술들인데 이게 어느순간 감당하기 힘들어지면 독립 팀으로 찢어지는 것들인데 이제 AI 엔지니어링도 그렇게 될까 싶은 생각이 듭니다.
항상 오버엔지니어링과 좋은 기술 선택 사이에서 줄타기를 잘 하면서 안정적으로 개발하고 운영해야겠습니다.
이번 포스팅도 읽어주셔서 감사합니다. 오늘도 즐거운 하루 되세요!
'AI Engineering > 이론' 카테고리의 다른 글
| vLLM은 어떻게 AI 엔지니어링에서 필수불가결한 선택지가 되었을까? (0) | 2026.01.08 |
|---|---|
| 양자화란 무엇인가 (0) | 2025.12.09 |