
창의적 인텔리전스 에이전트: 문제, 솔루션(아키텍처), 에이전트
요약
광고 크리에이티브의 성과 원인을 분석하기 위해 설계된 '크리에이티브 인텔리전스 에이전트'의 구축 과정을 다룹니다. 멀티모달 모델을 활용해 광고 요소를 구조화된 데이터로 추출하고, 이를 바탕으로 신뢰할 수 있는 추론을 수행하는 아키텍처를 제안합니다.
핵심 포인트
- 단순 지표를 넘어 크리에이티브 요소와 성과 간의 상관관계 분석
- 멀티모달 모델을 통한 '크리에이티브 게놈' 구조화 추출
- 결정론적 데이터 계산 후 에이전트 추론을 수행하는 설계 원칙
- 신뢰성, 멱등성, 비용 통제를 위한 런타임 하네스 구축
창의적 인텔리전스 에이전트: 문제, 솔루션(아키텍처), 에이전트
마케팅 대시보드는 한 가지 질문에 답하는 데 능숙합니다:
무슨 일이 일어났는가?
지출이 증가했습니다. ROAS(광고비 대비 매출액)가 하락했습니다. CTR(클릭률)이 개선되었습니다. 캠페인이 피로 징후를 보이기 시작했습니다.
그 정보는 유용하지만, 크리에이티브 팀이 실제로 답을 얻어야 하는 질문은 아닙니다.
그들의 질문은 더 어렵습니다:
왜 이 크리에이티브가 효과가 있었으며, 다음에 무엇을 만들어야 하는가?
그 답은 단일 지표 행에 들어있지 않습니다.
광고 크리에이티브는 다음과 같은 많은 결정들로 구성된 이미지 또는 비디오입니다:
- 후크 (The hook)
- 처음 3초 (The first three seconds)
- 페르소나 (The persona)
- 메시징 각도 (The messaging angle)
- 제안 (The offer)
- CTA (Call to Action)
- 비주얼 형식 (The visual format)
- 오디오 (The audio)
진정한 과제는 이러한 결정들이 성과(performance)와 어떻게 매핑되는지 이해하는 것입니다.
지난 몇 주 동안, 저는 그 질문에 답하기 위해 설계된 크리에이티브 인텔리전스 에이전트(creative intelligence agent)를 구축했습니다. 이 포스트에서는 데이터 아키텍처(data architecture), 백그라운드 프로세싱(background processing), 프롬프팅(prompting), 컨텍스트 구축(context construction), 메모리(memory), 툴 콜링(tool calling), 그리고 에이전트를 신뢰할 수 있게 만드는 런타임 하네스(runtime harness)를 다룹니다.
이 시스템의 핵심 원칙은 다음과 같습니다:
결정론적인 부분들—구조, 통계, 신뢰도, 증거—을 직접 계산하고, 그 후에만 에이전트가 그 데이터들을 바탕으로 추론하게 하라.
어려운 점은 언어 모델(language model)을 호출하는 것이 아니었습니다.
어려운 점은 분석이 신뢰할 수 있고, 멱등성(idempotent)을 유지하며, 비용이 통제되고, 설명 가능하며, 여러 대화에 걸쳐 유용하게 유지될 수 있도록 그 주변의 시스템을 구축하는 것이었습니다.
핵심 데이터 아키텍처: 크리에이티브 게놈 (Creative Genome)
시스템의 원자 단위는 **크리에이티브 게놈 (creative genome)**입니다.
멀티모달 모델(multimodal model)이 실제 광고를 관찰하고, 산문 형태의 문단 대신 구조화된 추출(structured extraction) 결과를 반환합니다.
추출 내용에는 다음이 포함됩니다:
- 후크(hook) 및 해당 내용의 그대로의 전사(verbatim transcript)
- 제품이 처음 등장하는 시점과 같은 타이밍 정보
- CTA(Call to Action)의 타임스탬프
- 메시징 각도(messaging angle)
- 광고에서 주장하는 내용(claims)
- 시각적 스타일(visual style)
- 페르소나(persona)
- 오디오 특성(audio characteristics)
단일 광고에 대한 구조화된 게놈(genome)은 유용하지만, 수천 개의 광고를 분석해야 할 때는 크리에이티브당 하나의 JSON 블롭(blob)을 사용하는 방식이 잘 작동하지 않습니다.
다음과 같은 질문을 효율적으로 던질 수 없기 때문입니다:
- 어떤 후크 유형이 가장 좋은 성과를 내는가?
- 어떤 페르소나가 어떤 오퍼(offer)와 잘 맞는가?
- 어떤 조합이 피로도(fatigue)를 보이고 있는가?
- 경쟁사가 사용하고 있지만 우리는 사용하지 않는 크리에이티브 각도는 무엇인가?
이를 가능하게 하기 위해, 각 게놈은 크리에이티브 태그(creative tags) 세트로 확장됩니다.
이 태그들은 다음 항목당 하나의 레코드를 가진, 인덱싱된 작은 행(rows)입니다:
(entity, dimension, value)
예를 들어:
hook_type = ugc_handheld
confidence = 0.82
evidence = {
...
깊게 중첩된(deeply nested) JSON 문서는 GROUP BY를 쉽게 수행할 수 없습니다.
하지만 이러한 태그들은 하루 종일 GROUP BY 할 수 있으며, 성과 데이터(performance data)와 직접 조인(join)할 수 있습니다.
게놈이 하나의 크리에이티브의 정체성을 나타낸다면, 태그는 전체 계정의 크리에이티브 어휘(vocabulary)를 나타냅니다.
이 두 구조를 중심으로 다음과 같은 여러 엔티티(entity)가 구축됩니다:
creative_patterns: 태그 성과, 태그 조합, 임베딩 클러스터(embedding clusters), 경쟁사 격차를 포함하여 매일 탐지되는 승리 및 패배 패턴creative_kb_summaries: 에이전트의 컨텍스트(context)에 포함되는,
시스템 아키텍처: 워커(Workers), 인텔리전스 작업(Intelligence Jobs), 그리고 에이전트 런타임(Agent Runtime)
시스템은 세 가지 주요 부분으로 구성됩니다:
- 크리에이티브 추출 워커 (creative extraction worker)
- 일일 인텔리전스 파이프라인 (daily intelligence pipeline)
- 계획을 세우고, 컨텍스트(context)를 검색하며, 도구(tools)를 호출하고, 답변을 합성하는 에이전트 런타임 (agent runtime)
1. 크리에이티브 추출 워커 (The Creative Extraction Worker)
장시간 실행되는 워커가 작업 큐(job queue)를 비우며 게놈 추출(genome extraction)을 수행합니다.
각 광고에 대해 다음을 수행합니다:
- 크리에이티브 에셋(creative asset)을 확인(resolve)합니다.
- 이미지 또는 비디오를 모델에 업로드합니다.
- 구조화된 추출(structured extraction)을 실행합니다.
- 응답을 검증(validate)합니다.
- 결과물인 게놈(genome)과 태그(tags)를 저장합니다.
단일 추출에는 약 30초에서 90초 정도가 소요될 수 있습니다.
2. 일일 인텔리전스 파이프라인 (The Daily Intelligence Pipeline)
예약된 일일 작업은 크리에이티브 게놈을 성과 데이터(performance data)와 결합하여 다음 항목들을 사전 계산(precompute)합니다:
- 승리 및 패배 패턴 (Winning and losing patterns)
- 피로 곡선 (Fatigue curves)
- 경쟁사 격차 (Competitor gaps)
- 인사이트 요약 (An insight digest)
- 업데이트된 지식 베이스 (An updated knowledge base)
사용자가 채팅 인터페이스를 열 때쯤이면, 비용이 많이 드는 대부분의 분석은 이미 완료된 상태입니다.
에이전트는 질문을 받을 때마다 원시 데이터(raw data)로부터 계정 정보를 매번 새로 발견하지 않습니다. 구조화된 증거(structured evidence)에서 시작하여, 추가로 어떤 정보가 필요한지를 결정합니다.
3. 에이전트 런타임 (The Agent Runtime)
에이전트 런타임은 시스템의 대화형(interactive) 부분을 처리합니다.
모든 요청에 대해 다음을 수행합니다:
- 사용자의 목표를 해석(interpret)합니다.
- 계정 범위의 컨텍스트(account-scoped context)를 구축합니다.
- 관련 메모리(memories)와 지식(knowledge)을 검색(retrieve)합니다.
- 질문에 답하는 데 필요한 도구(tools)를 선택합니다.
- 제어된 하네스(controlled harness)를 통해 해당 도구들을 실행합니다.
- 결과를 관찰(observe)하고 추가적인 도구 호출이 필요한지 결정합니다.
- 근거 있는 답변(grounded answer) 또는 크리에이티브 브리프(creative brief)를 생성합니다.
- 적절한 경우 재사용 가능한 지식을 다시 기록(write back)합니다.
에이전트는 정책(policies), 컨텍스트 조립(context assembly), 메모리(memory), 도구(tools), 재시도(retries), 트레이싱(tracing), 그리고 출력 검증(output validation)을 갖춘 실행 시스템입니다.

에이전트 런타임(agent runtime)을 더 깊이 파고들기 전에, 배경이 되는 메커니즘의 세 가지 구성 요소를 고려해 볼 가치가 있습니다.
1. 모델에 비용을 두 번 지불하지 마세요
비디오 추출(Video extraction)은 시스템에서 가장 느리고 비용이 많이 드는 작업입니다.
추출을 시작하기 전에, 워커(worker)는 다음과 같이 질문합니다:
내가 이미 이 정확한 크리에이티브(creative)를 분석했는가?
모든 크리에이티브에는 결정론적 핑거프린트(deterministic fingerprint)가 할당됩니다:
sha256("creative_id | video_id | body | title")
Meta 크리에이티브는 사실상 불변(immutable)입니다. 광고를 편집하면 새로운 creative_id가 생성되므로, ID를 크리에이티브 정체성의 일부로 취급할 수 있습니다.
해시(hash)에는 원본 소스 필드만 포함됩니다.
그 후 워커는 세 가지 가능한 경로를 따릅니다:
- 동일한 핑거프린트 및 동일한 광고: 작업 건너뛰기
- 동일한 핑거프린트지만 다른 광고: 모델 호출을 다시 하지 않고 기존 게놈(genome)을 복사
- 일치하는 핑거프린트 없음: 전체 추출 실행
두 번째 경우가 가장 큰 비용 절감을 가져옵니다.
동일한 크리에이티브는 여러 광고, 광고 세트(ad sets) 또는 캠페인(campaigns)에서 자주 재사용됩니다. 핑거프린팅(fingerprinting)이 없다면 시스템은 동일한 미디어를 반복적으로 분석하게 될 것입니다.
핑거프린팅을 사용하면, 한 번의 모델 호출로 동일한 크리에이티브를 사용하는 모든 광고에 대응할 수 있습니다.
2. 작업 큐(Job Queue)는 그냥 Postgres입니다
느린 비동기 작업(asynchronous jobs)을 위한 명백한 선택지는 Celery, SQS 또는 RabbitMQ와 같은 시스템입니다.
저는 다음과 같은 Postgres 테이블을 사용했습니다:
FOR UPDATE SKIP LOCKED
Postgres는 이미 시스템의 기록 저장소(system of record)였으며, 이 접근 방식은 몇 가지 장점을 제공했습니다:
- 작업 점유(Job claims)가 트랜잭션(transactional)으로 처리됨
- 우선순위(Priority)가
ORDER BY로 구현됨 - 복구(Recovery)가 쿼리(query)로 표현됨
- 추가적인 브로커(broker) 인프라가 필요하지 않음
- 큐(Queue) 상태가 가시적이며 검사하기 쉬움
SKIP LOCKED가 핵심 메커니즘입니다.
두 작업자(worker)가 동시에 작업을 점유(claim)하려고 시도할 때, 각 작업자는 다른 작업자에 의해 이미 잠긴(locked) 행을 건너뜁니다. 따라서 작업자들은 동일한 행을 중복 처리하지 않고 서로 겹치지 않는 작업 집합을 받게 됩니다.
현재 시스템은 하나의 작업자 복제본(worker replica)으로 실행되고 있으므로, 아직 수평적 병렬성(horizontal parallelism)을 위해 이 기능을 사용하고 있지는 않습니다.
하지만 점유(claim) 로직은 이미 동시성 안전(concurrency-safe)합니다. 큐를 재설계하지 않고도 나중에 추가 작업자를 도입할 수 있습니다.
부하가 증가한 후에 사후 적용(retrofit)하는 것보다, 안전한 점유 의미론(claim semantics)을 한 번에 구축하는 것이 더 낫습니다.
지출 기반 우선순위 (Spend-Based Priority)
큐의 우선순위는 각 광고의 지난 30일간 지출액(trailing 30-day spend)을 기준으로 합니다.
즉, 작업자가 지출액이 가장 높은 크리에이티브(creatives)를 먼저 분석한다는 의미입니다.
여기에는 중요한 부수 효과가 있습니다. 배치(batch) 작업이 중단되거나 부분적으로만 완료되더라도, 완료된 부분은 여전히 가장 가치 있는 부분이 됩니다.
점유 중 시도 횟수 증가 (Attempts Are Incremented During the Claim)
임대(lease) 및 시도 횟수(attempt count)는 작업을 점유하는 데 사용되는 것과 동일한 트랜잭션 내에서 업데이트됩니다.
이는 애플리케이션이 실패를 기록하기 전에 작업이 작업자(worker)를 충돌(crash)시키는 경우에 중요합니다.
시도 횟수가 이미 증가했기 때문에, 해당 작업은 여전히 한 번의 재시도(retry)를 소모합니다. 결과적으로 작업은 무한 루프를 도는 대신 결국 데드 레터(dead-letter) 상태로 이동하게 됩니다.
3. 임대(Leases), 재시도(Retries), 그리고 우아한 폴백(Graceful Fallbacks)
각 작업은 작은 상태 머신(state machine)을 따릅니다:
queued -> leased -> done
실패 시, 다음 상태로 돌아갑니다:
queued
세 번의 시도 실패 후에는 다음 상태로 이동합니다:
dead
재생 가능한(replayable) 데드 레터 레코드가 유지되므로, 실패한 작업이 조용히 폐기되는 일은 없습니다.
임대(Lease)가 곧 타임아웃(Timeout)입니다
시스템에서 가장 단순한 실패 처리 메커니즘이 가장 유용한 메커니즘 중 하나이기도 합니다.
작업자가 다음과 같은 상황에 처하면 어떻게 될까요:
- OOM-kill(메모리 부족으로 인한 프로세스 종료)
- 예기치 않은 종료(Terminated unexpectedly)
- 네트워크 요청에서 멈춤(Stuck on a network request)
- 브라우저 프로세스에 의해 차단됨(Blocked by a browser process)
- 고장난 다운로드에서 영원히 대기함(Waiting forever on a broken download)
이러한 상황에서는 try/except 블록이 실행되지 않습니다. 작업자는 작업을 정리(clean up)할 기회를 전혀 얻지 못합니다.
이를 처리하기 위해, 모든 워커 사이클(worker cycle)은 만료된 임대(lease)를 다시 큐에 넣는(requeuing) 것으로 시작됩니다.
죽은 워커에 의해 점유된 작업은 leased 상태로 남아 있지만, 해당 작업의 leased_until 타임스탬프는 결국 과거의 시점으로 이동하게 됩니다.
다음 워커 사이클은 만료된 임대를 확인하고 해당 작업을 큐로 반환합니다.
임대 자체가 타임아웃(timeout) 역할을 수행하므로, 별도의 와치독(watchdog) 프로세스가 필요하지 않습니다.
대부분의 실패는 다음 두 가지 경로 중 하나로 수렴합니다:
- 애플리케이션이 예외(exception)를 포착하고 작업을 다시 큐에 넣음
- 애플리케이션이 사라지고, 임대가 만료되며, 다음 사이클이 작업을 다시 큐에 넣음
두 경로 모두 동일한 상태 머신(state machine)으로 돌아옵니다.
완전히 실패하는 대신 성능 저하(Degrade) 수용
재시도(Retries)는 일시적인 실패(transient failures)에는 유용하지만, 일부 입력값은 영구적으로 처리가 어려울 수 있습니다.
그러한 경우를 위해 시스템은 우아하게 성능을 저하시킵니다(degrades gracefully).
만약 비디오를 해석할 수 없다면, 워커는 대신 썸네일이나 훅 프레임(hook frame)을 분석하고 해당 게놈(genome)을 폴백 추출(fallback extraction)로 표시합니다.
결과는 불완전하겠지만, 부분적인 게놈이라도 아예 없는 것보다는 훨씬 유용할 때가 많습니다.
동일한 원칙이 모델 제공자에게도 적용됩니다. 선택 사항인 Claude 경로를 사용할 수 없거나 구성되지 않은 경우, 시스템은 투명하게 Gemini로 폴백(fallback)합니다.
멱등성(Idempotency)을 통한 안전한 재시도
재시도는 작업을 반복해도 상태를 손상시키지 않을 때에만 안전합니다.
두 가지 제약 조건이 이를 가능하게 합니다:
- 인큐잉(Enqueueing)은 고유 인덱스(unique index)에 의해 보호됩니다.
- 게놈 쓰기(Genome writes)는 업서트(upserts)를 사용합니다.
결과적으로, 작업을 실수로 두 번 실행하더라도 사실상 아무런 동작도 하지 않는(no-op) 상태가 됩니다.
여기서 멱등성(Idempotency)은 최적화 요소가 아닙니다. 이는 신뢰할 수 있는 재시도를 위한 전제 조건입니다.
계산 우선, 서술은 그다음
일일 인텔리전스 파이프라인(intelligence pipeline)은 시스템의 핵심 원칙이 가장 중요해지는 지점입니다.
모델은 특정 패턴이 통계적으로 유의미한지 여부를 결정하지 않습니다.
애플리케이션이 먼저 증거를 계산합니다.
각 패턴에 대해 시스템은 다음과 같은 값들을 계산합니다:
- 통합 ROAS (Pooled ROAS)
- 지출 가중 승률 (Spend-weighted win rate)
- 계정 기준 대비 리프트 (Lift relative to the account baseline)
- 표본 크기 (Sample size)
- 신뢰 구간 (Confidence intervals)
3개의 광고를 기반으로 한 패턴은 수백 개의 광고에 의해 뒷받침되는 패턴과 동일한 신뢰도로 제시되어서는 안 됩니다.
신뢰 구간 (Confidence interval)은 적은 표본 크기로 인한 우연한 결과 (small-sample flukes)가 강력한 신호 (strong signals)로 제시되는 것을 방지합니다.
이 값들이 계산된 후에야 모델이 이를 전달받아 읽기 쉬운 언어로 변환합니다.
동일한 원칙이 시스템 전반에 적용됩니다:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기