🤖

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

⚠️

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

이미지 로딩 중...

Session과 Message 시스템 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 4. · 15 Views

Session과 Message 시스템 완벽 가이드

Claude Code의 세션과 메시지 시스템을 깊이 있게 다룹니다. 대화 상태 관리부터 메시지 처리, 프롬프트 구성, 대화 압축, 실행 취소까지 AI 에이전트의 핵심 아키텍처를 살펴봅니다.


목차

  1. session_디렉토리_구조
  2. Session_네임스페이스와_CRUD
  3. MessageV2_시스템
  4. SessionPrompt_프롬프트_처리
  5. SessionCompaction_대화_압축
  6. SessionRevert_실행_취소_다시_실행

1. session 디렉토리 구조

김개발 씨는 Claude Code 소스 코드를 처음 열어보고 당황했습니다. "session 폴더 안에 파일이 이렇게 많다니..." 대체 이 파일들은 각각 무슨 역할을 하는 걸까요?

선배 박시니어 씨가 옆에서 "이 구조만 이해하면 AI 에이전트의 핵심이 보여요"라고 말했습니다.

session 디렉토리는 AI 에이전트의 대화 상태를 관리하는 핵심 모듈들이 모여 있는 곳입니다. 마치 호텔의 프론트 데스크처럼, 손님(사용자)의 체크인부터 체크아웃까지 모든 기록을 관리합니다.

이 구조를 이해하면 AI 에이전트가 어떻게 대화를 기억하고 처리하는지 한눈에 파악할 수 있습니다.

다음 코드를 살펴봅시다.

// session 디렉토리의 핵심 구조
src/session/
├── Session.ts          // 세션 CRUD 및 네임스페이스
├── MessageV2.ts        // 메시지 처리 시스템
├── SessionPrompt.ts    // 프롬프트 구성 로직
├── SessionCompaction.ts // 대화 압축 알고리즘
├── SessionRevert.ts    // 실행 취소/다시 실행
├── SessionCost.ts      // 비용 계산
├── SessionSummary.ts   // 대화 요약
└── types.ts            // 공통 타입 정의

// 각 모듈의 책임 분리 원칙
// Session.ts: 세션 생명주기 관리
// MessageV2.ts: 메시지 변환 및 검증
// SessionPrompt.ts: API 요청용 프롬프트 조립

김개발 씨는 입사 첫 주에 Claude Code 프로젝트를 분석하는 과제를 받았습니다. 터미널을 열고 소스 코드 디렉토리로 이동했습니다.

수많은 폴더 중에서 session이라는 폴더가 눈에 들어왔습니다. "session이라...

뭔가 중요해 보이는데?" 김개발 씨는 폴더를 열어보았습니다. Session.ts, MessageV2.ts, SessionPrompt.ts 등 여러 파일이 있었습니다.

각 파일이 무슨 역할을 하는지 감이 오지 않았습니다. 마침 지나가던 박시니어 씨가 김개발 씨의 모니터를 보더니 미소를 지었습니다.

"아, session 폴더를 보고 있구나. 여기가 바로 AI 에이전트의 심장이야." 그렇다면 session 디렉토리는 정확히 무엇을 담당할까요?

쉽게 비유하자면, session 디렉토리는 마치 호텔의 프론트 데스크 시스템과 같습니다. 손님이 체크인하면 방을 배정하고, 머무는 동안의 모든 요청을 기록하고, 체크아웃할 때 정산을 처리합니다.

AI 에이전트도 마찬가지입니다. 사용자가 대화를 시작하면 세션을 생성하고, 대화 내용을 저장하고, 대화가 끝나면 정리합니다.

Session.ts는 프론트 데스크의 메인 카운터입니다. 세션을 생성하고, 조회하고, 수정하고, 삭제하는 모든 CRUD 작업을 담당합니다.

MessageV2.ts는 투숙객의 요청을 처리하는 컨시어지 서비스입니다. 사용자의 메시지를 받아서 AI가 이해할 수 있는 형태로 변환합니다.

SessionPrompt.ts는 주방에 주문서를 전달하는 웨이터입니다. 사용자의 요청을 API가 처리할 수 있는 프롬프트 형태로 조립합니다.

