Files
2nd/10_Wiki/Topic_Programming/Architecture/VSCode_확장_구조와_생명주기.md
T
Antigravity Agent e2c5471046 wiki: Topic_Blog 신규 문서 일괄 추가 + ASTRA 성장 자산 동기화
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 09:55:38 +09:00

7.6 KiB

id, title, category, status, verification_status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, created_at, updated_at, review_reason, merge_history, tags, raw_sources, applied_in, github_commit
id title category status verification_status canonical_id aliases duplicate_of source_trust_level confidence_score created_at updated_at review_reason merge_history tags raw_sources applied_in github_commit
vscode-extension-structure-lifecycle VSCode 확장 구조와 생명주기 Architecture draft applied
VS Code Extension
activate
deactivate
Disposable
Webview
command 등록
extension API
A 0.93 2026-06-13 2026-06-13
vscode
extension
lifecycle
disposable
webview
astraai
AstraAI/src/extension.ts
AstraAI/package.json
AstraAI/src/features/_shared/eventSourcedStore.ts
AstraAI

VSCode 확장 구조와 생명주기

🎯 한 줄 통찰 (One-line insight)

VS Code 확장은 activate(context) 에서 깨어나 명령·뷰·이벤트를 등록하고 deactivate() 에서 정리되며, 모든 자원을 context.subscriptions 에 Disposable 로 등록해 두면 확장 종료 시 메모리/타이머/리스너가 누수 없이 일괄 정리된다 [S1].

🧠 핵심 개념 (Core concepts)

  1. activate(context): 확장 진입점. package.json 의 activationEvents 조건이 충족되면 호출된다. context: ExtensionContext 가 전역 상태·구독·시크릿 저장소를 제공 [S1].
  2. deactivate(): 종료 훅. 명시적으로 풀어야 하는 자원(외부 프로세스, 봇, 모델 언로드)을 여기서 정리 [S1].
  3. Disposable 패턴: { dispose(): void } 를 가진 객체. context.subscriptions.push(disposable) 하면 VS Code 가 종료 시 dispose() 를 호출 [S1].
  4. Command: vscode.commands.registerCommand(id, handler) 로 등록, package.jsoncontributes.commands 에 선언. 반환값이 Disposable [S1].
  5. Webview: HTML 기반 커스텀 UI. 확장↔웹뷰는 postMessage 로 통신. AstraAI 는 사이드바 대신 에디터 컬럼 에 패널로 띄운다 [S1].
  6. Configuration: vscode.workspace.getConfiguration('g1nation') 으로 설정 읽기, onDidChangeConfiguration 으로 변경 반응 [S1].
  7. SecretStorage: 토큰 등 민감정보는 context.secrets 에 저장(평문 설정 금지) [S1].

🧩 추출된 패턴 (Extracted patterns)

  • 모든 자원을 subscriptions 로: 명령·리스너·상태바·타이머·커스텀 dispose 콜백까지 전부 context.subscriptions.push(...) — 정리를 잊지 않는 구조적 보장 [S1].
  • 설정 변경 반응: onDidChangeConfiguration((e) => { if (!e.affectsConfiguration('g1nation.ollamaUrl')) return; ... }) — 관심 키만 필터링해 재설정 [S1].
  • lazy webview 전송: 매우 이른 활성화 시점엔 웹뷰가 아직 없을 수 있어 provider?._sendModels(...) 옵셔널 체이닝 + best-effort [S1].
  • getter 콜백으로 늦은 바인딩: 아직 안 만들어진 객체는 getProvider: () => provider 처럼 getter 로 주입 — 순환 의존/초기화 순서 문제 회피 [S1].
  • 워처 = disposable 반환 함수: startStocksWatcher(context) 가 타이머를 만들고 disposable 을 반환해 subscriptions 에 등록 → 종료 시 timer cleanup [S1].

📖 세부 내용 (Details)

activate 의 책임 순서 (AstraAI 실제 순서)

  1. 가시화(버전 popup/console) → 환경 진단.
  2. 부트스트랩(brain 디렉터리, 임베딩 감지, 기능 인벤토리) — 일부는 void 비차단.
  3. 인프라 초기화(health monitor, path resolver, config 검증).
  4. 핵심 객체 생성·주입(LMStudioClient, lifecycle, AgentExecutor, SidebarChatProvider, BridgeServer).
  5. 명령·리스너 등록.
  6. 워처 시작(stocks, daily briefing, growth cycle, sleep digest).
  7. 웹뷰 자동 오픈.

