🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Context Compression 전략 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 27. · 5 Views

Context Compression 전략 완벽 가이드

AI 에이전트의 장기 세션에서 컨텍스트 윈도우를 효율적으로 관리하는 압축 전략을 다룹니다. Anchored Summarization, Opaque Compression, Regenerative Summary 등 실무에서 바로 적용할 수 있는 기법들을 배워봅니다.


목차

  1. 장기_세션의_도전_24시간_에이전트
  2. Anchored_Iterative_Summarization
  3. Opaque_Compression_99퍼센트_압축률
  4. Regenerative_Full_Summary
  5. Tokens_per_Task_지표
  6. 평가_프레임워크_구축하기

1. 장기 세션의 도전 24시간 에이전트

김개발 씨는 회사에서 AI 에이전트를 개발하고 있습니다. 처음에는 잘 작동하던 에이전트가 몇 시간만 지나면 갑자기 이상한 대답을 하기 시작했습니다.

"분명히 아까 말했잖아요!"라고 외쳐봐도 에이전트는 멀뚱멀뚱 바라볼 뿐이었습니다.

컨텍스트 윈도우란 AI 모델이 한 번에 기억할 수 있는 텍스트의 양입니다. 마치 책상 위에 올려놓을 수 있는 서류의 양이 정해져 있는 것과 같습니다.

장기 세션에서는 이 한계를 효율적으로 관리하는 것이 핵심 과제가 됩니다.

다음 코드를 살펴봅시다.

# 컨텍스트 윈도우 사용량 모니터링
class ContextMonitor:
    def __init__(self, max_tokens=128000):
        self.max_tokens = max_tokens
        self.current_tokens = 0
        self.warning_threshold = 0.8

    def add_message(self, message, token_count):
        self.current_tokens += token_count
        usage_ratio = self.current_tokens / self.max_tokens

        if usage_ratio > self.warning_threshold:
            # 경고: 컨텍스트 압축 필요
            return {"status": "compress_needed", "usage": usage_ratio}
        return {"status": "ok", "usage": usage_ratio}

김개발 씨는 입사 1년 차 AI 엔지니어입니다. 최근 회사에서 24시간 작동하는 고객 상담 에이전트를 개발하라는 미션을 받았습니다.

처음에는 자신만만했습니다. GPT-4의 128K 컨텍스트 윈도우면 충분하지 않을까요?

첫 번째 테스트는 성공적이었습니다. 에이전트는 고객의 질문에 정확하게 답변했습니다.

하지만 3시간이 지나자 문제가 시작되었습니다. 에이전트가 고객이 처음에 말한 주문 번호를 잊어버린 것입니다.

"아니, 128K 토큰이면 엄청 많은 양 아닌가요?" 김개발 씨는 의아했습니다. 선배 개발자 박시니어 씨가 다가와 화면을 살펴봤습니다.

"김개발 씨, 128K 토큰이 많아 보이지만, 실제 대화에서는 금방 차버려요. 특히 코드나 로그를 주고받으면 더 빨리 소진되죠." 그렇다면 컨텍스트 윈도우란 정확히 무엇일까요?

쉽게 비유하자면, 컨텍스트 윈도우는 마치 책상 위의 공간과 같습니다. 아무리 큰 책상이라도 올려놓을 수 있는 서류의 양에는 한계가 있습니다.

새 서류를 올리려면 기존 서류를 치워야 합니다. AI 모델도 마찬가지입니다.

새로운 대화 내용이 들어오면 오래된 내용은 밀려나게 됩니다. 문제는 여기서 끝나지 않습니다.

128K 토큰 전체를 사용할 수 있는 것도 아닙니다. 실제로는 시스템 프롬프트, 도구 정의, 응답 공간 등이 상당 부분을 차지합니다.

실질적으로 대화에 사용할 수 있는 공간은 생각보다 적습니다. 더 큰 문제는 비용입니다.

GPT-4 기준으로 128K 토큰을 매번 처리하면 한 번의 API 호출에도 상당한 비용이 발생합니다. 24시간 운영하는 서비스라면 비용이 기하급수적으로 늘어납니다.