SessionCompaction.ts는 기록 보관실의 아키비스트입니다. 대화가 너무 길어지면 핵심만 남기고 압축합니다.

SessionRevert.ts는 실수를 바로잡는 매니저입니다. 잘못된 작업을 되돌리거나 다시 실행할 수 있게 해줍니다.

이렇게 각 파일이 명확한 책임을 가지고 있습니다. 이것이 바로 단일 책임 원칙이 적용된 좋은 설계입니다.

박시니어 씨가 덧붙였습니다. "이런 구조 덕분에 한 기능을 수정해도 다른 기능에 영향을 주지 않아.

유지보수가 훨씬 쉬워지지." 김개발 씨는 고개를 끄덕였습니다. 단순히 파일을 나눈 것이 아니라, 각 모듈이 독립적으로 동작할 수 있도록 설계되어 있었습니다.

이제 각 파일을 하나씩 자세히 살펴볼 차례입니다.

실전 팁

💡 - 새로운 기능을 추가할 때는 기존 파일을 수정하기보다 새 모듈을 만드는 것이 좋습니다

  • 각 모듈 간의 의존성을 최소화하면 테스트와 유지보수가 쉬워집니다

2. Session 네임스페이스와 CRUD

김개발 씨는 Session.ts 파일을 열었습니다. 파일 맨 위에 namespace Session이라고 선언되어 있었습니다.

"네임스페이스? 요즘에도 이걸 쓰나?" 박시니어 씨가 말했습니다.

"관련 함수들을 논리적으로 그룹화할 때 아직도 유용해."

Session 네임스페이스는 세션 관련 모든 함수를 하나의 이름 아래 묶어둔 컨테이너입니다. 마치 도서관에서 같은 주제의 책을 한 서가에 모아두는 것처럼, create, load, save, delete 같은 세션 관련 함수들이 Session이라는 이름 아래 정리되어 있습니다.

이를 통해 코드의 가독성과 유지보수성이 크게 향상됩니다.

다음 코드를 살펴봅시다.

// Session 네임스페이스의 핵심 CRUD 함수들
export namespace Session {
  // 새 세션 생성
  export function create(options: SessionOptions): SessionState {
    return {
      id: uuidv4(),
      messages: [],
      createdAt: Date.now(),
      ...options
    };
  }

  // 세션 로드 (파일에서 읽기)
  export async function load(sessionId: string): Promise<SessionState | null> {
    const filePath = getSessionPath(sessionId);
    if (!existsSync(filePath)) return null;
    return JSON.parse(await readFile(filePath, 'utf-8'));
  }

  // 세션 저장 (파일에 쓰기)
  export async function save(session: SessionState): Promise<void> {
    const filePath = getSessionPath(session.id);
    await writeFile(filePath, JSON.stringify(session, null, 2));
  }
}

김개발 씨가 Session.ts 파일을 열자 가장 먼저 눈에 띈 것은 namespace 키워드였습니다. ES6 모듈이 등장한 이후로 네임스페이스는 잘 사용하지 않는다고 들었는데, 왜 여기서는 사용하고 있을까요?

박시니어 씨가 설명을 시작했습니다. "네임스페이스는 관련 함수들을 하나의 이름 아래 묶을 때 여전히 유용해.

Session.create(), Session.load()처럼 호출하면 이 함수가 세션과 관련된 것임을 바로 알 수 있잖아." 그렇다면 네임스페이스란 정확히 무엇일까요? 쉽게 비유하자면, 네임스페이스는 마치 회사의 부서와 같습니다.

영업부, 개발부, 인사부가 있듯이, Session 네임스페이스 안에는 세션 관련 함수들만 모여 있습니다. 다른 개발자가 코드를 볼 때 Session.create()만 봐도 "아, 세션을 생성하는구나"라고 바로 이해할 수 있습니다.

Session 네임스페이스의 핵심은 CRUD 함수들입니다. CRUD는 Create, Read, Update, Delete의 약자로, 데이터를 다루는 가장 기본적인 네 가지 작업을 의미합니다.

create 함수는 새로운 세션을 만듭니다. UUID를 생성하고, 빈 메시지 배열을 초기화하고, 생성 시간을 기록합니다.

