알림 시스템

두 파이프라인 — REPL 내 토스터 큐와 OS 레벨 터미널 알림.

01

개요

Claude Code의 알림 시스템은 두 개의 독립적인 파이프라인으로 구성됩니다. 하나는 REPL 내부에서 동작하는 토스트(Toast) 큐이고, 다른 하나는 운영체제 레벨의 터미널 알림입니다. 이 두 파이프라인은 서로 다른 사용 사례를 지원하며, 사용자 주의를 효과적으로 관리합니다.

다루는 소스 파일: notifications/toastQueue.tsnotifications/osNotifier.tshooks/useNotification.tsnotifications/channels.ts

핵심 설계 원칙:

02

Toast Queue 파이프라인

Toast Queue는 REPL 내부에 표시되는 일시적 알림 메시지를 관리합니다. 새 알림이 추가되면 우선순위에 따라 정렬되고, 지정된 시간 후 자동으로 사라집니다.

// Toast Queue — 우선순위 정렬과 자동 소멸
interface Toast {
  id: string
  message: string
  priority: number      // 높을수록 먼저 표시
  duration: number      // ms 단위 표시 시간
  foldable: boolean    // 접기 가능 여부
  category: string     // fold 그룹 키
}

class ToastQueue {
  private queue: Toast[] = []

  push(toast: Toast): void {
    this.queue.push(toast)
    this.queue.sort((a, b) => b.priority - a.priority)
    this.fold()        // 같은 카테고리 알림 접기
    this.scheduleExpiry(toast)
  }
}

우선순위 정렬

각 토스트에는 우선순위가 할당됩니다. 에러 알림은 높은 우선순위를, 정보성 알림은 낮은 우선순위를 가집니다. 큐는 항상 우선순위 내림차순으로 정렬되어 가장 중요한 알림이 먼저 표시됩니다.

Fold 메커니즘

같은 카테고리의 알림이 여러 개 쌓이면 접기(fold)가 적용됩니다. 예를 들어 "파일 저장 완료" 알림이 5개 연속으로 들어오면 "파일 저장 완료 (x5)"로 접혀서 표시됩니다. 이를 통해 반복적인 알림이 화면을 가리는 것을 방지합니다.

// Fold 메커니즘 — 같은 카테고리 알림 접기
private fold(): void {
  const groups = groupBy(this.queue, t => t.category)
  for (const [category, toasts] of groups) {
    if (toasts.length > 1 && toasts[0].foldable) {
      const folded = {
        ...toasts[0],
        message: `${toasts[0].message} (x${toasts.length})`,
        id: foldedId(category)
      }
      this.queue = this.queue.filter(t => t.category !== category)
      this.queue.push(folded)
    }
  }
}
03

14개 알림 훅 카탈로그

알림 시스템은 14개의 React 훅을 제공하여 다양한 컴포넌트에서 알림을 쉽게 사용할 수 있습니다. 각 훅은 특정 사용 사례에 최적화되어 있습니다.

04

OS 알림 채널

터미널 에뮬레이터마다 알림을 지원하는 방식이 다릅니다. OS Notifier는 현재 터미널을 감지하고 최적의 채널을 선택합니다.

// OS 알림 채널 선택 로직
function selectNotificationChannel(): NotificationChannel {
  if (isITerm2())   return 'osc9'      // iTerm2 OSC 9 프로토콜
  if (isKitty())    return 'kitty'     // Kitty 전용 프로토콜
  if (isGhostty())  return 'ghostty'   // Ghostty 전용 프로토콜
  return 'bel'                         // 범용 BEL (0x07) 폴백
}

백그라운드 태스크 축소

장시간 실행되는 작업(파일 인덱싱, MCP 서버 연결 등)은 토스트가 축소되어 상태 표시줄에 작은 인디케이터로 표시됩니다. 작업이 완료되면 OS 알림이 발송되어 사용자가 터미널 밖에 있어도 알 수 있습니다.

딥 다이브 — MCP 채널 알림과 6레이어 보안

MCP(Model Context Protocol) 서버에서 오는 알림은 6단계 보안 검증을 거칩니다:

  1. 출처 검증: 알림이 등록된 MCP 서버에서 왔는지 확인
  2. 스키마 검증: 알림 페이로드가 유효한 형식인지 확인
  3. 레이트 리밋: 서버당 초당 최대 알림 수 제한
  4. 콘텐츠 필터링: 악의적인 이스케이프 시퀀스 제거
  5. 사용자 설정: 사용자가 해당 서버의 알림을 허용했는지 확인
  6. 표시 격리: MCP 알림은 별도의 시각적 스타일로 표시되어 시스템 알림과 구분