그래서 등장한 것이 바로 Context Compression, 즉 컨텍스트 압축 전략입니다. 컨텍스트 압축은 중요한 정보는 유지하면서 불필요한 부분을 줄이는 기술입니다.

마치 회의록을 작성할 때 모든 발언을 기록하는 것이 아니라 핵심 결정 사항만 정리하는 것과 같습니다. 위 코드를 살펴보면, ContextMonitor 클래스가 현재 토큰 사용량을 추적합니다.

사용량이 80%를 넘으면 압축이 필요하다는 신호를 보냅니다. 이 시점에 적절한 압축 전략을 적용해야 합니다.

실제 현업에서는 컨텍스트 관리가 AI 서비스의 성패를 좌우합니다. 네이버, 카카오 같은 대형 서비스들도 이 문제와 씨름하고 있습니다.

단순히 큰 모델을 쓰는 것이 아니라, 효율적으로 컨텍스트를 관리하는 것이 경쟁력입니다. 김개발 씨는 고개를 끄덕였습니다.

"그러면 어떻게 압축해야 하나요?" 박시니어 씨가 미소 지었습니다. "좋은 질문이에요.

이제부터 세 가지 핵심 전략을 알려드릴게요."

실전 팁

💡 - 컨텍스트 사용량을 실시간으로 모니터링하는 시스템을 구축하세요

  • 압축 임계값은 보통 70-80% 사용량에서 설정합니다
  • 시스템 프롬프트와 도구 정의도 토큰 계산에 포함해야 합니다

2. Anchored Iterative Summarization

김개발 씨가 첫 번째로 배운 전략은 Anchored Iterative Summarization입니다. 이름이 어렵게 느껴지지만, 실제로는 우리가 일상에서 늘 하는 것과 비슷합니다.

마치 두꺼운 책을 읽고 핵심 내용만 노트에 정리하는 것처럼요.

Anchored Iterative Summarization은 대화 내용을 주기적으로 요약하되, 중요한 앵커 포인트는 원본 그대로 유지하는 전략입니다. 모든 것을 압축하는 것이 아니라, 핵심 정보는 보존하면서 나머지만 요약합니다.

다음 코드를 살펴봅시다.

# Anchored Iterative Summarization 구현
class AnchoredSummarizer:
    def __init__(self, llm_client):
        self.llm = llm_client
        self.anchors = []  # 절대 압축하지 않을 핵심 정보
        self.summary = ""

    def add_anchor(self, info, anchor_type):
        # 중요 정보를 앵커로 등록
        self.anchors.append({
            "type": anchor_type,  # "user_goal", "decision", "error"
            "content": info,
            "timestamp": datetime.now()
        })

    def summarize(self, conversation_history):
        # 앵커를 제외한 나머지 대화만 요약
        non_anchor_content = self.extract_non_anchors(conversation_history)
        new_summary = self.llm.summarize(non_anchor_content)
        self.summary = f"{self.summary}\n{new_summary}"
        return self.build_compressed_context()

박시니어 씨가 화이트보드에 그림을 그리기 시작했습니다. "김개발 씨, 회의할 때 회의록 작성해본 적 있죠?" 김개발 씨가 고개를 끄덕였습니다.

"네, 인턴 때 매번 작성했어요." "그때 모든 말을 다 받아 적었나요?" "아니요, 중요한 결정 사항이랑 액션 아이템만 정리했어요." 박시니어 씨가 환하게 웃었습니다. "바로 그거예요!

Anchored Iterative Summarization이 정확히 그 방식입니다." 이 전략의 핵심은 앵커(Anchor) 개념입니다. 앵커란 절대로 요약하거나 압축해서는 안 되는 핵심 정보입니다.

마치 배를 고정시키는 닻처럼, 앵커는 전체 대화의 맥락을 고정시켜 줍니다. 어떤 정보가 앵커가 될까요?

크게 세 가지 유형이 있습니다. 첫째, 사용자의 목표입니다.

"쇼핑몰 결제 시스템을 구축해 주세요"라는 최초 요청은 세션이 끝날 때까지 유지되어야 합니다. 이것을 잊으면 에이전트가 엉뚱한 방향으로 갈 수 있습니다.