사용자가 Claude Code를 처음 실행할 때 이 함수가 호출됩니다. load 함수는 기존 세션을 불러옵니다.

세션 ID를 받아서 파일 시스템에서 해당 세션 데이터를 읽어옵니다. 이전에 나눴던 대화를 이어서 할 때 사용됩니다.

save 함수는 현재 세션 상태를 저장합니다. 사용자가 메시지를 보내거나 AI가 응답할 때마다 세션이 업데이트되고, 이 함수가 호출되어 변경 사항이 파일에 기록됩니다.

김개발 씨가 질문했습니다. "그런데 왜 데이터베이스가 아니라 파일 시스템에 저장하나요?" 박시니어 씨가 답했습니다.

"Claude Code는 로컬에서 실행되는 CLI 도구야. 별도의 데이터베이스 설정 없이도 바로 사용할 수 있어야 하거든.

파일 시스템을 사용하면 사용자가 직접 세션 파일을 확인하거나 백업할 수도 있고." 실제로 세션 파일은 사용자의 홈 디렉토리 아래 .claude 폴더에 JSON 형태로 저장됩니다. 이 덕분에 사용자는 자신의 대화 기록을 완전히 통제할 수 있습니다.

주의할 점도 있습니다. 세션을 저장할 때는 반드시 비동기 함수를 사용해야 합니다.

파일 쓰기는 시간이 걸리는 작업이기 때문에, 동기 함수를 사용하면 프로그램이 멈춘 것처럼 느껴질 수 있습니다. 김개발 씨는 이제 Session 네임스페이스의 구조를 이해했습니다.

다음은 이 세션 안에 저장되는 메시지가 어떻게 처리되는지 알아볼 차례입니다.

실전 팁

💡 - 네임스페이스를 사용하면 함수 이름 충돌을 방지하고 코드의 의도를 명확히 할 수 있습니다

  • 세션 저장 시 JSON.stringify의 세 번째 인자로 2를 전달하면 가독성 좋은 포맷으로 저장됩니다

3. MessageV2 시스템

김개발 씨는 Session 안에 저장되는 messages 배열이 궁금해졌습니다. "메시지가 그냥 문자열로 저장되나요?" 박시니어 씨가 웃으며 MessageV2.ts 파일을 열었습니다.

"메시지 처리는 생각보다 복잡해. 텍스트뿐만 아니라 이미지, 도구 호출, 결과까지 다 처리해야 하거든."

MessageV2 시스템은 다양한 유형의 메시지를 통합적으로 처리하는 모듈입니다. 마치 우체국에서 편지, 소포, 등기 우편을 각각 다르게 처리하듯이, 텍스트 메시지, 이미지 메시지, 도구 호출 메시지를 각각 적절한 방식으로 변환하고 검증합니다.

V2라는 이름은 기존 메시지 시스템을 개선한 두 번째 버전임을 의미합니다.

다음 코드를 살펴봅시다.

// MessageV2의 핵심 타입 정의
type MessageContent =
  | { type: 'text'; text: string }
  | { type: 'image'; source: ImageSource }
  | { type: 'tool_use'; id: string; name: string; input: unknown }
  | { type: 'tool_result'; tool_use_id: string; content: string };

// 메시지 변환 함수
export namespace MessageV2 {
  // 사용자 메시지 생성
  export function createUserMessage(content: string): Message {
    return {
      role: 'user',
      content: [{ type: 'text', text: content }]
    };
  }

  // 도구 결과 메시지 생성
  export function createToolResult(toolUseId: string, result: string): Message {
    return {
      role: 'user',
      content: [{ type: 'tool_result', tool_use_id: toolUseId, content: result }]
    };
  }
}

김개발 씨는 메시지가 단순한 문자열이 아니라는 것을 알게 되었습니다. AI와의 대화에서는 텍스트만 주고받는 것이 아닙니다.

이미지를 보내기도 하고, AI가 도구를 호출하기도 하고, 그 결과를 다시 전달하기도 합니다. "일반 채팅 앱이랑은 완전히 다르네요." 김개발 씨가 말했습니다.

박시니어 씨가 고개를 끄덕였습니다. "맞아.

