LINE Engineering — LLM에게 어디까지 맡길 것인가, 광고 분석 리포트 자동화
LY Corporation 기술 블로그에 9월 17일 올라온 「LLM에게 어디까지 맡길 것인가: AI 에이전트 기반 광고 분석 리포트 자동화」를 읽고 정리했다. 매일 도는 리포트 자동화에서 LLM에게 숫자를 맡기면 어떻게 깨지는지, 그걸 어디까지 코드로 되찾아 와야 하는지가 골자다. 앞서 다룬 LINE Tech-Verse 2026 참관기와 같은 조직에서 나온 실무 사례다. (이 글의 초안은 설치된 Hermes 에이전트가 작성했고, Claude가 검수 후 발행했다.)
TL;DR: 당일 데이터와 비즈니스 컨텍스트를 한 프롬프트에 몰아넣는 방식은 수치 오류, 중요 항목 누락, 불안정한 포맷, 얕은 해석으로 무너졌다. 팀은 계산·집계·정합성 검증을 코드로 빼고 LLM에는 해석과 문장 생성만 남겼다. 원인 탐색은 탐색 그래프로 범위를 제한한 ReAct 에이전트가 맡고, 결과는
driver_eligible·caution_only·monitoring_signal세 등급으로 나눠 섹션마다 다르게 흘려보낸다. 여기에 Langfuse 트레이싱과 정량·정성 평가 루브릭을 붙여 매일 돌릴 만한 품질을 만들었다.
단일 프롬프트가 무너진 네 가지 방식
처음에는 당일 집계 데이터와 비즈니스 컨텍스트를 하나의 프롬프트에 넣고 리포트 전체를 한 번에 뽑았다. 결과물만 보면 그럴듯했지만 매일 돌리자 네 군데가 어긋났다.
수치 오류와 집계 누락. 숫자 계산을 LLM에 맡겼더니 전체 매출 변화와 원인별 기여도를 같은 기준으로 집계하고 세부 항목 합이 전체와 맞는지 확인하는 일을 안정적으로 해내지 못했다. DoD/MoM/YoY 변화율과 반올림 결과가 실행마다 달라졌다.
중요 항목 누락. 긴 컨텍스트 안에서 매출 기여도가 큰 항목이 아예 언급되지 않는 일이 생겼다. 더 곤란한 건 생성 결과만 봐서는 무엇이 빠졌는지 알 수 없다는 점이었다.
불안정한 포맷. 섹션 순서, 불릿 개수, 금지 표현 같은 가드레일이 매번 똑같이 지켜지지 않았다. 매일 도는 시스템에서는 확률이 낮은 형식 오류도 결국 반복해서 터진다.
얕은 해석. 전체 증감 요약까지는 만들었지만 어느 상품과 광고주가 그 변화를 주도했는지로는 이어지지 않았다. 실무자는 리포트를 읽고 다시 원천 데이터를 열어야 했다.
원문 근거
"리포트에 필요한 것은 단순한 숫자가 아니라 전체 집계에서 어떤 항목이 얼마나 기여했는지 확인된 근거였습니다. 이런 문제는 컨텍스트의 양만 줄여서 해결할 문제가 아니라, 계산과 중요 항목 후보 선정, 커버리지 확인을 생성 과정 밖에서 코드로 수행해야 해결되는 문제였습니다."
컨텍스트를 줄여서 될 문제가 아니었다는 진단이 핵심이다. 여기서 LLM이 잘하는 일과 신뢰성이 반드시 보장돼야 하는 일을 갈라놓자는 설계 원칙이 나왔다.
계산과 해석을 가른다
역할 분담은 이렇게 정리됐다. 코드는 DoD/MoM/YoY 변화 계산, 상위 변동 항목 산출, 후보 선정(현재 매출·변화량·선정 이유를 함께 기록), 정합성 검증을 맡는다. LLM은 그렇게 확정된 수치를 받아 비즈니스 관점의 문장을 쓰고, 변화의 의미와 우선순위, 후속 확인 사항을 구성한다.
리포트는 Executive Snapshot, Key Drivers(OA/DA), Trend Diagnosis(OA/DA), Opportunity/Risk Signals 여섯 섹션으로 나뉜다. 섹션 생성에는 OpenAI GPT-5.4를 reasoning effort = high로 쓰고, ThreadPoolExecutor로 여러 섹션을 동시에 호출한다. 검증에서 문제가 나오면 그 섹션만 다시 만든다.
원문 근거
"리포트를 섹션 단위로 나눠 병렬로 생성합니다. 섹션 생성에는 OpenAI GPT-5.4 모델을 reasoning effort = high 설정으로 사용하고, ThreadPoolExecutor 로 여러 섹션을 동시에 호출합니다."
숫자가 문장이 되기까지의 경로는 이렇다.
코드로 계산한 결과
→ Display 광고 업종 A: 현재 매출 5.68M JPY, MoM -5.13M JPY, YoY -1.61M JPY
코드 기반 후보 선정
→ 업종별 MoM 절대 변화가 큰 항목으로 탐지 → 영향 큰 항목으로 분류
→ [주요 변동 요인: Display 광고]에 우선 배정
섹션 프롬프트에 들어가는 사실
→ [HIGH IMPACT] [주요 변동 요인: Display 광고] [Display 광고 업종] 업종 A
(현재 5.68M JPY, MoM -5.13M JPY, YoY -1.61M JPY, 선정 이유: large_mom_diff)
LLM 생성 결과
→ "업종 A의 월 누적 매출은 5.68M JPY로, 전월 같은 기간보다 5.13M JPY 감소했습니다."
문장에 박힌 수치는 LLM이 원본에서 찾아 더한 값이 아니다. 분석 단계가 비교 기준일에 맞춰 계산하고 후보 선정 단계가 영향도와 함께 확정해 둔 사실이다.
고정 DAG 대신 탐색 그래프
원인 분석 경로는 처음에 고정 DAG로 짰다. 그런데 그날 데이터에 따라 다음에 확인할 대상이 달라졌고, 가능한 경로를 전부 조건으로 박으면 DAG가 금세 불어났다. 새 패턴이 나올 때마다 흐름을 덧붙여야 하는 것도 부담이었다.
그래서 구조를 바꿨다. 사전 집계 KPI 데이터를 받아 에이전트가 Trino 쿼리로 추가 탐색을 하고, 그 결과로 섹션별 리포트를 만든다. 에이전트는 OpenAI Python SDK의 tool calling으로 분석 함수 다섯 개를 호출한다.
| Tool | 역할 |
|---|---|
drill_down |
매출을 더 세부 분석 단위로 분해해 주요 기여자 반환 |
compare_pattern |
기간별 추세를 신규/성장/하락/구조적 패턴으로 분류 |
entity_context |
최초 매출일, 업종 등 분석 대상 메타데이터 조회 |
peer_comparison |
같은 그룹 평균과 분석 대상 비교 |
volume_decompose |
매출 변화를 단가 요인과 물량 요인으로 분해 |
에이전트를 DB 전체에 풀어놓으면 의미가 다른 식별자를 엮거나 쓸모없는 차원을 뒤지는 일이 생긴다. 그래서 비즈니스적으로 유효한 분석 차원 사이의 관계만 탐색 그래프로 정의했다.
LINE OA 광고: 전체 매출 → 상품군 → 세부 상품, 업종, 에이전시 → 계정·광고주
Display 광고: 전체 매출 → 광고 판매 유형 → 업종, 캠페인 속성, 채널 → 광고주·상품
각 노드는 사용할 데이터 소스와 다음에 확인할 수 있는 분석 단위를 정해 둔다. 어느 길로 갈지는 데이터를 보고 에이전트가 고르되, 갈 수 있는 범위 자체는 시스템이 묶어 둔다.
원문 근거
"각 노드는 사용할 데이터 소스와 다음에 확인할 수 있는 분석 단위를 정의합니다. 어떤 경로를 선택할지는 데이터에 따라 에이전트가 결정하지만, 확인할 수 있는 범위는 시스템이 제한합니다."
가드레일도 몇 겹이다. 같은 tool과 파라미터 조합은 seen_calls 집합으로 중복 호출을 막는다. 변동 요인별 분석 횟수(MAX_QUERIES)와 전체 실행 시간에 상한을 둔다. Trino 쿼리가 실패하거나 결과가 비면 분석을 통째로 멈추는 대신 ok/no_data/error 상태를 돌려줘서 모델이 다른 차원을 고르게 한다.
에이전트가 찾았다고 원인은 아니다
큰 변화를 찾아냈다고 바로 원인으로 쓰면 곤란하다. 전체는 늘었는데 세부는 줄어드는 방향 불일치, 설명 비중 부족, 매출 인식 시점 차이 같은 것들이 과도한 인과 주장을 만든다. 그래서 근거에 등급을 매긴다.
| 등급 | 의미 | 리포트 반영 |
|---|---|---|
driver_eligible |
방향과 기여 관계가 맞아 주요 변동 요인의 설명 근거로 쓸 수 있음 | 원인으로 사용 |
caution_only |
움직임은 보이나 불일치나 데이터 제약이 있음 | 주의사항으로만 |
monitoring_signal |
변화는 관측됐으나 원인 판단에는 근거 부족 | 신호로만 기록 |
분류는 규칙 기반이다. 각 분석 단계의 변화 방향과 기여도를 상위 단계와 견줘 보고, 비즈니스 규칙과 데이터 제약을 적용해 자동으로 등급을 매긴다.
원문 근거
"따라서 에이전트가 찾은 분석 결과를 그대로 원인으로 사용하지 않고, 리포트에 반영하기 전에 근거 등급화(evidence grading) 단계를 거칩니다. 규칙 기반 로직으로 각 분석 단계의 변화 방향과 기여도를 상위 단계와 비교합니다."
섹션마다 다른 컨텍스트를 준다
검증을 통과한 근거라도 모든 섹션에 똑같이 넘기면 컨텍스트가 오염되고, 내용이 겹치고, 아직 확정되지 않은 신호가 너무 일찍 노출된다. 그래서 용도별로 세 갈래로 쪼갰다. 인과 컨텍스트는 원인으로 쓸 수 있는지 판단하는 근거로 Executive Snapshot과 Key Drivers에, 통계 분석은 수치와 순위와 매출 흐름 확인용으로 Trend Diagnosis에, 과금 방식이나 데이터 해석 주의점 같은 비즈니스 지식은 Opportunity/Risk Signals에 간다.
업종 A의 대형 캠페인이 끝난 사건 하나가 섹션마다 어떻게 달리 적히는지 보면 감이 온다.
| 섹션 | 컨텍스트 전략 | 표기 예시 |
|---|---|---|
| Executive Snapshot | 전체 변화 + driver_eligible 상위 원인만 |
“DA MTD 매출 88.5M JPY, 전일 대비 -4.1M JPY 감소. 업종 A 대형 캠페인 종료가 하락 대부분 설명” |
| Key Drivers | driver_eligible 원인 + 통계 분석으로 규모·기여도 확인 |
“업종 A가 전일 대비 -3.6M JPY로 DA 하락 주도. 광고주 B 캠페인 집행 종료가 확인된 원인” |
| Trend Diagnosis | 전일/전월/전년 흐름 + 상품별 순위 (인과 컨텍스트 미전달) | “업종 A MTD 매출 MoM -8%로 둔화 흐름 지속. 예산 집행량 큰 캠페인 수 감소” |
| Opportunity/Risk | 확정 변화 + caution_only/monitoring_signal을 신호·조건·후속으로 구분 |
“위험: 광고주 B 캠페인 종료로 다음 주 DA 집행 공백 예상. 후속 집행 여부 확인 필요” |
Trend Diagnosis에 인과 컨텍스트를 일부러 주지 않는 선택이 눈에 띈다. 흐름을 읽는 섹션이 원인까지 단정하지 않게 막는 장치다.
측정할 수 있어야 고칠 수 있다
팀 내부 리뷰와 비즈니스 담당자, 세일즈 조직에서 나온 피드백을 평가 항목과 판정 기준으로 정리해 Evaluation rubric을 만들었다.
정량 평가는 금액 표기, 섹션 구조, 불릿 개수, 문장 길이, 내부 용어 노출 같은 것을 규칙으로 보고 정상/누락/확인 필요로 가른다. 정성 평가는 도메인 정확성, 분석 우선순위, 인과 설명의 타당성, 모니터링 항목의 적절성, 비즈니스 유용성을 같은 rubric으로 pass/needs-review/fail 판정한다. 앞쪽이 최소 운영 기준을 지키는 안전장치라면, 뒤쪽은 실제로 의사결정에 쓸모가 있는지를 본다. 금액과 구조가 다 맞아도 중요한 변화를 설명하지 못하거나 근거 없이 원인을 단정하면 좋은 리포트가 아니다.
문제가 어디서 났는지 알려면 최종 결과만 봐서는 안 된다. 그래서 중간 계산, 에이전트의 iteration과 tool call, 섹션 생성, 평가 결과까지 하나의 실행 단위로 묶어 Langfuse trace에 연결했다. trace에는 리포트 날짜, 코드 버전, 모델, reasoning effort, report mode가 함께 기록된다. 덕분에 어느 단계가 실패했는지 짚고, 서로 다른 프롬프트나 에이전트 버전의 결과를 같은 조건에서 비교하고, 데이터 분석 규칙과 컨텍스트 구성과 프롬프트 중 무엇을 고칠지 판단할 수 있다.
생성 시점에는 리포트와 trace를 저장하고, 평가는 저장된 결과를 같은 기준으로 다시 채점한다. 두 결과는 trace의 버전 정보로 이어지므로 프롬프트나 정책을 바꾸기 전후의 점수를 나란히 놓고 볼 수 있다.
남는 교훈 네 가지
원문이 정리한 결론은 이렇다.
- LLM과 코드의 책임 범위를 명확히 가른다. 계산·집계·정합성 검증은 코드가, 해석과 문장 생성은 LLM이 맡는다.
- 에이전트의 자율성은 조정 대상이다. 탐색 그래프와 반복 차단, 횟수 상한으로 범위를 좁히면 불필요한 조회와 잘못된 추론이 줄면서도 유연성은 남는다.
- 컨텍스트 범위가 출력 품질을 좌우한다. 목적에 맞는 정보만 주면 과도한 해석이 줄고 토큰도 아낀다.
- 측정할 수 있어야 개선을 검증할 수 있다. 실행 결과와 과정을 버전과 함께 trace로 남기고, 사람이 정한 rubric으로 변경 전후를 같은 조건에서 채점한다.
RAG든 에이전트든 “LLM에 맡길 수 있는 일”의 경계를 실측으로 그어 나간 사례라 읽을 값이 있다. 특히 수치를 프롬프트 밖으로 빼낸 결정은 매일 도는 자동화라면 대부분 따라 할 만하다.
참고 자료
- 원문: LLM에게 어디까지 맡길 것인가: AI 에이전트 기반 광고 분석 리포트 자동화 (2026-09-17)
- AI를 전제로 다시 설계하다, Tech-Verse 2026 참관기
- 장애 Alert의 원인을 스스로 찾다: SRE Observer 개발기
- LLM Wiki: 코드 기준으로 자동 최신화되는 도메인 지식 SSOT 만들기
- 타이틀 사진: Unsplash