둘째, 중요한 결정 사항입니다. "PostgreSQL을 사용하기로 했습니다"라는 결정은 이후 모든 작업에 영향을 미칩니다.

이것을 잊으면 갑자기 MySQL 코드를 작성하는 황당한 상황이 발생합니다. 셋째, 에러 정보입니다.

사용자가 보고한 에러 메시지나 버그 상황은 문제 해결의 핵심 단서입니다. 이것이 사라지면 같은 실수를 반복하게 됩니다.

위 코드에서 add_anchor 메서드는 이런 중요 정보를 앵커로 등록합니다. summarize 메서드는 앵커가 아닌 나머지 대화 내용만 요약합니다.

실제로 이 전략을 적용하면 어떤 효과가 있을까요? 김개발 씨의 에이전트를 예로 들어보겠습니다.

고객이 "주문번호 A12345의 배송 상태를 확인해 주세요"라고 말했습니다. 이 주문번호는 앵커로 등록됩니다.

이후 고객과 10분간 이런저런 대화를 나눠도, 주문번호 A12345는 절대 사라지지 않습니다. 반면 "네, 확인해 드리겠습니다", "잠시만 기다려 주세요" 같은 대화는 요약됩니다.

"고객 요청 확인 후 조회 진행"이라는 한 줄로 압축될 수 있습니다. 이 전략의 장점은 점진적 압축이 가능하다는 것입니다.

한 번에 모든 것을 요약하는 것이 아니라, 주기적으로 조금씩 요약합니다. 덕분에 갑자기 중요한 정보가 사라지는 사고를 방지할 수 있습니다.

주의할 점도 있습니다. 앵커를 너무 많이 등록하면 압축 효과가 떨어집니다.

반대로 너무 적게 등록하면 중요한 맥락이 사라질 수 있습니다. 적절한 균형을 찾는 것이 중요합니다.

김개발 씨가 물었습니다. "그러면 보통 앵커는 몇 개 정도가 적당한가요?" 박시니어 씨가 답했습니다.

"경험상 전체 컨텍스트의 10-20% 정도가 앵커로 유지되는 것이 좋아요. 너무 적으면 맥락을 잃고, 너무 많으면 압축 효과가 없어요."

실전 팁

💡 - 앵커 유형을 명확히 분류하세요: 목표, 결정, 에러, 제약조건 등

  • 앵커가 전체 컨텍스트의 10-20%를 넘지 않도록 관리하세요
  • 요약은 LLM을 활용하되, 앵커 추출은 규칙 기반으로 하는 것이 안정적입니다

3. Opaque Compression 99퍼센트 압축률

김개발 씨가 두 번째로 배운 전략은 충격적이었습니다. 99% 이상의 압축률이라니요!

처음에는 믿기 어려웠습니다. 하지만 박시니어 씨가 보여준 데모를 보고 나서 생각이 완전히 바뀌었습니다.

Opaque Compression은 사람이 읽을 수 없는 형태로 정보를 극도로 압축하는 전략입니다. LLM이 해석할 수 있는 특수한 토큰 시퀀스로 변환하여 99% 이상의 압축률을 달성합니다.

마치 암호문처럼 보이지만, AI는 완벽하게 이해합니다.

다음 코드를 살펴봅시다.

# Opaque Compression 개념적 구현
class OpaqueCompressor:
    def __init__(self, encoder_model):
        self.encoder = encoder_model
        self.compression_cache = {}

    def compress(self, content):
        # 긴 텍스트를 압축된 벡터 표현으로 변환
        compressed = self.encoder.encode(content)
        # 결과는 사람이 읽을 수 없는 토큰 시퀀스
        # 예: "<|ctx_0x7f3a|><|ctx_0x8b2c|>..."
        opaque_tokens = self.vectorize_to_tokens(compressed)

        compression_ratio = len(content) / len(opaque_tokens)
        print(f"압축률: {compression_ratio:.1f}x")
        return opaque_tokens

    def decompress_for_llm(self, opaque_tokens, query):
        # LLM이 압축된 컨텍스트를 이해하고 응답
        return self.encoder.decode_with_query(opaque_tokens, query)