그래서 MessageV2라는 별도의 시스템이 필요한 거야. V2는 기존 시스템을 개선한 두 번째 버전이라는 뜻이고." 그렇다면 MessageV2는 어떻게 동작할까요?

쉽게 비유하자면, MessageV2는 마치 통역사와 같습니다. 한국어, 영어, 일본어를 모두 이해하고 번역할 수 있는 통역사처럼, 텍스트, 이미지, 도구 호출을 모두 이해하고 적절한 형태로 변환합니다.

메시지의 핵심은 content 배열입니다. 하나의 메시지 안에 여러 종류의 콘텐츠가 들어갈 수 있습니다.

예를 들어, 사용자가 "이 이미지에서 텍스트를 추출해줘"라고 말하면서 이미지를 첨부할 수 있습니다. 이 경우 content 배열에는 텍스트 요소와 이미지 요소가 함께 들어갑니다.

type 필드가 각 콘텐츠의 종류를 구분합니다. text는 일반 텍스트, image는 이미지, tool_use는 AI가 도구를 호출할 때, tool_result는 도구 실행 결과를 전달할 때 사용됩니다.

실무에서 가장 많이 사용되는 것은 createUserMessage 함수입니다. 사용자가 터미널에 입력한 텍스트를 API가 이해할 수 있는 메시지 형태로 변환합니다.

단순해 보이지만, 이 함수가 없으면 매번 메시지 구조를 직접 작성해야 합니다. createToolResult 함수도 중요합니다.

AI가 파일을 읽거나 명령어를 실행하면 그 결과를 다시 AI에게 전달해야 합니다. 이때 tool_use_id를 통해 어떤 도구 호출에 대한 결과인지 연결합니다.

김개발 씨가 질문했습니다. "그런데 왜 role이 항상 user인가요?

도구 결과는 시스템이 보내는 거 아닌가요?" 좋은 질문이었습니다. Claude API의 설계상, 도구 결과는 user 역할로 전달됩니다.

AI(assistant)가 도구를 호출하면, 그 결과는 마치 사용자가 답변하는 것처럼 user 역할로 전송됩니다. 이것은 대화의 흐름을 일관되게 유지하기 위한 설계 결정입니다.

주의할 점이 있습니다. 메시지를 생성할 때 content는 반드시 배열 형태여야 합니다.

문자열로 직접 전달하면 API에서 오류가 발생합니다. 초보 개발자들이 자주 하는 실수 중 하나입니다.

김개발 씨는 이제 메시지가 어떻게 구성되는지 이해했습니다. 다음은 이 메시지들이 어떻게 프롬프트로 조립되는지 알아볼 차례입니다.

실전 팁

💡 - 메시지 content는 항상 배열 형태로 전달해야 합니다

  • tool_use_id는 고유해야 하며, 도구 호출과 결과를 정확히 매칭하는 데 사용됩니다

4. SessionPrompt 프롬프트 처리

김개발 씨는 메시지가 어떻게 AI에게 전달되는지 궁금해졌습니다. "메시지를 그냥 API에 보내면 되는 거 아닌가요?" 박시니어 씨가 SessionPrompt.ts를 열며 말했습니다.

"실제로는 시스템 프롬프트, 대화 기록, 현재 요청을 모두 조립해서 보내야 해. 이 과정이 생각보다 복잡하지."

SessionPrompt는 API 요청에 필요한 프롬프트를 조립하는 모듈입니다. 마치 요리사가 여러 재료를 적절한 순서로 조합해 요리를 완성하듯이, 시스템 프롬프트, 이전 대화 내용, 현재 사용자 요청을 올바른 순서와 형식으로 조합합니다.

이 과정에서 토큰 제한, 컨텍스트 관리, 도구 정의 등 여러 요소를 고려해야 합니다.

다음 코드를 살펴봅시다.

// SessionPrompt의 프롬프트 조립 로직
export namespace SessionPrompt {
  // API 요청용 프롬프트 생성
  export function buildPrompt(session: SessionState, options: PromptOptions): APIRequest {
    const systemPrompt = buildSystemPrompt(options);
    const messages = prepareMessages(session.messages, options.maxTokens);
    const tools = getAvailableTools(options.toolset);

    return {
      model: options.model,
      system: systemPrompt,
      messages,
      tools,
      max_tokens: options.maxResponseTokens
    };
  }

