AI 에이전트에게 런타임 트레이스 접근 권한 부여 방법

발행: (2025년 12월 30일 오후 11:00 GMT+9)
16 min read
원문: Dev.to

Source: Dev.to

Who is it for?

이 글은 AI 코딩 에이전트(Claude, Cursor 등)를 사용해 로컬에서 실제 애플리케이션을 디버깅하고, 정적 코드 분석이 제공할 수 있는 것보다 더 빠르고 구체적인 답변을 원하는 개발자를 위한 것입니다.

AI 코딩 에이전트는 코드를 읽는 데 매우 능숙합니다. 저장소 하나만 가리키면 제어 흐름을 설명하고, 의존성을 추적하며, 패턴을 찾아내고, 거의 즉시 변경 사항을 제안할 수 있습니다.

그런데 로컬에서 디버깅을 시도하면 모든 것이 느려집니다:

  • “테스트에서는 빠른데 클릭할 때는 느려요.”
  • “이 요청은 약 20번 실행될 때마다 한 번씩 멈춰요.”
  • “서버를 재시작하기 전까지는 동작했어요.”
  • “아무것도 바꾸지 않았는데 이제는 타임아웃이 발생해요.”

이것은 코드 이해의 문제가 아니라 코드가 실제로 실행되는 방식의 문제입니다.

현재 에이전트는 대부분 정적 입력에만 기반해 동작합니다. 코드는 무엇이라고 쓰여 있는지는 알지만, 실행될 때 어떻게 동작하는지는 직접 보지 못합니다. 그래서 비극적인 과정—문제를 재현하고, 트레이스나 로그를 확인하고, 무엇이 느리거나 실패하는지 파악한 뒤, 그 정보를 다시 텍스트로 변환하는—을 하게 됩니다.

그 변환 단계가 대부분의 시간을 차지합니다.

이 글에서는 로컬 디버깅을 위해 그 단계를 없애는 방법을 소개합니다. OpenTelemetry 트레이스와 제가 만든 작은 도구 otel‑mcp 를 활용합니다.

Source:

현재 AI 디버깅 워크플로우 (그리고 왜 느린가)

AI 에이전트를 사용해 구문 오류를 넘어서는 디버깅을 해본 적이 있다면, 이 루프가 익숙하게 느껴질 것입니다.

이전

You:    The /users endpoint is slow locally.
Agent: I see two DB queries and an external call. Which part is slow?
You:    (spends 10 minutes checking logs / traces / console output)
You:    The external API averages ~600 ms.
Agent: Add caching. Here’s how.

에이전트의 제안이 실제로 옳을 수도 있지만, 시간이 어디에 소비됐는지 살펴보세요:

  • 코드를 작성하지 않음
  • 논리를 이해하지 않음

하지만 많은 시간이 증거를 찾는 것그것을 설명하는 것에 사용됩니다. 여러분은 실행 중인 시스템과 모델 사이의 인간 어댑터 역할을 하고 있는 것입니다.

문제는 추론이 아니라 가시성입니다.

Source:

코드를 읽는다고 동작 방식을 알 수는 없습니다

다음은 완전히 정상적인 엔드포인트입니다:

app.get('/api/users/:id', async (req, res) => {
  const user = await db.query('SELECT * FROM users WHERE id = ?', [req.params.id]);
  const posts = await db.query('SELECT * FROM posts WHERE user_id = ?', [user.id]);
  const enriched = await enrichUserData(user, posts);
  res.json(enriched);
});

소스만 보면 에이전트가 합리적인 말을 할 수 있습니다:

  • 데이터베이스 쿼리가 두 개 있습니다.
  • enrichUserData는 아마도 I/O를 수행할 것입니다.
  • await는 순차적으로 실행됩니다.
  • 느린 의존성이나 인덱스 누락이 가능성이 있습니다.

이 모든 것이 사실이지만, 디버깅하기엔 충분하지 않습니다. 실제로 로컬 이슈를 해결할 때는 다음과 같은 것들이 중요합니다:

  • 현재 머신에서 어느 단계가 느린가?
  • 지속적으로 느린가, 아니면 가끔씩만 느린가?
  • 재시도나 타임아웃이 포함되어 있는가?
  • 작업이 풀이나 락 뒤에서 대기하고 있는가?
  • 오류가 발생하고 이를 무시하고 있는가?

다음과 같은 답을 코드만 읽고는 찾을 수 없습니다:

“이 쿼리는 인덱스 없이 약 50개의 행을 반환하기 때문에 약 430 ms가 걸립니다.”

또는