박시니어 씨가 화면에 이상한 문자열을 보여줬습니다. "<|ctx_0x7f3a|><|ctx_0x8b2c|><|ctx_0x9e1d|>" 김개발 씨는 당황했습니다.

"이게 뭔가요? 암호문인가요?" 박시니어 씨가 웃으며 설명했습니다.

"이건 원래 5000자짜리 대화 내용이에요. 지금 50자도 안 되는 것으로 압축되어 있죠." 이것이 바로 Opaque Compression의 위력입니다.

쉽게 비유하자면, Opaque Compression은 마치 압축 파일과 같습니다. ZIP 파일을 메모장으로 열면 이상한 문자만 보이지만, 압축 프로그램으로 열면 완벽하게 복원됩니다.

Opaque Compression도 마찬가지입니다. 사람 눈에는 의미 없는 토큰이지만, LLM에게는 완전한 정보입니다.

이 기술의 원리는 잠재 공간(Latent Space) 압축입니다. LLM은 텍스트를 처리할 때 내부적으로 고차원 벡터로 변환합니다.

Opaque Compression은 이 벡터 표현을 직접 저장하고 전달합니다. 중간 과정인 텍스트를 건너뛰는 것입니다.

99%라는 압축률이 과장이 아닙니다. 실제 연구 결과에 따르면, 10만 토큰의 대화 내용을 수백 개의 특수 토큰으로 압축할 수 있습니다.

비용 절감 효과가 어마어마합니다. 하지만 이 전략에는 중요한 주의사항이 있습니다.

첫째, 디버깅이 어렵습니다. 압축된 내용을 사람이 확인할 수 없기 때문에, 문제가 생겼을 때 원인을 파악하기 힘듭니다.

"왜 에이전트가 저런 답을 했지?"라는 질문에 답하기 어려워집니다. 둘째, 모델 의존성이 높습니다.

특정 LLM에 맞춰 압축된 토큰은 다른 모델에서 작동하지 않을 수 있습니다. GPT-4로 압축한 컨텍스트를 Claude에서 사용하려면 다시 처리해야 합니다.

셋째, 정보 손실 가능성이 있습니다. 극단적인 압축은 일부 세부 정보를 잃을 수 있습니다.

중요한 정보가 누락되면 에이전트의 응답 품질이 떨어집니다. 그래서 실무에서는 Opaque Compression을 선택적으로 적용합니다.

모든 대화에 적용하는 것이 아니라, 정말 오래된 히스토리나 덜 중요한 부분에만 사용합니다. 최근 대화나 앵커 정보는 원본 텍스트로 유지합니다.

위 코드를 보면, compress 메서드가 텍스트를 opaque 토큰으로 변환합니다. decompress_for_llm 메서드는 LLM이 쿼리와 함께 압축된 컨텍스트를 해석하도록 합니다.

김개발 씨가 물었습니다. "그러면 실제로 이걸 쓰는 회사가 있나요?" 박시니어 씨가 답했습니다.

"물론이죠. 특히 비용에 민감한 대규모 서비스에서 연구하고 있어요.

아직 프로덕션에 완전히 적용한 사례는 많지 않지만, 점점 발전하고 있는 분야예요." 현재 이 기술은 아직 연구 단계에 있는 부분이 많습니다. 하지만 컨텍스트 비용이 AI 서비스의 큰 부담인 만큼, 앞으로 더욱 중요해질 전략입니다.

실전 팁

💡 - Opaque Compression은 고급 기법으로, 먼저 Anchored Summarization을 충분히 익힌 후 시도하세요

  • 디버깅을 위해 원본 텍스트를 별도 로그로 보관하는 것이 좋습니다
  • 모델 업그레이드 시 압축된 컨텍스트의 호환성을 반드시 테스트하세요

4. Regenerative Full Summary

세 번째 전략을 배우면서 김개발 씨는 발상의 전환을 경험했습니다. 지금까지는 기존 내용을 어떻게 줄일까만 고민했는데, 이번에는 완전히 다른 접근법이었습니다.

아예 새로 만들면 어떨까요?