  // 시스템 프롬프트 구성
  function buildSystemPrompt(options: PromptOptions): string {
    const parts = [BASE_SYSTEM_PROMPT];
    if (options.cwd) parts.push(`Working directory: ${options.cwd}`);
    if (options.customInstructions) parts.push(options.customInstructions);
    return parts.join('\n\n');
  }
}

김개발 씨는 단순히 메시지만 보내면 될 줄 알았습니다. 하지만 실제로는 그렇지 않았습니다.

AI에게 요청을 보내려면 여러 가지 요소를 함께 조립해야 합니다. 박시니어 씨가 비유를 들어 설명했습니다.

"레스토랑에서 주문할 때를 생각해봐. 손님이 '스테이크요'라고만 하면 웨이터가 알아서 굽기, 사이드 메뉴, 음료까지 다 정해서 주방에 전달하잖아.

SessionPrompt가 바로 그 웨이터 역할을 해." 그렇다면 SessionPrompt는 정확히 어떤 일을 할까요? 첫 번째로, 시스템 프롬프트를 구성합니다.

시스템 프롬프트는 AI에게 "너는 이런 역할이야"라고 알려주는 지시사항입니다. Claude Code의 경우 "당신은 소프트웨어 엔지니어링 작업을 돕는 CLI 도구입니다"라는 기본 지시사항에 현재 작업 디렉토리, 사용자 정의 지시사항 등이 추가됩니다.

두 번째로, 대화 기록을 준비합니다. 이전에 나눈 모든 대화를 보내야 AI가 맥락을 이해할 수 있습니다.

하지만 토큰 제한이 있기 때문에 모든 대화를 보낼 수 없는 경우도 있습니다. 이때 prepareMessages 함수가 중요한 메시지는 유지하면서 불필요한 부분을 정리합니다.

세 번째로, 사용 가능한 도구를 정의합니다. Claude Code는 파일 읽기, 쓰기, Bash 명령 실행 등 다양한 도구를 사용할 수 있습니다.

이 도구들의 이름, 설명, 파라미터 스키마를 API 요청에 포함시켜야 AI가 적절한 도구를 선택할 수 있습니다. 실제 코드를 살펴보겠습니다.

buildPrompt 함수는 세 가지 주요 함수를 호출합니다. buildSystemPrompt로 시스템 프롬프트를 만들고, prepareMessages로 메시지 배열을 준비하고, getAvailableTools로 도구 목록을 가져옵니다.

buildSystemPrompt 함수는 여러 부분을 합쳐서 하나의 시스템 프롬프트를 만듭니다. 기본 프롬프트에 현재 작업 디렉토리 정보를 추가하고, 사용자가 CLAUDE.md 파일에 작성한 커스텀 지시사항도 포함합니다.

이 모든 것이 parts 배열에 담기고, 줄바꿈 두 개로 연결됩니다. 김개발 씨가 물었습니다.

"그런데 maxTokens는 뭐예요?" 토큰은 AI가 텍스트를 처리하는 단위입니다. 대략 영어 단어 하나가 1-2토큰, 한글 한 글자가 1토큰 정도입니다.

Claude API는 한 번의 요청에서 처리할 수 있는 토큰 수에 제한이 있습니다. 대화가 길어지면 이 제한을 초과할 수 있기 때문에, prepareMessages 함수가 토큰 수를 계산하면서 메시지를 준비합니다.

주의할 점이 있습니다. 시스템 프롬프트가 너무 길면 실제 대화에 사용할 수 있는 토큰이 줄어듭니다.

따라서 시스템 프롬프트는 필요한 정보만 간결하게 포함해야 합니다. 김개발 씨는 이제 프롬프트가 어떻게 조립되는지 이해했습니다.

하지만 대화가 정말 길어지면 어떻게 할까요? 그것이 바로 다음에 알아볼 SessionCompaction의 역할입니다.

실전 팁

💡 - 시스템 프롬프트는 간결하게 유지하여 대화에 더 많은 토큰을 할당하세요

  • 커스텀 지시사항은 CLAUDE.md 파일에 작성하면 자동으로 시스템 프롬프트에 포함됩니다