“HTTP 호출은 정상인데, 재시작 후 연결 재사용이 멈춥니다.”

이러한 답은 코드를 실제로 실행해 보아야 나타납니다.

Traces: execution data an AI can actually use

분산 추적은 요청이 실행되는 방식을 구조화된 기록으로 제공합니다.

tracespan들의 트리 구조입니다. 각 span은 데이터베이스 쿼리, HTTP 호출, 캐시 접근과 같은 시간 측정이 가능한 작업을 나타내며, 지속 시간, 상태, 선택적 메타데이터와 같은 속성을 가집니다.

OpenTelemetry 자동 계측을 사용하면 일반적으로 로컬 지연 시간을 지배하는 작업에 대한 span을 정확히 얻을 수 있습니다.

같은 엔드포인트가 다음과 같은 trace를 생성할 수 있습니다:

Trace: GET /api/users/123   (total: 892 ms)

  db.query users_by_id                 6 ms
  db.query posts_by_user_id          438 ms   rows=52
  enrichUserData                     440 ms
    http.client GET /user-metadata   411 ms   status=200
    cache.set                          9 ms

이는 구체적이고, 시간 측정이 가능하며, 계층적인 데이터입니다. 어떤 작업이 실행됐는지, 어떤 순서로 진행됐는지, 각 단계가 얼마나 걸렸는지를 알려줍니다—수동 디버깅 시 찾고자 하는 정확한 정보입니다.

What if the agent could inspect this directly?

otel‑mcp: AI 에이전트를 위한 트레이스

“MCP (Model Context Protocol)는 AI 에이전트가 세션 중에 외부 도구를 호출할 수 있게 하는 방법입니다.”

otel‑mcp 은 로컬 개발 중에 AI 에이전트가 런타임 트레이스를 사용할 수 있게 해 주는 작은 MCP 서버입니다. 세 가지 간단한 일을 수행합니다:

  1. 로컬 OTLP HTTP 컬렉터 실행 (localhost 전용).
  2. 최근 트레이스를 메모리에 저장 (일시적, 개발 중심).
  3. 에이전트가 MCP를 통해 호출할 수 있는 소규모 쿼리 도구 제공.

이는 APM이 아닙니다—UI도 없고, 대시보드도 없으며, 보존 정책도 없습니다. AI 에이전트를 이용한 로컬 디버깅에 특화되어 설계되었습니다.

이 작업은 어떤 에이전트와 함께 사용할 수 있나요?

otel‑mcp는 MCP와 호환되는 모든 AI 코딩 어시스턴트와 함께 작동하며, 포함:

  • Claude Code
  • Cursor
  • MCP 도구를 지원하는 기타 모든 도구

에이전트가 MCP 도구를 호출할 수 있다면, otel‑mcp를 통해 트레이스를 조회할 수 있습니다.

Source:

에이전트가 트레이스를 볼 수 있을 때 무엇이 바뀔까?

같은 디버깅 시나리오를 다시 재생해 보겠습니다.

After (with otel‑mcp)

You:    The /users endpoint is slow locally.
Agent: (lists slow traces from the last few minutes)
Agent: I found 23 slow requests. The posts query averages ~430 ms and
       returns ~50 rows without an index. The external API averages ~70 ms.
       Adding an index on posts(user_id) should fix this.

“트레이스를 확인하고 알려줄 수 있나요?” 같은 왕복 대화가 필요 없습니다—에이전트가 실행 데이터를 직접 검사하고 실행 가능한 조언을 바로 제공할 수 있습니다.

TL;DR

  • 정적 코드 분석은 코드가 무엇을 하는지 알려 주지만, 런타임에서 어떻게 동작하는지는 알려 주지 않습니다.
  • OpenTelemetry 트레이스는 누락된 런타임 가시성을 제공합니다.
  • otel‑mcp는 그 격차를 메우며, 최신 트레이스를 MCP‑호환 AI 어시스턴트에 노출시켜 느리고 수동적인 디버깅 루프를 빠르고 AI‑기반 루프로 전환합니다.

에이전트가 받는 도구

otel‑mcp는 고의로 작고 예측 가능한 도구 집합을 제공합니다:

get_summary()

어떤 서비스가 트레이스를 내보내고 있나요? 몇 개인가요? 최근 오류는 있나요?

list_traces(filters)

느린 트레이스, 오류 트레이스, 혹은 특정 서비스의 트레이스를 표시합니다.

get_trace(trace_id)

하나의 요청에 대한 전체 스팬 트리를 가져옵니다.

query_spans(where)

