---
title: "MCP 도구 호출마다 무엇을 로그로 남겨야 할까"
description: "클라이언트에게 원격 MCP 서버는 속을 알 수 없는 하나의 스팬이고, 디렉터리 대시보드에는 합계만 보입니다. 호출을 본 것은 서버뿐입니다. Tajo의 MCP 서버가 호출마다 남기는 행을 필드별로 살펴보고, 거기서 무엇을 지우는지, 무엇이 아직 만들어지지 않았는지 설명합니다."
url: https://tajo.io/kr/blog/what-to-log-for-every-mcp-tool-call/
markdown: https://tajo.io/kr/blog/what-to-log-for-every-mcp-tool-call.md
lang: ko-KR
author: "Set Noa"
author_url: https://tajo.io/kr/set-noa/
published: 2026-11-06
updated: 2026-11-06
alternates: {en-US: /blog/what-to-log-for-every-mcp-tool-call.md, bg-BG: /bg/blog/what-to-log-for-every-mcp-tool-call.md, cs-CZ: /cz/blog/what-to-log-for-every-mcp-tool-call.md, de-DE: /de/blog/what-to-log-for-every-mcp-tool-call.md, da-DK: /dk/blog/what-to-log-for-every-mcp-tool-call.md, es-ES: /es/blog/what-to-log-for-every-mcp-tool-call.md, fr-FR: /fr/blog/what-to-log-for-every-mcp-tool-call.md, el-GR: /gr/blog/what-to-log-for-every-mcp-tool-call.md, hi-IN: /hi/blog/what-to-log-for-every-mcp-tool-call.md, id-ID: /in/blog/what-to-log-for-every-mcp-tool-call.md, hr-HR: /hr/blog/what-to-log-for-every-mcp-tool-call.md, hu-HU: /hu/blog/what-to-log-for-every-mcp-tool-call.md, it-IT: /it/blog/what-to-log-for-every-mcp-tool-call.md, ja-JP: /jp/blog/what-to-log-for-every-mcp-tool-call.md, ar-SA: /ar/blog/what-to-log-for-every-mcp-tool-call.md, nl-NL: /nl/blog/what-to-log-for-every-mcp-tool-call.md, no-NO: /no/blog/what-to-log-for-every-mcp-tool-call.md, pl-PL: /pl/blog/what-to-log-for-every-mcp-tool-call.md, pt-BR: /pt/blog/what-to-log-for-every-mcp-tool-call.md, ro-RO: /ro/blog/what-to-log-for-every-mcp-tool-call.md, ru-RU: /ru/blog/what-to-log-for-every-mcp-tool-call.md, sv-SE: /se/blog/what-to-log-for-every-mcp-tool-call.md, zh-CN: /zh-cn/blog/what-to-log-for-every-mcp-tool-call.md, sl-SI: /sl/blog/what-to-log-for-every-mcp-tool-call.md, sr-Latn-RS: /sr/blog/what-to-log-for-every-mcp-tool-call.md, th-TH: /th/blog/what-to-log-for-every-mcp-tool-call.md, tr-TR: /tr/blog/what-to-log-for-every-mcp-tool-call.md, ur-PK: /ur/blog/what-to-log-for-every-mcp-tool-call.md, vi-VN: /vi/blog/what-to-log-for-every-mcp-tool-call.md, sk-SK: /sk/blog/what-to-log-for-every-mcp-tool-call.md}
---