5. SessionCompaction 대화 압축

김개발 씨는 Claude Code를 몇 시간 동안 사용하다가 이상한 현상을 발견했습니다. 분명히 수백 개의 메시지를 주고받았는데, 응답 속도가 크게 느려지지 않았습니다.

"대화가 길어지면 느려져야 하는 거 아닌가요?" 박시니어 씨가 미소 지었습니다. "SessionCompaction이 뒤에서 열심히 일하고 있거든."

SessionCompaction은 긴 대화를 압축하여 토큰 사용량을 줄이는 모듈입니다. 마치 책의 요약본처럼, 긴 대화에서 핵심 내용만 추출하여 저장합니다.

이를 통해 무한한 대화가 가능해지고, 동시에 응답 속도와 비용 효율성을 유지할 수 있습니다. 압축된 요약은 새로운 대화의 맥락으로 사용됩니다.

다음 코드를 살펴봅시다.

// SessionCompaction의 압축 로직
export namespace SessionCompaction {
  // 대화 압축 실행
  export async function compact(
    session: SessionState,
    options: CompactionOptions
  ): Promise<SessionState> {
    // 압축이 필요한지 확인
    if (!shouldCompact(session, options.threshold)) {
      return session;
    }

    // 이전 메시지들을 요약
    const summary = await summarizeMessages(
      session.messages.slice(0, -options.keepRecent)
    );

    // 요약 + 최근 메시지로 새 세션 구성
    return {
      ...session,
      messages: [createSummaryMessage(summary), ...session.messages.slice(-options.keepRecent)],
      compactedAt: Date.now()
    };
  }
}

김개발 씨는 의문이 들었습니다. 토큰 제한이 있다면, 대화를 계속할수록 언젠가는 한계에 도달할 텐데요.

그런데 Claude Code는 몇 시간을 사용해도 문제없이 동작했습니다. 박시니어 씨가 설명했습니다.

"비결은 압축이야. 오래된 대화를 요약해서 저장하면 토큰을 절약할 수 있거든." 그렇다면 SessionCompaction은 어떻게 동작할까요?

쉽게 비유하자면, 회의록 작성자를 생각해보세요. 3시간짜리 회의 내용을 전부 기록하면 수십 페이지가 됩니다.

하지만 숙련된 작성자는 핵심 결정사항과 액션 아이템만 추려서 한두 페이지로 요약합니다. SessionCompaction도 마찬가지입니다.

압축 과정은 세 단계로 이루어집니다. 첫 번째로, 압축이 필요한지 판단합니다.

shouldCompact 함수가 현재 대화의 토큰 수가 임계값을 초과했는지 확인합니다. 아직 여유가 있다면 압축하지 않습니다.

두 번째로, 이전 메시지를 요약합니다. 최근 메시지 몇 개는 그대로 유지하고, 나머지 오래된 메시지들을 AI를 통해 요약합니다.

이 요약에는 대화의 맥락, 중요한 결정사항, 현재 작업 상태 등이 포함됩니다. 세 번째로, 새로운 세션을 구성합니다.

요약된 내용을 담은 메시지가 맨 앞에 오고, 그 뒤에 최근 메시지들이 이어집니다. 이렇게 하면 AI는 여전히 전체 맥락을 이해하면서도 토큰 사용량은 크게 줄어듭니다.

keepRecent 옵션이 중요합니다. 이 값은 압축하지 않고 그대로 유지할 최근 메시지의 개수입니다.

너무 적으면 최근 맥락이 손실되고, 너무 많으면 압축 효과가 줄어듭니다. 보통 최근 10-20개 정도의 메시지를 유지합니다.

김개발 씨가 질문했습니다. "요약할 때 중요한 정보가 빠지면 어떡해요?" 좋은 질문이었습니다.

이것이 바로 압축 알고리즘의 핵심 과제입니다. summarizeMessages 함수는 단순히 텍스트를 줄이는 것이 아니라, AI에게 "이 대화에서 가장 중요한 결정사항, 현재 작업 중인 파일, 발생한 오류 등을 정리해달라"고 요청합니다.

