Claude Code와 개발을 함께 진행하다보면, Claude Code로 얻게 되는 지식들이 있습니다. 이 지식들은 단순히 그 자리에서 습득하는 것으로 그치거나, 어디에 메모하고 마는 것이 아니라 저는 제가 운영하고 있는 기술 블로그에 일목요연하게 글로 정리되면 좋겠다고 생각했습니다.
이미 제가 운영하고 있는 블로그에는 'AI 개선 제안 받기'라는 기능이 있습니다. 제가 블로그에 작성한 원문 글을 좀더 가시성 있게 구조화해서 SEO를 최적화해주고, 필요에 따라 내용을 더 보완해주고, 제 생각과 말투를 따라할 수 있도록 개발했습니다. 저는 Claude Code와 주고받은 대화를 정리하는 것이, 블로그에 글을 작성하고 AI에게 피드백을 받는 것과 꽤나 유사한 상황이라고 느껴졌습니다.
Claude Code 대화 세션 내에서 방금 대화한 따끈따끈한 내용을, 'AI 개선 제안 받기'의 기능처럼 저의 말투를 따라해서 작성해줄 수 있다면, 대화하며 주고받은 내용을 스크롤해서 더듬어서 어떻게 쓰면 좋을지를 고민하는 시간이 줄고, AI가 정리해준 내용을 전반적으로 검토해서 제가 보완하는 것으로 생산성 있게 글을 효율적으로 작성할 수 있겠다고 판단했습니다.
Claude Code에게 어떻게 하면 제가 구축한 블로그 시스템에다가 글을 쓰라고 요청할 수 있을까요? 간단하게는 의도한대로 결과물이 나올 수 있도록 프롬프팅을 빡빡하게 작성해서, 글 초안 작성 시 필요한 엔드포인트를 알려주고, 필요한 권한을 부여하고 작성하게끔 하면 됩니다.
그러나, 우리는 앞서 얘기한 문장에서 '필요한 권한을 부여하고'라는 것에 대한 의미를 눈여겨봐야 할 필요가 있습니다. 권한 분리의 작업은 섬세한 작업입니다. 가령, 관리자의 모든 권한을 다 부여하자니, AI가 과연 제가 요구한 것만 골라서 필요한 작업을 진행할지에 대해서 확신이 없습니다. 기껏 권한을 다 부여해줬더니, 가능성은 매우 적겠지만, 가령 모든 게시 상태의 글을 삭제해버리면 그건 누구의 책임, 누구의 잘못이 될까요? 우리는 AI가 언제든 실수할 수 있다는 것을 고려하면서 작업을 진행해야 하는 게 당연한 태도가 되어야 한다고 생각합니다.
두 번째로는 모든 권한을 부여하지 않는다고 하더라도, 그렇다면 Claude Code가 필요한 API에 대해서 권한만을 추가로 분기 처리하는 것도 능사는 아니라는 것입니다. 가령, 이후로 운영하면서 추가로 필요한 API가 있다면, 그 API 엔드포인트에 대해서 추가로 분기 처리를 해줘야 하는데, 관리하기가 번거롭다는 생각이 들었습니다.
그래서, 저는 이러한 문제를 해결하기 위해 MCP(Model Context Protocol)를 활용해보기로 했습니다.
MCP는 Anthropic에서 제안한 프로토콜로, Claude Code가 외부 도구 서버와 통신할 수 있게 해주는 표준입니다. 쉽게 말해, Claude Code에게 "이 도구들만 사용할 수 있어"라고 명확하게 정의해줄 수 있는 방법입니다.
MCP 서버는 독립적인 프로세스로 실행되며, Claude Code는 필요할 때 이 서버에 정의된 도구들을 호출합니다. 중요한 점은 MCP 서버에서 정의한 도구만 사용할 수 있다는 것입니다. 관리자 전체 권한을 주는 것이 아니라, 초안 생성, 초안 조회, 초안 수정 같은 필요한 기능만 노출할 수 있습니다.
제가 만든 blog-mcp 서버는 다음과 같은 구조로 되어 있습니다:
index.ts: MCP 서버 진입점. 도구 목록을 정의하고, 각 도구 호출을 처리
api-client.ts: 블로그 백엔드 API와 통신하는 클라이언트
tools/: 개별 도구 구현 (create-draft, list-posts, get-writing-guidelines 등)
constants/persona.ts: 저의 글쓰기 스타일과 페르소나 정의
Claude Code 세션이 시작되면, .mcp.json 설정에 따라 MCP 서버가 자동으로 실행됩니다. 이후 Claude Code는 대화 중에 필요하다고 판단되면 MCP 도구를 호출하고, 그 결과를 활용해서 작업을 이어갑니다.
처음에는 기존 블로그 관리자 페이지에 있는 'AI 개선 제안 받기' 기능과 동일한 방식으로 MCP를 구현했습니다. 즉, Claude Code가 초안을 작성하면 백엔드의 Gemini API를 호출해서 SEO 분석과 개선 제안을 받는 방식이었습니다.
그런데 곰곰이 생각해보니, 이상한 점이 있었습니다. 제가 Claude Code로 사용하고 있는 모델은 Opus 4.5입니다. 반면 백엔드에서 AI 개선 제안에 사용하는 모델은 Gemini 2.5 Flash입니다. Opus 4.5의 품질이 더 좋을 것으로 판단되는데, 굳이 한 번 더 다른 AI에게 요청할 필요가 있을까요?
결국, Claude Code 대화 세션 자체에서 이미 AI 개선 제안을 받은 것처럼 작성될 수 있도록 하면, Gemini API 호출 없이도 고품질의 글을 작성할 수 있겠다는 생각이 들었습니다.
이 아이디어를 실현하기 위해 get_writing_guidelines 도구를 개선했습니다. 기존에는 단순히 페르소나 정보만 반환했다면, 이제는 1회 호출로 모든 가이드라인을 제공합니다:
저자 페르소나: 문체 특성, 자주 사용하는 표현, 어조 특성
SEO 최적화 가이드라인: 제목, 본문 구조, 메타 요소, E-E-A-T 원칙
금지 사항: 톤 변경, 과도한 구조화, 마케팅 톤 등
Few-shot 예시: 최근 게시된 글 3~5개의 제목과 요약
체크리스트: 페르소나와 SEO 확인 항목
Few-shot 예시는 최근에 제가 작성한 실제 글들입니다. Claude가 이 예시들을 참고하면, 단순히 가이드라인을 따르는 것을 넘어서 실제 제 글의 어조와 흐름을 더 정확하게 파악할 수 있습니다. 마치 "이런 식으로 써줘"라고 샘플을 보여주는 것과 같습니다.
개선 전에는 이런 흐름이었습니다:
Claude Code가 get_writing_guidelines() 호출 → 기본 페르소나만 획득
Claude Code가 analyze_seo() 호출 → Gemini API로 SEO 제안 획득
Claude Code가 글 작성
개선 후에는 이렇게 단순해졌습니다:
Claude Code가 get_writing_guidelines() 호출 → 페르소나 + SEO + Few-shot 예시 (1회 호출)
Claude Code (Opus 4.5)가 직접 고품질 글 작성
Gemini API 의존성을 제거하고, 더 높은 품질의 모델이 직접 글을 작성하게 된 것입니다.
핵심 변경 사항은 get-writing-guidelines.ts에 있습니다:
export async function getWritingGuidelines(
apiClient: BlogApiClient,
input: GetWritingGuidelinesInput,
): Promise<string> {
const { includeFewShot, fewShotCount } = input;
if (!includeFewShot) {
return getFullWritingGuidelines();
}
// 최근 게시된 한국어 글 조회 (Few-shot 예시용)
const postsResponse = await apiClient.listPosts(1, fewShotCount * 2, 'ko');
// excerpt가 있는 글만 필터링하여 Few-shot 예시 생성
const fewShotExamples = postsResponse.posts
.filter((post) => post.excerpt && post.excerpt.length > 50)
.slice(0, fewShotCount)
.map((post) => ({
title: post.title,
excerpt: post.excerpt || '',
}));
return getFullWritingGuidelines(fewShotExamples);
}이 코드는 최근 게시된 글에서 요약(excerpt)을 추출하여 Few-shot 예시로 제공합니다.
MCP를 직접 만들어서 사용해보니, 몇 가지 깨달음이 있었습니다.
첫째, 권한 분리가 명확해집니다. 블로그 초안 관련 기능만 노출하고, 게시글 삭제나 사용자 관리 같은 위험한 작업은 아예 접근할 수 없게 됩니다. AI가 실수하더라도 피해 범위가 제한됩니다.
둘째, 도구 정의가 문서 역할을 합니다. MCP 도구의 description을 잘 작성해두면, Claude Code가 언제 어떤 도구를 사용해야 하는지 스스로 판단합니다. "초안 작성 전에 get_writing_guidelines를 먼저 호출하세요"라고 설명해두면, 실제로 그렇게 동작합니다.
셋째, 더 나은 AI 모델을 활용할 수 있습니다. 기존에는 비용 효율성 때문에 Gemini Flash를 사용했지만, Claude Code 세션에서는 이미 고성능 모델이 동작하고 있습니다. 이 점을 활용하면 추가 API 호출 없이도 높은 품질을 얻을 수 있습니다.
이 글 자체도 방금 개선한 blog-mcp를 통해 초안이 작성되었습니다. get_writing_guidelines로 가이드라인을 확인하고, 대화 내용을 종합해서 초안을 업데이트하는 과정이 실제로 잘 동작하는지 검증하는 의미도 있었습니다. 앞으로 Claude Code와 대화하며 얻은 지식들을 블로그에 정리하는 작업이 한결 수월해질 것 같습니다.