다음과 같은 조건에 맞는 스팬을 찾습니다:

duration > 100 AND status = error
http.status_code >= 500

예시

Agent calls:
query_spans({ where: "duration > 100 AND http.status_code >= 500" })

Result:
12 spans from the last 5 minutes showing slow, failed API calls

clear_traces()

테스트 실행 사이에 상태를 초기화합니다.

이 도구들은 실제 디버깅 방식과 일치합니다: 먼저 넓게 시작하고, 점점 좁혀가며, 세부 사항을 검사합니다.

필요한 것

설정을 진행하기 전에 다음을 확인하세요:

  • OpenTelemetry‑instrumented application (또는 추가 의향)
  • MCP‑compatible AI agent (Claude Code, Cursor 등)
  • OpenTelemetry를 지원하는 런타임 (Node.js, Java, Go, Python, …)

프로덕션 관측이나 호스팅된 백엔드가 필요하지 않습니다 — 모두 로컬에서 실행됩니다.

설정하기

이미 OpenTelemetry를 사용하고 있다면 설정은 보통 간단합니다 — 익스포터를 로컬 콜렉터에 지정하기만 하면 됩니다.

일반적인 Node.js 구성

import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';

const sdk = new NodeSDK({
  serviceName: 'my-app',
  traceExporter: new OTLPTraceExporter({
    url: 'http://localhost:4318/v1/traces',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

자동 계측은 보통 로컬에서 중요한 대부분을 캡처합니다:

  • HTTP 핸들러
  • 데이터베이스 쿼리
  • 외부 HTTP 호출
  • 캐시

자동 계측이 되지 않을 경우, 중요한 섹션에 수동 스팬을 추가하는 것만으로도 충분합니다.

왜 이것이 로컬 디버깅에 잘 작동하는가

실제 사용에서 효과적인 몇 가지 설계 선택이 있습니다:

  • 인‑메모리 저장소 – 빠르고 간단하며 로컬 반복에 충분히 적합합니다.
  • 제한된 쿼리 – 에이전트가 모든 정보를 컨텍스트에 끌어들이는 대신 목표 지향적인 질문을 합니다.
  • 기본적으로 로컬 전용 – 실수로 프로덕션 데이터를 노출할 위험이 없습니다.
  • 공유 컬렉터 – 여러 에이전트 클라이언트를 실행하면 모두 동일한 트레이스를 볼 수 있습니다.

목표는 전체 관측성 플랫폼을 구축하는 것이 아니라 디버깅의 마찰을 없애는 것입니다.

일반적인 문제

  • 트레이스가 표시되지 않나요?
    앱이 http://localhost:4318/v1/traces 로 내보내고 있는지 확인하세요.

  • 에이전트가 도구를 인식하지 못하나요?
    MCP 설정에 otel‑mcp 가 포함되어 있는지 확인하세요.

  • 여러 에이전트를 사용하고 있나요?
    첫 번째 에이전트가 컬렉터를 시작하고, 나머지는 자동으로 연결됩니다.

  • 트레이스에 흥미로운 내용이 없나요?
    조사 중인 코드 주변에 수동 스팬을 추가해야 할 수도 있습니다.

제한 사항 (그리고 왜 여기서는 괜찮은가)

  • 프로덕션 APM이 아님 – 대시보드, 알림, 장기 저장소가 없습니다.
  • 자동 계측이 완벽하지 않음 – 일부 라이브러리와 비동기 경계는 수동 스팬이 필요합니다.
  • 트레이스에 민감한 데이터가 포함될 수 있음 – 컬렉터를 로컬호스트에 두고 필요하면 속성을 redact(삭제)하세요.
  • 오버헤드가 존재 – 보통 로컬에서는 괜찮지만, 매우 타이트한 작업을 할 경우 측정이 필요합니다.

로컬 디버깅에서는 이러한 트레이드오프가 보통 허용됩니다.

사용해 보기

AI 에이전트를 사용해 로컬에서 디버깅하면서 로그나 트레이스에서 본 내용을 계속 설명해야 한다면, 이것을 시도해 볼 가치가 있습니다.

👉 https://github.com/moondef/otel-mcp

  • OpenTelemetry를 계속 사용하세요.
  • 개발 중에 익스포터를 localhost에 지정하세요.
  • 에이전트가 트레이스를 요약해 달라고 요청하는 대신 직접 조회하도록 하세요.

에이전트가 실제 코드 실행 방식을 볼 수 있게 되면 대화가 바뀌고, 디버깅 속도가 눈에 띄게 빨라집니다.

Back to Blog

관련 글

더 보기 »