[AI 에이전트](https://tajo.io/kr/blog/?category=ai-agents)

# MCP 도구 호출마다 무엇을 로그로 남겨야 할까

클라이언트에게 원격 MCP 서버는 속을 알 수 없는 하나의 스팬이고, 디렉터리 대시보드에는 합계만 보입니다. 호출을 본 것은 서버뿐입니다. Tajo의 MCP 서버가 호출마다 남기는 행을 필드별로 살펴보고, 거기서 무엇을 지우는지, 무엇이 아직 만들어지지 않았는지 설명합니다.

MCP 서버 로그

MCP 서버는 도구 호출마다 무엇을 기록해야 하나요?

도구 호출마다 한 행을 서버에서 기록하세요. 호출을 본 곳은 서버뿐이기 때문입니다. Tajo의 MCP 서버는 누가 호출했는지(키의 ID만 기록하고 비밀 값은 기록하지 않음), 어떤 서버와 커넥터인지, 도구가 존재하면 그 도구, 효과 등급, ok 또는 짧은 오류 코드, 소요 시간, 결과 크기, 추적 ID, 호출이 건드린 레코드, 그리고 비밀 정보와 개인 데이터를 지운 인수와 응답을 기록합니다. 행은 logs.list와 logs.get으로 읽으며 30일 후 삭제됩니다. 이 행은 승인과 그 입력 다이제스트가 보관되는 해시 체인 감사 로그와 따로 저장됩니다. 아직 만들지 않은 것: 상태 점수, 오류율 알림, 도구나 추적 ID로 검색하기, 자체 트레이싱으로 내보내기입니다.

[자세히 알아보기](https://tajo.io/kr/blog/what-to-log-for-every-mcp-tool-call/#%ED%98%B8%EC%B6%9C%EB%8B%B9-%ED%95%9C-%ED%96%89)

2026년 6월 8일, Anthropic은 Claude 디렉터리에 있는 커넥터의 소유자에게 대시보드를 제공했습니다. 활성 사용자, 전체 도구 호출 수, 디렉터리 순위를 보여 줍니다. 또한 “[상태 점수, 오류율, 지연 시간을 한눈에 보여 주고, 도구별 오류 분석으로 무엇이 실패하는지 정확히 짚어 줍니다](https://claude.com/resources/articles/observability-for-developers-building-connectors)”.

그보다 1년 전, Weights & Biases의 Alex Volkov는 같은 문제를 반대편에서 설명했습니다. 그의 에이전트가 MCP로 도구를 호출하기 시작하자 “[내 코드를 처음부터 끝까지 직접 실행할 때 익숙했던 관측성이 조금 어두워졌다](https://www.youtube.com/watch?v=Lcqat4iP_lE&t=61s)”는 것입니다. 함께 발표한 Dylibso의 Benjamin Eckel은 그 이유를 보여 주었습니다. 원격 MCP 서버는 호출하는 쪽의 통제 밖에서 실행되기 때문에 “[트레이스에서 하나의 서비스 스팬으로 나타납니다](https://www.youtube.com/watch?v=Lcqat4iP_lE&t=447s)”.

두 시각 모두 서버 바깥에 있습니다. 클라이언트에게는 속을 알 수 없는 하나의 스팬이 보입니다. 디렉터리에는 합계가 보입니다. 서버가 무엇을 요청받았고, 무엇을 거부했고, 무엇을 건드렸는지는 어느 쪽도 보지 못했습니다. 그것을 본 것은 서버뿐이므로, 기록할 수 있는 것도 서버뿐입니다.

이 글은 Tajo의 MCP 서버가 기록하는 내용을, 서버를 실행하는 코드에서 읽어 정리한 것이며 [문서에도 적혀 있습니다](https://tajo.io/kr/docs/mcp/#mcp-request-log). 프로토콜은 [MCP 서버란 무엇인가](https://tajo.io/kr/blog/what-is-an-mcp-server/)에서 다룹니다. 이 글에서 다루는 것은 로그의 한 행입니다.

## 호출당 한 행

대시보드는 항만 관리자의 시각입니다. 들어온 배, 나간 배, 늦은 배를 봅니다. 요청 로그는 배 자신의 항해일지로, 그 시각에 배 위에서 쓰입니다.

Tajo의 워크스페이스 서버와 모든 커넥터 서버에서 각 `tools/call`은 [한 행으로 끝납니다](https://tajo.io/kr/docs/mcp/#mcp-request-log). 행은 응답이 무엇이었든 응답이 만들어진 뒤에 기록됩니다. 키에 쓰기 권한이 없거나 엔드포인트가 읽기 전용이라서 거부된 호출도 다른 호출과 똑같이 한 행을 남깁니다. 존재하지 않는 도구를 호출한 경우도 마찬가지입니다.

행이 담는 것과 담기를 거부하는 것은 다음과 같습니다.

| 필드 | 보관하는 것 | 보관하지 않는 것 |
| --- | --- | --- |
| 누가 | 호출한 API 키의 ID. OAuth 로그인으로 받은 토큰도 키입니다. | 키의 비밀 값이나 그 접두사. |
| 어디서 | 워크스페이스 서버 또는 커넥터 서버와 그 커넥터 및 프로필. |  |
| 도구 | 서버에 그 이름의 도구가 있을 때의 이름. | 클라이언트가 보내는 그 밖의 이름. `(unknown)`으로 저장됩니다. |
| 효과 | `read`, `write`, `send` 또는 `destructive`. 호출이 가질 수 있는 가장 무거운 효과입니다. |  |
| 결과 | `ok`, 또는 `unknown_tool` 같은 짧은 snake\_case 오류 코드. | 오류 설명문. 코드가 아닌 것은 모두 `tool_error`로 저장됩니다. |
| 소요 시간과 크기 | 도착부터 응답까지의 밀리초, 그리고 호출한 쪽이 받은 바이트 수. |  |
| 추적 ID | `x-request-id`, `x-trace-id` 또는 W3C `traceparent` 헤더에서 가져온 요청 ID. 없으면 새로 만듭니다. | 16진수도 UUID도 아닌 헤더 값. |
| 레코드 | 호출이 지정하거나 생성한 레코드의 ID 최대 20개. 연락처, 메시지, 승인 등입니다. | 레코드 자체. |
| 본문 | 인수와 응답. [정리된 상태](https://tajo.io/kr/docs/mcp/#mcp-request-log)로 각각 최대 4KB. | 비밀 정보, 자유 텍스트, 그리고 아래에 나열한 개인 데이터. |

이 중 세 가지 거부는 데이터가 아니라 클라이언트에 관한 것입니다. 도구 이름, 오류 코드, 추적 ID는 모두 바깥에서 들어옵니다. 각각은 서버가 보증할 수 있는 형태로만 보관됩니다. 호출한 쪽이 보낸 것을 무엇이든 저장하는 로그는 무엇으로든 채워질 수 있습니다. 도구 이름 열에 고객의 이메일 주소가 들어갈 수도 있습니다.

발표 끝에서 Benjamin Eckel이 남긴 열린 질문은 수집기가 “[그것이 오류가 난 MCP 도구 호출이라는 것](https://www.youtube.com/watch?v=Lcqat4iP_lE&t=906s)”을 어떻게 아느냐였습니다. 하나의 서버 안에서라면 답은 하나의 열입니다. `ok`가 false이고, 어떤 오류인지는 코드가 알려 줍니다.

## 인수: 우리가 뒤집은 규칙

반론은 타당하며, 우리 스스로의 반론이기도 합니다. 인수를 로그로 남기면 고객 데이터의 두 번째 사본을, 어떤 삭제 요청도 닿지 않는 곳에 만들게 됩니다. 2026년 10월 18일까지는 그것이 [우리 자신의 규칙](https://tajo.io/kr/docs/mcp/#mcp-request-log)이었습니다. 둘 다 개인 데이터를 담을 수 있으므로 로그는 인수도 결과 본문도 보관하지 않았습니다.

그것은 잘못된 절충이었습니다. 무엇을 보냈고 무엇이 돌아왔는지 보여 주지 못하는 요청 로그는, 그 로그가 존재하는 단 하나의 질문, 즉 “내 에이전트의 호출은 왜 실패했는가”에 답할 수 없습니다.

그래서 본문을 보관하되, 보관하지 않았던 이유는 다른 방법으로 해결합니다. 각 본문은 대기열에 들어가기 전에 [결정론적인 한 번의 처리](https://tajo.io/kr/docs/mcp/#mcp-request-log)를 거칩니다.

- **비밀 정보는 남지 않습니다.** 이름이 token, password, secret, signature, cookie, session 또는 이와 비슷한 스무 개 정도의 단어를 가리키는 필드에는 `[secret]`만 남습니다. 알려진 자격 증명 형태의 값도 어디에 있든 마찬가지입니다. 여기에는 bearer 토큰, JWT, 개인 키, 비밀번호가 들어간 URL, 그리고 40자 이상 이어지는 불투명한 키 문자열이 포함됩니다.
- **글은 아예 보관하지 않습니다.** 이름이 `html`, `text`, `body`, `markdown` 또는 `content`인 필드에는 `[redacted]`만 남습니다. 글에는 어떤 패턴으로도 찾을 수 없는 이름과 주소가 들어 있기 때문입니다.
- **개인 데이터는 영구적으로 마스킹됩니다.** 이메일, 전화번호, 이름, 주소, 메모처럼 이름이 개인 데이터를 나타내는 필드에는 `[redacted]`만 남습니다. 그 밖의 문자열 안에 있는 이메일 주소, 전화번호, 카드 번호, IBAN은 마스킹됩니다.
- **본문은 작게 유지됩니다.** [문자열은 512자](https://tajo.io/kr/docs/mcp/#mcp-request-log), 목록은 20개 항목, 객체는 50개 키, 중첩은 6단계에서 잘립니다. 본문 전체는 [4KB에서 잘리고](https://tajo.io/kr/docs/mcp/#mcp-request-log) 잘렸다는 표시가 붙습니다.

두 종류의 호출은 이보다 덜 보관합니다. 사람의 채팅이 다른 앱에서 가져온 연락처는 본문 없이 표시와 개수로만 기록됩니다. 로그를 읽는 호출은 응답을 보관하지 않습니다. 그 응답은 다른 로그 행일 뿐이기 때문입니다.

이제 비용입니다. 마스킹은 영구적이며, 누군가 키를 가진 암호화가 아닙니다. 로그로는 반송된 이메일 주소를 볼 수 없습니다. 보이는 것은 연락처의 ID이고, 연락처 자체는 그 고유한 규칙에 따라 호출 한 번이면 조회할 수 있습니다. 로그는 워크스페이스 삭제 처리의 범위 밖에 있으며, 그래서 마스킹이 그 처리를 기다릴 수 없습니다.

## 이 로그가 감사 추적이 아닌 이유

Tajo에는 이미 [추가만 가능한 감사 로그](https://tajo.io/kr/docs/mcp/#mcp-request-log)가 있습니다. 각 행은 바로 앞 행의 해시를 담고 있어서, 어디든 수정하면 체인이 끊어집니다. 그렇다면 도구 호출을 왜 거기에 기록하지 않을까요?

체인에는 대가가 있기 때문입니다. 추가할 때마다 워크스페이스 단위 잠금을 걸고, 체인을 잇기 위해 앞 행을 읽습니다. 모든 읽기를 여기에 기록하면 워크스페이스의 호출이 하나의 잠금 뒤에 줄을 서게 됩니다. 또한 감사 로그가 보여 주려고 존재하는 상태 변경이 수천 건의 읽기 아래에 묻힙니다.

그래서 두 기록은 질문에 따라 나뉩니다. 요청 로그는 에이전트가 무엇을 요청했고 무슨 일이 일어났는지를 [30일 동안](https://tajo.io/kr/docs/mcp/#mcp-request-log) 알려 줍니다. 감사 로그는 무엇이 바뀌었는지, 누가 허용했는지, 그 뒤로 누가 기록을 수정했는지를 알려 줍니다.

승인은 감사 로그 쪽에 있습니다. Tajo의 커넥터 프로필에서는 [propose 도구가 선언된 액션을 준비하고, 승인되면 apply 도구가 실행합니다](https://tajo.io/kr/docs/mcp/). 제안이 승인되기 전에는 프로바이더에 아무것도 전달되지 않습니다. 승인은 사람이 하거나, 워크스페이스가 켠 규칙이 합니다. propose 호출의 행은 자신이 만든 승인을 레코드 중 하나로 기록합니다. 승인 자체는 정확한 입력의 SHA-256 다이제스트에 묶여 있습니다. [승인은 사용자가 본 바로 그 입력에만 적용됩니다](https://tajo.io/kr/docs/mcp/agent-specification/). 필드 하나만 바꿔도 더 이상 일치하지 않습니다. 쓰기가 반영되면 그 감사 행에는 입력 다이제스트와 프로바이더 응답의 다이제스트가 남고, 응답의 값 자체는 남지 않습니다.

## 한 행의 비용

한 행은 데이터베이스 쓰기이고, 쓰기에는 커밋이 따릅니다. [2026년 10월 8일까지](https://tajo.io/kr/docs/mcp/#mcp-request-log)는 각 호출이 응답 전에 자신의 커밋을 기다렸고, 우리 호스트에서 약 2.6ms가 걸렸습니다. 한 클라이언트에게 그것은 작은 도구 호출 시간의 4분의 1이었습니다.

지금은 호출이 끝날 때 행을 만들어 대기열에 넣습니다. 플러시가 [최대 100ms 뒤에](https://tajo.io/kr/docs/mcp/#mcp-request-log) 대기열을 기록하며, 워크스페이스마다 트랜잭션 하나이므로 여러 호출이 커밋 하나를 공유합니다. 타임스탬프를 포함해 행의 내용은 아무것도 바뀌지 않습니다. [5,000개 행이 대기 중이면](https://tajo.io/kr/docs/mcp/#mcp-request-log) 다음 호출은 행을 버리는 대신 플러시를 기다립니다.

기록 때문에 호출이 실패하는 일은 없습니다. 실패한 쓰기는 행 단위로 다시 시도하고, 그래도 안 되면 로그에 남긴 뒤 버립니다. 프로세스가 강제 종료될 때 잃는 것은 대기열에 있던 것, 즉 [최대 마지막 100ms 동안의 호출](https://tajo.io/kr/docs/mcp/#mcp-request-log)입니다.

## 다시 읽기

[`logs.list`](https://tajo.io/kr/docs/mcp/#mcp-request-log)는 워크스페이스의 호출을 최신순으로, 본문 없이 반환합니다. 시간, 결과 또는 HTTP 상태, 출처(MCP, 또는 같은 테이블을 쓰는 REST API), API 키로 필터링할 수 있습니다. 기본적으로 한 페이지에 50개, 최대 100개입니다. `logs.get`은 호출 하나를 키의 현재 이름, 상태, 소요 시간, 정리된 요청과 응답, 건드린 레코드와 함께 반환합니다.

둘 다 호출한 쪽의 워크스페이스만 읽습니다. 다른 워크스페이스의 행 ID는 찾을 수 없습니다.

도구 오류에는 요청 ID가 담깁니다. 서버가 그 ID를 만들었거나 16진수 또는 UUID로 들어온 경우, 그것이 행의 추적 ID입니다. 오류를 받은 에이전트는 그 호출을 가리키는 값 하나를 사람에게 건넬 수 있습니다.

## 만들어진 것과 만들어지지 않은 것

이 글을 쓰는 시점에 만들어진 것:

- 워크스페이스 서버와 모든 커넥터 서버에서 거부된 호출과 알 수 없는 호출을 포함한 `tools/call`당 한 행.
- [키 ID, 서버, 커넥터, 프로필, 도구, 효과, 결과, 소요 시간, 결과 크기, 추적 ID, 그리고 건드린 레코드 최대 20개](https://tajo.io/kr/docs/mcp/#mcp-request-log).
- [정리된 인수와 응답](https://tajo.io/kr/docs/mcp/#mcp-request-log), 각각 최대 4KB.
- 워크스페이스 범위로 제한되고 30일 동안 보관되는 [`logs.list`와 `logs.get`](https://tajo.io/kr/docs/mcp/#mcp-request-log).
- 입력 다이제스트에 묶인 승인, 그리고 해시 체인 감사 로그에 입력과 출력 다이제스트와 함께 기록되는 적용된 쓰기.

만들어지지 않은 것. 의지하기 전에 알아 둘 만합니다:

- 상태 점수도, 도구별 차트도, 오류율 상승에 대한 알림도 없습니다. 호출, 오류, 가장 느린 소요 시간의 도구별 요약은 [Tajo 운영자에게만 있으며](https://tajo.io/kr/docs/mcp/#mcp-request-log), 사용자가 열 수 있는 화면에는 없습니다.
- `logs.list`는 도구 이름이나 추적 ID로 필터링할 수 없습니다. 요청 ID에 해당하는 행을 찾으려면 시간과 키로 범위를 좁히세요.
- 행은 사용자가 운영하는 트레이싱 시스템으로 내보내지지 않습니다. 추적 ID는 HTTP 헤더에서만 읽으며, 발표에서 [트레이스 컨텍스트를 전달](https://www.youtube.com/watch?v=Lcqat4iP_lE&t=535s)하는 데 쓴 MCP `_meta` 필드에서는 읽지 않습니다.
- [30일이 지나면 행은 삭제됩니다](https://tajo.io/kr/docs/mcp/#mcp-request-log). 보관 기록이나 내보내기는 없습니다.
- 마스킹된 내용은 로그에서 복구할 수 없습니다.
- [강제 종료 시 마지막 100ms 동안의 행을 잃을 수 있습니다](https://tajo.io/kr/docs/mcp/#mcp-request-log).

발표는 MCP의 관측성이 “[고르게 퍼져 있지 않다](https://www.youtube.com/watch?v=Lcqat4iP_lE&t=841s)”는 말로 끝났습니다. 하류의 대시보드로는 이를 고칠 수 없고, 서버 문 앞에서 끊기는 트레이스로도 고칠 수 없습니다. [실패한 동기화에는 자체 기록이 필요합니다](https://tajo.io/kr/blog/worker-died-sync-didnt/). 무언가를 요청한 모든 호출도 마찬가지입니다.

호출을 본 것은 서버입니다. 다른 누구도 보지 못했습니다. 그러니 거기서 기록하세요.

## 자주 묻는 질문

**MCP 서버는 도구 호출마다 무엇을 로그로 남겨야 하나요?**

서버가 직접 쓰는, 호출당 한 행입니다. 어떤 API 키가 호출했는지, 어떤 서버와 커넥터인지, 도구가 존재하면 그 도구 이름, 효과 등급, ok 또는 짧은 오류 코드, 소요 시간, 결과 크기, 요청의 추적 ID, 호출이 지정하거나 생성한 레코드의 ID, 그리고 비밀 정보와 개인 데이터를 지운 인수와 응답입니다. Tajo의 MCP 서버는 거부된 호출을 포함해 모든 tools/call에 대해 이 행을 쓰고 30일 동안 보관합니다.

**MCP 요청 로그에 도구 인수를 남겨야 하나요?**

네, 정리한 상태로 남깁니다. 인수가 없는 로그는 호출이 왜 실패했는지 말해 줄 수 없습니다. Tajo는 2026년 10월 18일까지 본문을 전혀 보관하지 않았고, 지금은 결정론적인 한 번의 처리를 거친 뒤 둘 다 보관합니다. 비밀 정보는 \[secret\]이 되고, 자유 텍스트와 개인 데이터 필드는 \[redacted\]가 되며, 이메일, 전화번호, 카드 번호, IBAN은 마스킹되고, 각 본문은 4KB에서 잘립니다. 마스킹은 되돌릴 수 없으므로 로그는 레코드를 복사하지 않고 ID로 가리킵니다.

**MCP 도구 호출 로그를 감사 로그와 분리하는 이유는 무엇인가요?**

답하는 질문도, 드는 비용도 다르기 때문입니다. Tajo의 감사 로그는 상태 변경의 해시 체인이며, 추가할 때마다 체인을 잇기 위해 워크스페이스 단위 잠금을 겁니다. 모든 읽기를 여기에 기록하면 워크스페이스의 호출이 그 잠금 뒤에 줄을 서고, 변경 사항이 읽기 기록 속에 묻힙니다. 도구 호출은 30일 동안 보관되는, 체인이 없는 별도 테이블에 기록됩니다. 호출이 준비한 쓰기는 여전히 각자의 감사 행을 남깁니다.

## 관련 글

### [MCP 서버란 무엇인가? 2026년 MCP와 MCP UI의 작동 방식](https://tajo.io/kr/blog/what-is-an-mcp-server/)

2026년 10월 3일 · 11 분 읽기

1단계 → 6단계

### [Grok Bot과 Brevo로 제품 피드백에 응답하기](https://tajo.io/kr/blog/grok-bot-brevo-product-feedback/)

2026년 10월 7일 · 4 분 읽기

3개 섹션

### [MCP냐 CLI냐는 잘못된 질문입니다. 상태가 어디에 있는지 물어야 합니다](https://tajo.io/kr/blog/mcp-or-cli-is-the-wrong-question/)

2026년 11월 4일 · 6 분 읽기

5개 섹션
