---
ai_assisted: true
title: "Claude Code 세션 공유 — .jsonl 심볼릭 링크"
description: "여러 Claude Code 계정에서 같은 세션을 재개하는 셋업 — projects 디렉토리를 공유 물리 경로로 매핑"
pubDate: 2026-05-20T20:30:37+09:00
category: "AI"
subcategory: "Agent"
tags: ["Claude Code", "Multi-account", "Session Sharing", "Symlink", ".jsonl", "Configuration", "Developer Workflow"]
heroImage: ""
series: "claude-multi-account"
seriesOrder: 2
seriesTitle: "Claude Code 멀티 계정 운영"
serial: 15
draft: false
published: true
---

멀티 계정을 설정하고 나면 새로운 문제가 생긴다. 계정 A에서 작업하던 세션이 계정 B에서는 보이지 않는다. Resume 목록이 계정마다 별도 `projects` 디렉토리에 쌓이기 때문이다. 계정을 바꿀 때마다 이전 대화 맥락이 끊기면 멀티 계정을 쓰는 의미가 절반쯤 사라진다.

해결책은 모든 계정의 `projects` 디렉토리를 같은 물리 경로로 가리키게 하면 된다.

Claude Code는 projects 디렉토리의 `.jsonl` 파일을 직접 스캔해 재개 가능한 세션 목록을 구성합니다. 여러 계정에서 같은 세션을 이어 쓰려면 모든 계정의 projects 디렉토리를 같은 물리 디렉토리로 가리키는 심볼릭 링크로 설정하면 됩니다.

---

## 어떻게 가능한가

Claude Code가 Resume 목록을 구성하는 방식은 외부 색인 파일(index)을 조회하는 것이 아닙니다. 기동 시마다 `projects` 디렉토리 아래의 모든 `.jsonl` 파일을 동적으로 스캔해 세션 메타데이터를 직접 파싱합니다. 의사 코드로 표현하면 다음과 같습니다.

```javascript
function loadResumeList(projectsDir) {
    const sessions = [];
    const files = fs.readdirSync(projectsDir, { recursive: true });
    for (const file of files) {
        if (file.endsWith('.jsonl')) {
            const session = parseJsonl(file);
            sessions.push(session);
        }
    }
    return sessions;
}
```

핵심은 파일의 물리적 위치입니다. 경로 자체가 아니라 그 경로가 실제로 가리키는 파일이 중요합니다. 이 특성 덕분에 `projects` 디렉토리를 심볼릭 링크로 대체해도 Claude Code의 스캔 로직은 아무 변경 없이 동작합니다. 링크 여부를 구분하지 않기 때문입니다.

일부 외부 도구(cc-session-sync, qmd)는 빠른 조회를 위해 `sessions-index.json`을 별도로 생성합니다. 그러나 Claude Code 자체는 이 파일을 사용하지 않습니다. `sessions-index.json`이 오래되거나 손상된 상태여도 Resume 기능에는 영향이 없습니다.

---

## 디렉토리 구조와 심볼릭 링크

목표 구조는 다음과 같습니다.

```
~/.claude-shared/projects/              ← 물리적 디렉토리 (모든 .jsonl 파일 보관)
├── -Users-jaesolshin/
│   └── *.jsonl
├── -private-tmp/
│   └── *.jsonl
└── ...

~/.claude/projects        → 심볼릭 링크 → ~/.claude-shared/projects/
~/.claude-2/projects      → 심볼릭 링크 → ~/.claude-shared/projects/
~/.claude-3/projects      → 심볼릭 링크 → ~/.claude-shared/projects/
~/.claude-4/projects      → 심볼릭 링크 → ~/.claude-shared/projects/
```

모든 계정의 `projects`가 같은 물리 디렉토리를 가리키므로, 한 계정에서 생성한 `.jsonl` 파일은 다른 계정에서 즉시 접근 가능합니다. 파일 시스템 수준의 투명성이 핵심입니다.

심볼릭 링크를 수동으로 생성하는 명령은 다음과 같습니다.

```bash
# 공유 디렉토리 생성
mkdir -p ~/.claude-shared/projects

# 각 계정의 projects를 공유 디렉토리로 연결
ln -sf ~/.claude-shared/projects ~/.claude/projects
ln -sf ~/.claude-shared/projects ~/.claude-2/projects
ln -sf ~/.claude-shared/projects ~/.claude-3/projects
ln -sf ~/.claude-shared/projects ~/.claude-4/projects
```

설정 후 심볼릭 링크를 확인합니다.

```bash
ls -la ~/.claude/projects
# 예상 출력:
# lrwxr-xr-x ... ~/.claude/projects -> /Users/user/.claude-shared/projects
```

---

## 마이그레이션 절차