실제로 Claude Code의 압축 요약에는 다음과 같은 정보가 포함됩니다. 현재 작업 중인 프로젝트와 파일, 이미 완료한 작업 목록, 진행 중인 작업의 상태, 발견된 문제나 오류, 사용자의 선호사항이나 지시사항 등입니다.

주의할 점이 있습니다. 압축은 비가역적입니다.

한번 압축되면 원본 메시지는 복구할 수 없습니다. 따라서 압축 전에 세션을 백업하거나, 정말 중요한 대화는 별도로 저장해두는 것이 좋습니다.

김개발 씨는 무한한 대화가 가능한 비결을 이해했습니다. 하지만 때로는 작업을 되돌려야 할 때도 있습니다.

그것이 바로 다음에 알아볼 SessionRevert의 역할입니다.

실전 팁

💡 - 중요한 대화는 압축 전에 별도로 저장해두세요

  • keepRecent 값이 너무 작으면 최근 맥락이 손실될 수 있습니다

6. SessionRevert 실행 취소 다시 실행

김개발 씨가 Claude Code에게 파일 수정을 요청했습니다. 그런데 결과물이 예상과 달랐습니다.

"이거 원래대로 돌릴 수 있나요?" 박시니어 씨가 말했습니다. "당연하지.

SessionRevert가 바로 그 일을 해. 마치 문서 편집기의 실행 취소 기능처럼."

SessionRevert는 세션 상태를 이전 시점으로 되돌리거나 다시 실행하는 모듈입니다. 마치 게임의 세이브 포인트처럼, 특정 시점의 세션 상태를 기억하고 있다가 필요할 때 복원합니다.

이를 통해 AI의 실수를 쉽게 되돌리고, 여러 가지 접근 방식을 시도해볼 수 있습니다. 파일 변경까지 함께 되돌리는 기능도 제공합니다.

다음 코드를 살펴봅시다.

// SessionRevert의 실행 취소/다시 실행 로직
export namespace SessionRevert {
  // 특정 메시지 지점으로 되돌리기
  export async function revertTo(
    session: SessionState,
    messageIndex: number,
    options: RevertOptions
  ): Promise<SessionState> {
    // 되돌릴 메시지 범위 확인
    const messagesToRevert = session.messages.slice(messageIndex + 1);

    // 파일 변경사항도 함께 되돌리기
    if (options.revertFiles) {
      await revertFileChanges(messagesToRevert);
    }

    // 세션 상태 업데이트
    return {
      ...session,
      messages: session.messages.slice(0, messageIndex + 1),
      revertedAt: Date.now()
    };
  }

  // 파일 변경사항 되돌리기
  async function revertFileChanges(messages: Message[]): Promise<void> {
    for (const msg of messages.reverse()) {
      const fileOps = extractFileOperations(msg);
      for (const op of fileOps) {
        await op.revert(); // 각 파일 작업을 역순으로 취소
      }
    }
  }
}

모든 개발자가 한 번쯤 경험했을 것입니다. 뭔가 잘못되어서 Ctrl+Z를 연타하게 되는 순간을요.

AI 에이전트를 사용할 때도 마찬가지입니다. AI가 파일을 잘못 수정하거나, 예상과 다른 코드를 생성할 수 있습니다.

김개발 씨도 그런 상황에 처했습니다. Claude Code에게 리팩토링을 요청했는데, 결과물이 마음에 들지 않았습니다.

"이걸 어떻게 되돌리죠?" 박시니어 씨가 미소 지으며 말했습니다. "Claude Code에는 실행 취소 기능이 있어.

세션 상태뿐만 아니라 파일 변경까지 되돌릴 수 있지." 그렇다면 SessionRevert는 어떻게 동작할까요? 쉽게 비유하자면, 타임머신을 생각해보세요.

특정 시점으로 돌아가면 그 이후에 일어난 모든 일이 사라집니다. SessionRevert도 마찬가지입니다.

특정 메시지 시점으로 돌아가면 그 이후의 대화와 작업이 모두 취소됩니다. revertTo 함수의 핵심은 messageIndex입니다.

이 인덱스 이후의 모든 메시지가 삭제됩니다. 예를 들어, 10개의 메시지가 있는 세션에서 messageIndex를 5로 지정하면, 6번째부터 10번째 메시지가 모두 사라집니다.