Regenerative Full Summary는 컨텍스트가 한계에 도달했을 때, 기존 대화를 완전히 새로운 요약본으로 재생성하는 전략입니다. 점진적 요약이 아닌 전체 재구성으로, 더 깔끔하고 일관된 컨텍스트를 만들어냅니다.

다음 코드를 살펴봅시다.

# Regenerative Full Summary 구현
class RegenerativeSummarizer:
    def __init__(self, llm_client):
        self.llm = llm_client

    def regenerate_context(self, full_history, current_goal):
        prompt = f"""
        다음 대화 히스토리를 분석하여 새로운 컨텍스트 문서를 생성하세요.

        현재 목표: {current_goal}

        포함해야 할 섹션:
        1. [배경] 사용자의 원래 요청과 목표
        2. [진행상황] 지금까지 완료된 작업
        3. [결정사항] 내려진 주요 결정들
        4. [현재상태] 현재 작업 중인 내용
        5. [다음단계] 예정된 작업

        대화 히스토리:
        {full_history}
        """
        return self.llm.generate(prompt)

박시니어 씨가 비유를 들어 설명했습니다. "김개발 씨, 방 청소할 때 어떻게 해요?" 김개발 씨가 생각했습니다.

"음, 보통 조금씩 정리하죠. 책상 정리하고, 옷 정리하고..." "그런데 가끔은 방이 너무 어질러져서 조금씩 정리하는 게 의미 없을 때가 있잖아요.

그럴 때는요?" "아, 그럴 때는 아예 전부 다 빼고 새로 정리해요!" 박시니어 씨가 손가락을 튕겼습니다. "바로 그거예요!

Regenerative Full Summary가 정확히 그 방식이에요." Anchored Summarization이 점진적 청소라면, Regenerative Summary는 대청소입니다. 기존 컨텍스트를 완전히 버리고, 처음부터 새로운 구조로 재구성합니다.

왜 이런 방식이 필요할까요? 점진적 요약을 반복하면 요약의 요약이 만들어집니다.

A를 요약해서 B가 되고, B를 요약해서 C가 됩니다. 이 과정에서 정보가 조금씩 왜곡되거나 누락될 수 있습니다.

마치 전화기 게임처럼요. 또한 점진적 요약은 구조가 일관되지 않습니다.

처음에는 시간순으로 정리되었다가, 나중에는 주제별로 섞이고, 결국 뒤죽박죽이 됩니다. 이런 컨텍스트는 LLM도 해석하기 어렵습니다.

Regenerative Summary는 이런 문제를 해결합니다. 원본 대화 전체를 한 번에 분석해서, 일관된 구조의 새 문서를 생성합니다.

위 코드를 보면, regenerate_context 메서드가 정해진 섹션 구조로 컨텍스트를 재생성합니다. 배경, 진행상황, 결정사항, 현재상태, 다음단계라는 다섯 개 섹션으로 정리됩니다.

이 구조의 장점은 명확함입니다. LLM이 "사용자의 목표가 뭐였지?"라는 질문에 답할 때, [배경] 섹션만 보면 됩니다.

"지금 뭘 하고 있지?"는 [현재상태] 섹션에 있습니다. 실제 적용 사례를 살펴보겠습니다.

개발 에이전트가 쇼핑몰 시스템을 구축하고 있습니다. 5시간 동안 대화하면서 데이터베이스 설계, API 개발, 프론트엔드 작업을 진행했습니다.

컨텍스트가 80%를 넘어섰습니다. 이때 Regenerative Summary를 실행합니다.

결과는 다음과 같습니다: [배경] 사용자는 중소규모 의류 쇼핑몰 시스템 구축을 요청함. 예산 제약으로 서버리스 아키텍처 선호.

[진행상황] PostgreSQL 스키마 설계 완료. 상품, 주문, 회원 테이블 구축.

API 엔드포인트 15개 중 12개 구현 완료. [결정사항] 결제는 토스페이먼츠 사용.

이미지 저장은 S3. 인증은 JWT 방식.

[현재상태] 장바구니 API 구현 중. 수량 변경 로직에서 재고 검증 이슈 발생.