deactivate 의 책임

HealthCheckMonitor.dispose(), 인메모리 인덱스 해제(clearBrainTokenIndex() — Map 이 프로세스 수명 동안 안 비는 것 방지), 텔레그램 봇 stop, 모델 lifecycle dispose+unload. 명시적 정리가 필요한 것만 여기서 처리하고, subscriptions 로 등록된 것은 VS Code 가 알아서 정리한다 [S1].

설정·시크릿

const cfg = vscode.workspace.getConfiguration('g1nation');
const timeout = cfg.get<number>('lmStudio.idleTimeoutMs', 300000);  // 기본값 동반
const token = await context.secrets.get(TELEGRAM_TOKEN_SECRET_KEY); // 민감정보는 secrets

Webview 통신

확장→웹뷰는 webview.postMessage({ type: 'streamChunk', value }), 웹뷰→확장은 메시지 핸들러(sidebar/chatHandlers). 스트리밍은 streamStart/streamChunk/streamEnd 의 메시지 프로토콜로 표현 [참조: Agent 오케스트레이터 분해].

⚖️ 모순 및 업데이트 (Contradictions & updates)

  • 사이드바 뷰 제거(v2.81): 과거엔 activity bar 사이드바에 webview view 를 등록했으나, 현재는 에디터 컬럼 3에 패널로 띄운다. 대신 activity bar 에는 명령 링크만 있는 빈 TreeView 를 둔다 — 탭이 닫혀도 다시 열 수 있게 [S1].
  • activationEvents: 너무 광범위하면(예: *) 시작이 느려진다. 필요한 이벤트로 좁히는 것이 좋다(AstraAI 는 명령/뷰 기반).

🛠️ 적용 사례 (Applied in summary)

  • AstraAI/src/extension.ts — activate/deactivate 의 전 과정, subscriptions 등록, 설정 반응, secrets 사용, 워처 등록이 모두 한 파일에 [S1].
  • AstraAI/src/features/_shared/eventSourcedStore.tsvscode.workspace.workspaceFolders 로 워크스페이스 경로 해석(확장에서 파일 경로 다루는 표준 방식) [S3].

💻 코드 패턴 (Code patterns)

// 1) 명령 등록 → 반환된 Disposable 을 subscriptions 로 (src/extension.ts)
context.subscriptions.push(
    vscode.commands.registerCommand('g1nation.clearChat', () => provider.clearChat()),
);

// 2) 설정 변경 반응 — 관심 키만 (src/extension.ts)
context.subscriptions.push(
    vscode.workspace.onDidChangeConfiguration((e) => {
        if (!e.affectsConfiguration('g1nation.ollamaUrl')) return;
        const newUrl = vscode.workspace.getConfiguration('g1nation').get<string>('ollamaUrl', '');
        lmStudioClient.setBaseUrl(newUrl);
    }),
);

// 3) 커스텀 dispose 콜백도 disposable 로 등록
context.subscriptions.push({ dispose: () => activityTracker.dispose() });

// 4) getter 콜백으로 늦은 바인딩 (순환/초기화 순서 회피)
const telegramBot = createTelegramBot(context, { telegramClient, getProvider: () => provider });

// 5) deactivate — 명시 정리가 필요한 것만
export async function deactivate() {
    HealthCheckMonitor.dispose();
    clearBrainTokenIndex();
    if (_telegramBot) { try { await _telegramBot.stop(); } catch {} }
}

검증 상태 및 신뢰도

  • 상태: draft
  • 검증 단계: applied
  • 출처 신뢰도: A
  • 신뢰 점수: 0.93
  • 중복 검사 결과: 신규 생성 (New discovery)

🔗 지식 그래프 (Knowledge Graph)

📚 출처 (Sources)

  • [S1] AstraAI/src/extension.ts — activate/deactivate, subscriptions, 명령/설정/시크릿/웹뷰/워처
  • [S2] AstraAI/package.json — engines.vscode, main, contributes(명령/뷰)
  • [S3] AstraAI/src/features/_shared/eventSourcedStore.ts — workspaceFolders 경로 해석

📝 변경 이력 (Change history)

  • 2026-06-13: AstraAI 코드 분석 기반 초안 생성.