하지만 메시지만 삭제하면 문제가 있습니다. AI가 파일을 수정했다면, 그 수정 내용은 그대로 남아있습니다.

이것이 revertFiles 옵션의 역할입니다. 이 옵션이 활성화되면 파일 변경사항도 함께 되돌립니다.

revertFileChanges 함수는 삭제될 메시지들을 역순으로 순회합니다. 왜 역순일까요?

파일 A를 수정한 후 다시 수정했다면, 최신 수정부터 되돌려야 원래 상태로 복원할 수 있기 때문입니다. 마치 탑을 쌓을 때 맨 위 블록부터 제거하는 것과 같습니다.

각 메시지에서 파일 작업을 추출하는 extractFileOperations 함수도 중요합니다. AI의 응답에서 Write, Edit 같은 도구 호출을 찾아내고, 각각의 되돌리기 로직을 실행합니다.

김개발 씨가 질문했습니다. "그런데 원본 파일 내용은 어디에 저장되어 있나요?" 좋은 질문이었습니다.

Claude Code는 파일을 수정하기 전에 원본 내용을 기록해둡니다. 정확히는 Edit이나 Write 도구를 사용할 때 변경 전후의 내용이 함께 저장됩니다.

이 정보를 활용해서 파일을 원래 상태로 복원하는 것입니다. 주의할 점이 있습니다.

되돌리기는 세션 내의 변경사항만 되돌릴 수 있습니다. 사용자가 직접 파일을 수정했거나, 다른 도구로 변경한 내용은 되돌릴 수 없습니다.

또한 git을 사용하고 있다면, 되돌리기 전에 현재 상태를 커밋해두는 것이 안전합니다. 김개발 씨는 이제 session 디렉토리의 모든 핵심 모듈을 이해했습니다.

세션 생성부터 메시지 처리, 프롬프트 조립, 대화 압축, 실행 취소까지. 이 모듈들이 함께 동작하면서 Claude Code의 강력한 대화 관리 기능을 만들어냅니다.

실전 팁

💡 - 대규모 변경 전에는 git commit을 해두면 되돌리기가 더 안전합니다

  • revertFiles 옵션을 비활성화하면 대화만 되돌리고 파일은 유지할 수 있습니다

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

#TypeScript#Session#Message#Agent#StateManagement#AI,Agent,TypeScript

댓글 (0)

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

함께 보면 좋은 카드 뉴스

마이크로서비스 배포 완벽 가이드

Kubernetes를 활용한 마이크로서비스 배포의 핵심 개념부터 실전 운영까지, 초급 개발자도 쉽게 따라할 수 있는 완벽 가이드입니다. 실무에서 바로 적용 가능한 배포 전략과 노하우를 담았습니다.

Application Load Balancer 완벽 가이드

AWS의 Application Load Balancer를 처음 배우는 개발자를 위한 실전 가이드입니다. ALB 생성부터 ECS 연동, 헬스 체크, HTTPS 설정까지 실무에 필요한 모든 내용을 다룹니다. 초급 개발자도 쉽게 따라할 수 있도록 단계별로 설명합니다.

고객 상담 AI 시스템 완벽 구축 가이드

AWS Bedrock Agent와 Knowledge Base를 활용하여 실시간 고객 상담 AI 시스템을 구축하는 방법을 단계별로 학습합니다. RAG 기반 지식 검색부터 Guardrails 안전 장치, 프론트엔드 연동까지 실무에 바로 적용 가능한 완전한 시스템을 만들어봅니다.

에러 처리와 폴백 완벽 가이드

AWS API 호출 시 발생하는 에러를 처리하고 폴백 전략을 구현하는 방법을 다룹니다. ThrottlingException부터 서킷 브레이커 패턴까지, 실전에서 바로 활용할 수 있는 안정적인 에러 처리 기법을 배웁니다.

AWS Bedrock 인용과 출처 표시 완벽 가이드

AWS Bedrock의 Citation 기능을 활용하여 AI 응답의 신뢰도를 높이는 방법을 배웁니다. 출처 추출부터 UI 표시, 검증까지 실무에서 바로 사용할 수 있는 완전한 가이드입니다.