[다음단계] 장바구니 완료 후 결제 연동 예정. 5시간의 대화가 깔끔한 문서 하나로 정리되었습니다.

이 문서만 있으면 새로운 세션에서도 바로 작업을 이어갈 수 있습니다. 주의할 점은 타이밍입니다.

Regenerative Summary는 비용이 많이 듭니다. 전체 히스토리를 다시 처리해야 하니까요.

너무 자주 실행하면 오히려 비효율적입니다. 보통 컨텍스트가 임계점에 도달했을 때, 한 번씩 실행하는 것이 좋습니다.

실전 팁

💡 - Regenerative Summary는 컨텍스트 사용량이 70-80%에 도달했을 때 실행하세요

  • 섹션 구조는 프로젝트 특성에 맞게 커스터마이징하세요
  • 재생성된 요약은 별도로 저장해두면 세션 복구에 유용합니다

5. Tokens per Task 지표

세 가지 압축 전략을 배운 김개발 씨는 뿌듯했습니다. 하지만 박시니어 씨가 한 가지를 더 강조했습니다.

"전략만 알면 뭐해요. 측정할 수 있어야죠!" 그렇게 김개발 씨는 AI 에이전트의 효율성을 측정하는 핵심 지표를 배우게 되었습니다.

Tokens-per-Task는 에이전트가 하나의 작업을 완료하는 데 사용한 총 토큰 수를 측정하는 지표입니다. 압축 전략의 효과를 객관적으로 평가하고, 비용 최적화의 기준점을 제공합니다.

측정 없이는 개선도 없습니다.

다음 코드를 살펴봅시다.

# Tokens-per-Task 측정 시스템
class TokenMetrics:
    def __init__(self):
        self.tasks = {}

    def start_task(self, task_id, task_type):
        self.tasks[task_id] = {
            "type": task_type,
            "start_time": datetime.now(),
            "input_tokens": 0,
            "output_tokens": 0,
            "api_calls": 0
        }

    def record_api_call(self, task_id, input_tokens, output_tokens):
        self.tasks[task_id]["input_tokens"] += input_tokens
        self.tasks[task_id]["output_tokens"] += output_tokens
        self.tasks[task_id]["api_calls"] += 1

    def complete_task(self, task_id, success=True):
        task = self.tasks[task_id]
        total_tokens = task["input_tokens"] + task["output_tokens"]

        return {
            "task_type": task["type"],
            "total_tokens": total_tokens,
            "tokens_per_call": total_tokens / task["api_calls"],
            "success": success
        }

박시니어 씨가 대시보드 화면을 열었습니다. 그래프와 숫자들이 가득했습니다.

"김개발 씨, 우리 에이전트가 효율적인지 어떻게 알 수 있을까요?" 김개발 씨가 생각했습니다. "음...

응답 속도요? 아니면 사용자 만족도?" "그것도 중요하죠.

하지만 비용 관점에서는 Tokens-per-Task가 핵심이에요." Tokens-per-Task는 말 그대로 하나의 작업을 완료하는 데 사용된 토큰 수입니다. 마치 자동차의 연비처럼, AI 에이전트의 효율성을 보여주는 지표입니다.

왜 이 지표가 중요할까요? 첫째, 비용을 직접적으로 반영합니다.

API 비용은 토큰 수에 비례합니다. Tokens-per-Task가 낮으면 같은 예산으로 더 많은 작업을 처리할 수 있습니다.

둘째, 압축 전략의 효과를 측정할 수 있습니다. Anchored Summarization을 적용하기 전과 후의 Tokens-per-Task를 비교하면, 정확히 얼마나 개선되었는지 알 수 있습니다.

셋째, 이상 징후를 감지할 수 있습니다. 갑자기 Tokens-per-Task가 급증했다면, 어딘가에 문제가 있다는 신호입니다.

무한 루프에 빠졌거나, 불필요한 정보가 컨텍스트에 쌓이고 있을 수 있습니다. 위 코드를 살펴보겠습니다.

TokenMetrics 클래스는 작업 단위로 토큰 사용량을 추적합니다. start_task로 작업을 시작하고, record_api_call로 각 API 호출의 토큰을 기록하며, complete_task로 최종 통계를 계산합니다.