05

핵심 요약

핵심 포인트

  • 알림 시스템은 두 파이프라인으로 구성됩니다: REPL 내 Toast Queue와 OS 레벨 터미널 알림
  • Toast Queue는 우선순위 정렬로 중요한 알림을 먼저 표시하고, fold 메커니즘으로 반복 알림을 접습니다
  • 14개의 React 훅이 다양한 알림 사용 사례를 지원합니다
  • OS 알림은 터미널 종류에 따라 최적의 채널(iTerm2 OSC9, Kitty, Ghostty, BEL)을 선택합니다
  • 백그라운드 태스크는 토스트가 축소되어 상태 표시줄에 표시되고, 완료 시 OS 알림이 발송됩니다
  • MCP 채널 알림은 6레이어 보안 검증(출처, 스키마, 레이트 리밋, 콘텐츠 필터, 사용자 설정, 표시 격리)을 거칩니다
06

지식 확인

퀴즈 — 5문제

Q1. Toast Queue의 fold 메커니즘이 해결하는 문제는 무엇인가요?

  • A) 메모리 사용량을 줄이기 위해 오래된 알림을 삭제한다
  • B) 알림의 글꼴 크기를 줄여서 더 많은 알림을 표시한다
  • C) 같은 카테고리의 반복 알림을 하나로 접어서 화면을 가리지 않도록 한다
  • D) 알림을 파일에 로깅하여 나중에 확인할 수 있도록 한다
Fold 메커니즘은 같은 카테고리의 알림이 여러 개 쌓이면 "메시지 (xN)" 형태로 접어서 하나의 토스트로 표시합니다. 이를 통해 반복적인 알림이 화면을 과도하게 차지하는 것을 방지합니다.

Q2. OS 알림에서 BEL 채널이 폴백으로 사용되는 이유는?

  • A) 가장 시각적으로 풍부한 알림을 제공하기 때문
  • B) 보안이 가장 강력하기 때문
  • C) 알림 메시지 내용을 포함할 수 있기 때문
  • D) \x07 한 바이트로 거의 모든 터미널에서 지원되기 때문
BEL(\x07)은 가장 기본적인 터미널 알림으로, 거의 모든 터미널 에뮬레이터에서 지원됩니다. iTerm2 OSC9, Kitty, Ghostty 전용 프로토콜을 사용할 수 없는 터미널에서도 최소한의 알림을 제공합니다.

Q3. 두 알림 파이프라인(Toast Queue, OS Notifier)이 분리된 이유는?

  • A) 기술적 제약으로 하나로 합칠 수 없기 때문
  • B) Toast는 REPL 내부에서, OS 알림은 사용자가 터미널 밖에 있을 때를 위한 서로 다른 사용 사례를 지원하기 때문
  • C) Toast는 에러용, OS 알림은 성공용으로 역할이 다르기 때문
  • D) 멀티스레드 환경에서의 경쟁 조건을 방지하기 위해
Toast Queue는 사용자가 REPL을 보고 있을 때 비침습적 인라인 알림을 제공합니다. OS Notifier는 사용자가 다른 앱으로 전환했을 때 데스크톱 알림으로 주의를 끕니다. 서로 다른 주의 상태를 대상으로 합니다.

Q4. MCP 채널 알림의 6레이어 보안에서 "콘텐츠 필터링"이 하는 일은?

  • A) 악의적인 터미널 이스케이프 시퀀스를 제거하여 터미널 조작을 방지한다
  • B) 알림 메시지의 길이를 제한한다
  • C) 특정 언어의 메시지만 허용한다
  • D) 알림 메시지를 암호화한다
MCP 서버에서 오는 알림에 악의적인 ANSI 이스케이프 시퀀스(예: 커서 이동, 화면 클리어)가 포함되면 터미널 UI가 조작될 수 있습니다. 콘텐츠 필터링 레이어가 이런 시퀀스를 제거하여 안전한 텍스트만 표시합니다.

Q5. 백그라운드 태스크의 토스트가 축소되는 시점은 언제인가요?

  • A) 사용자가 명시적으로 축소 버튼을 누를 때
  • B) 태스크가 에러로 실패할 때
  • C) 장시간 실행되는 작업이 시작되어 일정 시간이 지났을 때
  • D) 다른 더 높은 우선순위의 알림이 들어올 때
파일 인덱싱, MCP 서버 연결 등 장시간 실행되는 작업은 일정 시간 후 전체 토스트에서 상태 표시줄의 작은 인디케이터로 축소됩니다. 이를 통해 화면 공간을 절약하면서도 작업 진행 상태를 계속 표시합니다.
0 / 5