기존 세션 데이터가 각 계정의 `projects` 디렉토리에 분산되어 있는 경우, 초기화 스크립트를 사용하면 병합·백업·심볼릭 링크 교체를 자동으로 처리합니다.

```bash
bash ~/.claude/scripts/sessions-shared-init.sh
```

**Phase 1: 병합**

각 계정의 `projects` 디렉토리 내용을 `~/.claude-shared/projects/`로 rsync합니다. `--ignore-existing` 옵션을 사용하므로 같은 파일명이 이미 존재하면 덮어쓰지 않습니다. 결과적으로 공유 디렉토리는 모든 계정 세션의 합집합이 됩니다.

```bash
rsync -a --ignore-existing ~/.claude/projects/ ~/.claude-shared/projects/
rsync -a --ignore-existing ~/.claude-2/projects/ ~/.claude-shared/projects/
# ... 각 계정 반복
```

**Phase 2: 백업**

원본 `projects` 디렉토리를 타임스탬프와 함께 백업합니다. 심볼릭 링크로 교체하기 전에 원본을 보존하는 안전장치입니다.

```bash
mv ~/.claude/projects ~/.claude/projects.bak.$(date +%s)
mv ~/.claude-2/projects ~/.claude-2/projects.bak.$(date +%s)
```

**Phase 3: 심볼릭 링크**

각 계정의 `projects` 위치에 공유 디렉토리로 향하는 심볼릭 링크를 생성합니다.

```bash
ln -sf ~/.claude-shared/projects ~/.claude/projects
ln -sf ~/.claude-shared/projects ~/.claude-2/projects
```

스크립트 실행 출력 예시는 다음과 같습니다.

```
Accounts found: 4
  /Users/user/.claude
  /Users/user/.claude-2
  /Users/user/.claude-3
  /Users/user/.claude-4

=== Phase 1: Merge ===
Merging /Users/user/.claude/projects (100 .jsonl files) ...
Merging /Users/user/.claude-2/projects (80 .jsonl files) ...
...
Shared total: 160 .jsonl files

=== Phase 2: Symlink ===
Linked /Users/user/.claude/projects → ~/.claude-shared/projects (backup: ...)
Linked /Users/user/.claude-2/projects → ~/.claude-shared/projects (backup: ...)
...

[OK] Done. Verify: ls -la ~/.claude/projects
```

마이그레이션 전 각 계정에 중복 세션이 있었다면 합집합 기준으로 세션 수가 줄어드는 것은 정상입니다. 4개 계정에 각각 100, 80, 60, 40개 세션이 있어도 중복을 제거하면 공유 디렉토리의 파일 수는 그보다 적을 수 있습니다.

---

## 세션 재개 동작

설정 완료 후 사용 방법은 기존과 동일합니다. 계정 전환 후 Resume를 선택하면 다른 계정에서 생성한 세션이 목록에 나타납니다.

```bash
# 계정 1에서 새 세션 시작
claude -1

# 계정 2에서 같은 세션 재개
claude -2
# "Resume" 메뉴에 계정 1에서 생성한 세션이 표시됨
```

이것이 가능한 이유는 단순합니다. `~/.claude/projects`와 `~/.claude-2/projects`가 물리적으로 같은 디렉토리(`~/.claude-shared/projects`)를 가리키기 때문입니다. 계정 1에서 새 세션을 시작하면 `~/.claude-shared/projects/` 아래에 `.jsonl` 파일이 생성됩니다. 계정 2에서 Claude Code를 기동하면 동일한 물리 디렉토리를 스캔하므로 해당 파일을 즉시 발견합니다.

`claude --resume` 플래그를 사용하는 경우도 동일합니다.

```bash
# 특정 세션 ID를 지정해 재개
claude -2 --resume <session-id>
```

Resume 목록에 표시되는 세션 ID는 `.jsonl` 파일에서 직접 파싱됩니다. 색인 파일이나 외부 상태에 의존하지 않으므로, 심볼릭 링크로 같은 파일에 접근하는 한 어느 계정에서든 동일한 목록을 볼 수 있습니다.

```
계정 1 (claude -1)
  → ~/.claude/projects (symlink)
    → ~/.claude-shared/projects/
        └── session1.jsonl  (새로 생성)

계정 2 (claude -2)
  → ~/.claude-2/projects (symlink)
    → ~/.claude-shared/projects/  (같은 물리 디렉토리)
        └── session1.jsonl  (즉시 발견 → Resume 목록에 표시)
```

---

## 운영상 주의

**권한과 소유권**

`~/.claude-shared/projects/`의 소유자가 현재 사용자와 일치하는지 확인합니다. 초기화 스크립트를 루트 권한으로 실행한 경우 소유권이 root로 설정될 수 있습니다.