실무에서는 작업 유형별로 Tokens-per-Task를 따로 측정합니다. "버그 수정"과 "새 기능 개발"은 성격이 다르기 때문입니다.

버그 수정이 평균 5000 토큰이라면, 새 기능 개발은 평균 20000 토큰일 수 있습니다. 이 지표를 활용한 실제 최적화 사례를 보겠습니다.

김개발 씨의 팀에서 측정한 결과, "코드 리뷰" 작업의 Tokens-per-Task가 15000으로 나왔습니다. 업계 평균이 8000인데, 거의 두 배입니다.

원인을 분석해보니, 에이전트가 매번 전체 코드베이스를 컨텍스트에 포함하고 있었습니다. 관련 파일만 포함하도록 수정하자, Tokens-per-Task가 7500으로 줄었습니다.

비용이 절반으로 감소한 것입니다. 주의할 점은 성공률과 함께 봐야 한다는 것입니다.

Tokens-per-Task만 낮추려고 하면 품질이 떨어질 수 있습니다. 너무 적은 컨텍스트로 인해 에이전트가 실수하면 재작업이 필요하고, 결국 총 비용이 더 늘어납니다.

이상적인 목표는 최소 토큰으로 최대 성공률을 달성하는 것입니다. 이것이 바로 최적화의 황금 비율입니다.

김개발 씨가 물었습니다. "그러면 우리 에이전트의 Tokens-per-Task 목표를 어떻게 정해야 할까요?" 박시니어 씨가 답했습니다.

"처음에는 측정만 하세요. 2주 정도 데이터가 쌓이면 기준선이 보여요.

그때부터 10%씩 개선 목표를 세우면 됩니다."

실전 팁

💡 - 작업 유형별로 별도의 Tokens-per-Task 기준을 설정하세요

  • 압축 전략 도입 전후로 A/B 테스트를 진행하세요
  • 성공률과 함께 보면서 품질과 효율의 균형을 찾으세요

6. 평가 프레임워크 구축하기

모든 전략과 지표를 배운 김개발 씨에게 마지막 숙제가 남았습니다. "이제 이걸 어떻게 체계적으로 관리하죠?" 박시니어 씨가 회사에서 사용하는 평가 프레임워크 문서를 보여줬습니다.

이것이야말로 AI 엔지니어의 진정한 무기였습니다.

평가 프레임워크는 AI 에이전트의 성능을 체계적으로 측정하고 개선하기 위한 구조화된 기준입니다. 품질, 효율성, 안정성의 세 축으로 에이전트를 평가하며, 지속적인 개선의 로드맵을 제공합니다.

다음 코드를 살펴봅시다.

# 종합 평가 프레임워크
class EvaluationFramework:
    def __init__(self):
        self.metrics = {
            "quality": ["task_success_rate", "output_accuracy", "user_satisfaction"],
            "efficiency": ["tokens_per_task", "latency", "cost_per_task"],
            "reliability": ["context_retention", "error_rate", "recovery_success"]
        }

    def evaluate_session(self, session_data):
        scores = {}

        # 품질 평가
        scores["quality"] = self.calc_quality_score(session_data)
        # 효율성 평가
        scores["efficiency"] = self.calc_efficiency_score(session_data)
        # 안정성 평가
        scores["reliability"] = self.calc_reliability_score(session_data)

        # 종합 점수 (가중 평균)
        weights = {"quality": 0.4, "efficiency": 0.35, "reliability": 0.25}
        scores["overall"] = sum(scores[k] * weights[k] for k in weights)

        return scores

박시니어 씨가 화면에 문서를 띄웠습니다. "이건 우리 팀의 evaluation-framework.md 파일이에요.

AI 에이전트를 평가하는 모든 기준이 여기 정리되어 있죠." 김개발 씨가 문서를 살펴봤습니다. 생각보다 체계적이었습니다.

단순히 "잘 작동하는가?"가 아니라, 여러 차원에서 세밀하게 평가하고 있었습니다. 평가 프레임워크는 크게 세 가지 축으로 구성됩니다.