```bash
ls -la ~/.claude-shared/
# 소유자가 현재 사용자인지 확인

# 필요 시 소유권 교정
chown -R $(whoami) ~/.claude-shared/
```

심볼릭 링크 자체를 `rm`으로 제거해도 대상 파일은 삭제되지 않습니다. `rm ~/.claude/projects`는 링크만 제거하며 `~/.claude-shared/projects/` 아래 파일은 그대로입니다.

**동시 쓰기**

두 계정에서 동시에 같은 프로젝트 디렉토리에 쓰는 경우, `.jsonl` 파일 단위의 경합이 발생할 수 있습니다. Claude Code는 세션별로 별개의 `.jsonl` 파일을 사용하므로 서로 다른 세션을 동시에 진행하면 충돌 가능성은 낮습니다. 같은 세션 파일에 두 계정이 동시에 접근하는 상황은 피하는 것이 좋습니다.

외부 도구(cc-session-sync, qmd)가 `sessions-index.json`을 생성하는 경우 경합이 발생할 수 있습니다. 그러나 앞서 설명한 것처럼 Claude Code 자체는 이 파일을 사용하지 않으므로 Resume 기능에는 영향이 없습니다.

**손상된 .jsonl 파일 복구**

`.jsonl` 파일이 부분적으로 손상된 경우 해당 파일만 제거하면 됩니다. Claude Code는 디렉토리 전체를 스캔하므로 손상된 파일 하나가 다른 세션 목록에 영향을 주지 않습니다. 백업 디렉토리(`projects.bak.<타임스탬프>`)에서 원본 파일을 복원할 수도 있습니다.

```bash
# 손상된 파일 확인 (파싱 오류가 있는 .jsonl)
find ~/.claude-shared/projects/ -name "*.jsonl" -exec sh -c '
    node -e "
        const fs = require(\"fs\");
        fs.readFileSync(\"$1\", \"utf8\").split(\"\n\").forEach((l, i) => {
            if (l.trim()) try { JSON.parse(l); } catch(e) { process.exit(1); }
        });
    " 2>/dev/null || echo "손상: $1"
' sh {} \;
```

**settings는 분리 유지**

`projects` 디렉토리를 공유해도 각 계정의 `settings.json`, `CLAUDE.md`, `history.jsonl`은 독립적으로 유지됩니다. 모델 지정이나 API 키, 훅 설정은 계정별로 별도 관리됩니다. 세션 공유가 설정 공유를 의미하지는 않습니다.

**memory 디렉토리**

`projects` 디렉토리는 공유되지만 `memory` 디렉토리는 각 계정에 독립적으로 유지됩니다. 계정 1에서 세션 중 메모리에 저장한 정보는 계정 2에서 같은 세션을 재개해도 보이지 않습니다. memory까지 공유가 필요한 경우 별도로 심볼릭 링크를 구성해야 합니다.

```bash
mkdir -p ~/.claude-shared/memory
rsync -a --ignore-existing ~/.claude/memory/ ~/.claude-shared/memory/

for ACCT in ~/.claude ~/.claude-[0-9]*; do
    rm -rf "$ACCT/memory"
    ln -sf ~/.claude-shared/memory "$ACCT/memory"
done
```

memory 공유를 적용하면 한 계정의 변경이 다른 계정에도 즉시 반영됩니다.

**롤백**

공유를 취소하고 각 계정의 독립 `projects` 디렉토리를 복원하려면 백업에서 되돌립니다.

```bash
for ACCT in ~/.claude ~/.claude-[0-9]*; do
    [ -L "$ACCT/projects" ] || continue
    rm "$ACCT/projects"
    BACKUP=$(ls -td "$ACCT"/projects.bak.* 2>/dev/null | head -1)
    [ -d "$BACKUP" ] && mv "$BACKUP" "$ACCT/projects"
    echo "Restored $ACCT/projects"
done
```

초기화 이후 생성된 세션(공유 디렉토리에만 존재하는 파일)을 롤백 후에도 보존하려면 rsync를 추가합니다.

```bash
for ACCT in ~/.claude ~/.claude-[0-9]*; do
    [ -L "$ACCT/projects" ] || continue
    rm "$ACCT/projects"
    BACKUP=$(ls -td "$ACCT"/projects.bak.* 2>/dev/null | head -1)
    [ -d "$BACKUP" ] && mv "$BACKUP" "$ACCT/projects"
    rsync -a --update ~/.claude-shared/projects/ "$ACCT/projects/"
    echo "Restored and synced $ACCT/projects"
done
```

---

## 시리즈 위치

Ep1에서는 `CLAUDE_CONFIG_DIR`로 계정 디렉토리를 분리하는 방법을 다뤘으며, Ep3에서는 `sync-claude.sh`를 이용한 설정 파일 동기화와 트러블슈팅을 다룰 예정입니다.