첫 번째 축은 **품질(Quality)**입니다. 에이전트가 작업을 얼마나 잘 수행하는지 평가합니다.

여기에는 작업 성공률, 출력 정확도, 사용자 만족도가 포함됩니다. 아무리 효율적이어도 결과물이 엉망이면 의미가 없습니다.

두 번째 축은 **효율성(Efficiency)**입니다. 우리가 배운 Tokens-per-Task가 여기에 속합니다.

추가로 응답 지연 시간, 작업당 비용도 측정합니다. 같은 품질이라면 더 적은 자원으로 달성하는 것이 좋습니다.

세 번째 축은 **안정성(Reliability)**입니다. 이것이 장기 세션에서 특히 중요합니다.

컨텍스트 유지율, 에러 발생률, 에러 복구 성공률을 측정합니다. 24시간 에이전트가 중간에 맥락을 잃어버리면 심각한 문제입니다.

위 코드에서 EvaluationFramework 클래스는 이 세 축을 모두 평가합니다. 각 축의 점수를 계산한 뒤, 가중 평균으로 종합 점수를 산출합니다.

가중치 설정이 중요합니다. 코드에서는 품질 40%, 효율성 35%, 안정성 25%로 설정했습니다.

하지만 이것은 프로젝트 특성에 따라 달라져야 합니다. 예를 들어, 의료 분야 에이전트라면 품질의 가중치를 60% 이상으로 높여야 합니다.

오진은 절대 허용되지 않기 때문입니다. 반면 내부 개발 도구라면 효율성의 가중치를 높일 수 있습니다.

프레임워크를 실제로 운영하는 방법도 중요합니다. 첫째, 정기 평가를 실시합니다.

매주 또는 격주로 에이전트의 종합 점수를 측정합니다. 시간에 따른 추이를 보면 개선되고 있는지, 악화되고 있는지 알 수 있습니다.

둘째, A/B 테스트를 진행합니다. 새로운 압축 전략을 도입할 때, 기존 버전과 새 버전을 동시에 운영하며 비교합니다.

통계적으로 유의미한 차이가 있을 때만 새 버전을 채택합니다. 셋째, 알림 시스템을 구축합니다.

특정 지표가 임계값 아래로 떨어지면 즉시 알림을 받습니다. 품질 점수가 80점 아래로 떨어지거나, Tokens-per-Task가 갑자기 두 배로 증가하면 문제가 있다는 신호입니다.

김개발 씨가 감탄했습니다. "이렇게 체계적으로 관리하는군요!" 박시니어 씨가 고개를 끄덕였습니다.

"AI 에이전트 개발은 한 번 만들고 끝이 아니에요. 지속적으로 측정하고, 분석하고, 개선해야 해요.

이 프레임워크가 그 기반이 되는 거죠." 컨텍스트 압축 전략도 이 프레임워크 안에서 평가됩니다. Anchored Summarization을 도입한 후 효율성 점수가 얼마나 올랐는지, 대신 안정성 점수는 유지되고 있는지 확인할 수 있습니다.

마지막으로 박시니어 씨가 당부했습니다. "기억하세요.

측정하지 않으면 개선할 수 없어요. 그리고 잘못된 것을 측정하면 잘못된 방향으로 개선하게 돼요.

올바른 지표를 정의하는 것이 첫 번째 과제입니다." 김개발 씨는 오늘 배운 내용을 정리했습니다. 컨텍스트 윈도우의 한계, 세 가지 압축 전략, 그리고 이 모든 것을 체계적으로 관리하는 평가 프레임워크까지.

이제 24시간 에이전트를 제대로 만들 수 있을 것 같았습니다.

실전 팁

💡 - 평가 지표는 프로젝트 시작 전에 정의하세요. 나중에 추가하면 기준선이 없습니다

  • 자동화된 평가 파이프라인을 구축하면 지속적인 모니터링이 가능합니다
  • 평가 결과를 팀과 공유하여 모두가 같은 목표를 향해 개선하도록 하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#AI Engineering#Context Compression#LLM#Token Optimization#Agent Architecture#Prompt Engineering

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.