Herdr 개요

Herdr 개요

코딩 에이전트를 위한 터미널 멀티플렉서. "tmux가 터미널에 대해 하는 일을 코딩 에이전트에 대해 하는 것."

공식 문서: https://herdr.dev/docs/ · 저장소: https://github.com/herdrdev/herdr 작성 기준: 2026년 8월. 명령 문법의 최종 권위는 설치된 바이너리(herdr --help)입니다.


1. 한 줄 정의

Herdr는 Rust로 작성된 단일 바이너리 터미널 워크스페이스 매니저입니다. tmux처럼 백그라운드 서버가 실제 터미널 프로세스를 소유하고 클라이언트가 붙어서 렌더링하며, 클라이언트를 떼거나 터미널을 닫거나 SSH가 끊겨도 pane은 계속 살아있습니다.

tmux와 다른 점은 두 가지입니다:

  1. 마우스 우선 — pane, tab, workspace, 분할 경계, 우클릭 메뉴가 모두 클릭 가능. 키바인딩 학습이 필수가 아님
  2. 에이전트 인지 — pane 안에서 도는 코딩 에이전트를 인식하고 각각의 상태를 사이드바에 표시

tmux는 모든 프로세스를 동일하게 취급합니다. Claude Code나 Codex가 pane에서 돌아도 tmux에게는 프로세스 상태에 대한 이해가 없는 텍스트 스트림일 뿐입니다. Herdr는 이들을 식별하고 상태를 표면화해서, 사이드바 한 번 훑으면 어느 에이전트가 작업 중이고 어느 게 유휴고 어느 게 입력을 기다리며 막혀있는지 보입니다.


2. 아키텍처

[herdr 서버 (헤드리스, 영속)]  ← 모든 PTY/상태의 소유자
        ↕ Unix 도메인 소켓
[클라이언트 A] [클라이언트 B] ...  ← 얇은 렌더링 레이어

서버가 상태의 권위자입니다. PTY 프로세스를 관리하고, 에이전트 감지를 추적하고, 레이아웃을 다루고, 세션 스냅샷을 영속화합니다. 클라이언트는 서버로부터 프레임된 디스플레이 업데이트를 받고 키보드/마우스 입력을 되돌려 보내기만 합니다.

이 분리가 만드는 결과:

  • 여러 클라이언트를 동시에 붙일 수 있음
  • 모든 클라이언트를 떼도 프로세스가 안 죽음
  • 원격 어태치가 자연스럽게 가능
  • CLI/소켓 API가 UI와 동등한 1급 제어 경로

각 pane은 진짜 PTY입니다(portable-pty 기반). 웹뷰나 이스케이프 시퀀스가 빠진 유사 터미널이 아니라서 nvim, lazygit, 풀스크린 TUI가 평소대로 동작합니다.


3. 개념 모델

개념설명
Session영속 백그라운드 서버 네임스페이스. herdr는 default 세션에 붙음. 명명 세션(herdr session attach work)은 완전히 분리된 런타임 네임스페이스이며 설정 파일만 공유
Workspace프로젝트 레벨 컨테이너. 저장소·작업·조사 단위로 하나. 사이드바가 workspace별로 에이전트 상태를 롤업
Tabworkspace 안의 레이아웃. agents, logs, server 같은 뷰 분리용
Pane진짜 터미널. 오른쪽/아래로 분할 가능. 클라이언트 디태치를 견딤
AgentHerdr가 pane 안에서 인식한 프로세스

ID 체계

공개 ID는 불투명하지만 안정적인 핸들입니다.

workspace  w1
tab        w1:t1
pane       w1:p1
  • 닫힌 tab/pane ID는 재사용되지 않습니다
  • 다른 workspace로 옮겨진 pane은 새 workspace 한정 ID를 받습니다
  • pane move 이후에는 .result.move_result.pane.pane_id 또는 살아있는 에이전트 이름으로 계속하세요. 옛 값은 .result.move_result.previous_pane_id로 보고되며, 옮겨진 프로세스가 상속한 호출자 컨텍스트에서만 해석되므로 일반적인 타겟으로 쓰면 안 됩니다

ID는 항상 JSON 응답에서 파싱하세요. 사이드바 순서나 예제에서 유추하면 안 됩니다.

모드

  • 터미널 모드 — 키를 포커스된 pane으로 보냄
  • 프리픽스 모드 — 프리픽스 키(기본 ctrl+b) 후 액션 키 하나를 Herdr 명령으로
  • 네비게이트 모드 — 영속적인 워크스페이스 탐색 표면

tmux 근육기억이 대체로 통합니다: prefix+c 새 탭, prefix+v 오른쪽 분할, prefix+- 아래 분할, prefix+q 디태치, prefix+? 전체 바인딩 표시, prefix+[ 카피 모드.


4. 에이전트 라이프사이클 상태

Herdr의 핵심 차별점입니다.

상태의미
working실제로 작업 중
blockedHerdr가 승인 또는 질문 UI를 인식함
idle입력 받을 준비. 그리고 그 탭이 포커스된 Herdr UI에서 이미 눈에 띔
done동일한 idle 상태이되 보이지 않은 백그라운드 작업이 끝난 뒤
unknown에이전트는 있지만 확신 있게 분류 불가. 완료의 증거가 아님

done vs idle — 가장 미묘하고 가장 유용한 구분

done은 "끝났는데 아직 내가 안 본 것"입니다. 탭을 포커스하거나 pane focus/agent focus로 지목하면 "봤음"으로 표시됩니다. CLI로 읽는 것만으로는 봤음 처리가 되지 않습니다.

읽지 않은 메일 표시와 같은 역할입니다. 에이전트를 여럿 굴릴 때 "저거 결과 확인했던가?"를 머리에서 시스템으로 넘깁니다.

상태 롤업

blocked 에이전트는 그 pane, tab, workspace 전체를 blocked로 보이게 만듭니다. working 에이전트는 workspace를 active로 보이게 합니다. done 에이전트는 볼 때까지 계속 보입니다.

이게 Herdr의 메인 워크플로입니다 — 여러 에이전트를 병렬로 띄우고, 사이드바 한 컬럼으로 어느 프로젝트가 결정을 기다리는지 / 아직 돌고 있는지 / 리뷰 준비됐는지를 파악.


5. 에이전트 감지와 통합

감지 경로는 세 가지입니다: 포그라운드 프로세스, 스크린 매니페스트, 그리고 선택적 통합.

화면 감지의 한계

Herdr의 첫 감지 경로는 화면 읽기였습니다. 사람이 보는 것과 일치해서 유용했지만 에이전트 UI가 바뀌면 깨졌습니다. 그래서 지금은 핫리로드 가능한 감지 매니페스트를 배포해서 호환성 수정이 항상 새 바이너리를 요구하지 않게 합니다.

터미널 활동량을 신호로 쓰는 것도 안 됩니다:

  • 스피너는 의미 있는 상태가 blocked인데도 계속 다시 그려질 수 있음
  • 권한 프롬프트는 pane에서 가장 중요한 것인데도 가만히 앉아 있음
  • 서브에이전트가 활동을 만드는 동안 부모 세션은 대기 중일 수 있음

터미널 활동은 증거일 뿐이고, 라이프사이클이 더 강합니다.

통합 설치 (권장)

herdr integration install claude
herdr integration install opencode
herdr integration status          # 설치 버전 확인

통합은 에이전트 설정 디렉터리에 훅/플러그인을 설치해서, 화면 감지만이 아니라 에이전트가 직접 보고하는 권위 있는 상태를 Herdr에 줍니다. 지원 대상에는 pi, claude, codex, copilot, cursor, devin, droid, kimi, opencode, kilo, hermes, qodercli 등이 있습니다.

OpenCode의 경우 ~/.config/opencode/plugins/herdr-agent-state.js에 플러그인을 씁니다(OpenCode를 최소 한 번 실행해 둔 상태여야 함).

진단

herdr agent list                        # Herdr가 보는 것
herdr agent explain <target> --json     # 왜 그렇게 분류했는지
herdr integration status

agent explain은 서버에게 화면 감지가 쓰는 것과 동일한 하단 버퍼 스냅샷을 분류하게 시킵니다. Herdr 업그레이드 후에는 서버를 재시작하거나 핸드오프한 뒤에 써야 합니다.


6. 지속성 — 4개 층위

혼동하기 쉬운 부분입니다. 서로 다른 네 가지 메커니즘입니다.

(1) 디태치 / 재부착 — 가장 강력

# prefix+q 또는 그냥 터미널 창 닫기
herdr          # 다시 붙기

원래 프로세스가 아예 멈추지 않기 때문에 가장 강력한 경로입니다. 복원 개념 자체가 없습니다. 노트북 덮기, SSH 끊김, wezterm 재시작이 전부 여기 해당합니다.

(2) 스냅샷 복원 — 서버가 실제로 죽었을 때

herdr server stop     # ⚠️ pane 프로세스를 전부 죽임
herdr                 # 재시작

workspace·tab·pane·cwd·레이아웃·포커스가 복원됩니다. 실행 중이던 셸·서버·테스트·임의 프로세스는 보존되지 않습니다. 더 강한 경로를 쓸 수 없는 pane은 저장된 디렉터리의 새 셸로 돌아옵니다.

~/.config/herdr/session.json에 저장됩니다.

(3) 화면 히스토리 복원 — 기본 꺼짐

죽은 pane의 최근 터미널 내용을 복원합니다. 텍스트만 되살아나며 프로세스는 아닙니다.

기본 비활성인 이유는 보안입니다. pane 출력에 시크릿·토큰·프롬프트·명령 출력이 들어갈 수 있습니다. Settings > Experiments > pane screen history에서 켜며, session-history.json에 저장됩니다. Herdr 설정/세션 디렉터리를 터미널 히스토리처럼 취급하라고 권고합니다.

(4) 네이티브 에이전트 세션 복원 — 기본 켜짐

일부 에이전트는 자기 대화 세션을 스스로 관리합니다(세션 ID, 트랜스크립트). 공식 통합이 세션 참조를 보고하면, Herdr는 서버 재시작 후 그 pane을 빈 셸로 되돌리는 대신 에이전트를 원래 세션으로 재개시킵니다.

  • 화면 히스토리 복원보다 우선 적용됩니다
  • 클라이언트가 붙어서 터미널 크기와 테마 컨텍스트를 준 뒤, 각 pane이 포커스되길 기다리지 않고 전체를 재개합니다
  • 특정 통합 버전 이상을 요구합니다 (herdr integration status로 확인)
  • 지원되지 않거나 없거나 유효하지 않거나 중복이거나 오래된 세션 참조는 일반 셸로 복원됩니다
  • 끄려면 config의 [session] 아래 resume_agents_on_restore = false

(보너스) 라이브 핸드오프

업데이트나 원격 어태치에서 돌고 있는 서버를 교체해야 할 때, 옛 서버에게 라이브 pane을 새 서버로 넘기라고 요청합니다. 프로세스가 살아남습니다.

단 일시적 조정 상태는 보존되지 않습니다 — 진행 중인 CLI/API 요청, wait, 구독 스트림, 클라이언트 소켓, pane 간 메시지가 끊길 수 있으므로 클라이언트가 재연결하고 재시도해야 합니다.

herdr update --handoff는 Herdr 자체 업데이터가 관리하는 설치에만 적용됩니다.


7. 원격

두 가지 모드가 있습니다.

# (a) tmux 스타일: 서버에 SSH 붙어서 거기서 herdr 실행
ssh you@box
herdr

# (b) 로컬이 얇은 클라이언트: SSH 통해 원격 서버에 붙어 UI를 로컬로 스트리밍
herdr --remote workbox
herdr --remote ssh://you@yourserver:2222

직접 터미널 어태치도 있습니다 — 서버 소유 터미널 하나를 현재 터미널에서 엽니다. 렌더된 터미널 상태를 스트리밍한 뒤 라이브 ANSI 프레임을 보냅니다. ctrl+b q로 디태치, ctrl+b ctrl+b로 리터럴 ctrl+b 전송. 쓰기 가능한 직접 어태치 클라이언트는 하나만 입력과 리사이즈를 소유하며, --takeover로 교체합니다.

에이전트를 서버·맥미니·샌드박스 VM 등 SSH 되는 곳에서 돌리고, 폰을 포함한 아무 터미널에서 붙을 수 있습니다.


8. CLI와 에이전트 자동화

CLI는 통합·에이전트가 쓰는 것과 동일한 로컬 소켓 API로 서버와 통신합니다. 대부분의 명령이 JSON을 반환합니다.

커맨드 그룹

herdr agent     herdr pane      herdr workspace   herdr tab
herdr worktree  herdr terminal  herdr notification
herdr integration  herdr session  herdr server  herdr plugin

서브커맨드 없이 그룹을 실행하면 해당 그룹의 도움말이 출력됩니다. 단 herdr workspace create 같은 변경 명령은 기본값으로 유효해서 실제 실행되므로, 인자를 빼서 탐색하면 안 됩니다. herdr를 그냥 실행하면 TUI가 뜹니다 — 탐색 용도로 쓰지 마세요.

pane vs agent — 제어 표면 선택

pane은 에이전트가 있든 없든 존재하고, agent는 그 pane 안에서 현재 도는 인식된 프로세스입니다. agent start이미 존재하는 사용 가능한 셸 pane을 요구하며, 레이아웃을 만들거나 나누거나 옮기지 않습니다.

목적pane 표면agent 표면
명령 실행pane run
텍스트 전송pane send-textagent prompt
키 전송pane send-keysagent send-keys
대기pane wait-outputagent wait
읽기pane readagent read

차이: pane 입력은 안에 뭐가 있든 터미널에 직접 꽂히고, agent 입력은 살아있는 에이전트를 검증한 뒤 그 에이전트가 더 이상 해당 pane을 소유하지 않으면 거부합니다.

에이전트 이름

[a-z][a-z0-9_-]{0,31} 패턴, 살아있는 에이전트 사이에서 유일해야 합니다. 이름은 현재 pane 점유자를 따라가며 그 에이전트가 종료·해제·교체되면 지워집니다. 타겟은 유일한 살아있는 에이전트 이름 또는 그 에이전트를 호스팅 중인 pane ID만 받으며, 터미널 ID나 맨 에이전트 종류 라벨은 받지 않습니다.

표준 오케스트레이션 시퀀스

# 0) Herdr pane 안인지 확인
test "${HERDR_ENV:-}" = 1

# 1) 형제 pane 생성 (포커스 유지, cwd 보존)
split=$(herdr pane split --current --direction right --cwd "$PWD" --no-focus)
p=$(printf '%s\n' "$split" | jq -r '.result.pane.pane_id')

# 2) 에이전트 기동 — 준비될 때까지 블로킹 (기본 30초 타임아웃)
herdr agent start reviewer --kind codex --pane "$p"
#    네이티브 인자는 -- 뒤에만:
#    herdr agent start reviewer --kind claude --pane "$p" -- <agent-args>

# 3) 작업 지시 + 대기
herdr agent prompt reviewer "Review the current diff." --wait --timeout 120000

# 4) 결과 회수
herdr agent read reviewer --source recent-unwrapped --lines 120

호출자 컨텍스트가 각 관리 pane에 주입됩니다:

printf '%s\n' "$HERDR_WORKSPACE_ID" "$HERDR_TAB_ID" "$HERDR_PANE_ID"

타겟을 생략하면 UI 포커스된 pane(다른 사용자/클라이언트의 것일 수 있음)을 쓸 수 있으므로 --current를 선호하세요.

대기의 의미론

  • agent prompt --wait는 첫 안정 상태(idle/done/blocked)를 기다립니다. 이 기본값을 --until로 중복 지정하지 마세요
  • 비작업 상태에서 보낸 프롬프트는 5초 안에 라이프사이클 변화가 관측되어야 하며, 아니면 무한 대기 대신 agent_prompt_stalled를 반환합니다
  • 이 대기는 개별 턴이 아니라 라이프사이클 상태를 추적합니다. 에이전트가 이미 작업 중이면 진행 중이던 턴의 완료가 대기를 충족시킬 수 있습니다
  • --until은 상태 특정 워크플로에만: herdr agent wait reviewer --until blocked --timeout 120000
  • pane wait-output은 선택된 스냅샷을 즉시 검색하므로 이미 존재하는 출력도 매칭됩니다. --match는 리터럴 부분문자열, --regex는 Rust 정규식

읽기 소스

소스용도
visible현재 렌더된 뷰포트
recent최근 출력 (소프트 랩 포함)
recent-unwrapped소프트 랩 결합. 로그/트랜스크립트에 권장
detection에이전트 감지에 쓰이는 평문 하단 버퍼 스냅샷

색상과 스타일이 증거일 때만 --format ansi.

⚠️ Alternate screen 함정

--lines를 늘려도 완료된 응답이 더 안 나오면, 그 pane은 에이전트를 터미널의 alternate screen에서 돌리고 있을 가능성이 높습니다. alternate screen을 떠난 행은 Herdr의 호스트 스크롤백에 들어가지 않으므로 라인 수를 늘려도 복구할 수 없습니다. 폰트가 크거나 pane이 작을수록 잘 발생합니다.

대응: 짧게 답하도록 요청 / pane 크기 확대 / 스크롤 후 --source visible / 최후 수단으로 에이전트에게 전체 응답을 임시 디렉터리에 Markdown으로 쓰고 경로만 답하게 한 뒤 파일을 직접 읽기.

에이전트용 스킬 파일

Herdr는 코딩 에이전트가 pane 안에서 Herdr를 직접 제어하도록 가르치는 스킬을 함께 배포합니다.

npx skills add herdrdev/herdr --skill herdr -g

원본: https://raw.githubusercontent.com/herdrdev/herdr/master/skills/herdr/SKILL.md

스킬 시스템이 없는 에이전트는 이 내용을 글로벌 커스텀 인스트럭션에 붙여넣으면 됩니다. 스킬 설명은 사용자가 Herdr를 명시적으로 언급했을 때만 발동하도록 되어 있으니, 프롬프트에 "herdr로"를 넣어야 트리거됩니다.

안전 규칙 (스킬에 명시된 것들)

  • 백그라운드 작업엔 --no-focus
  • --current / 명시적 pane ID / 유일한 에이전트 이름 사용. 다른 클라이언트의 포커스에 의존 금지
  • ID는 JSON에서 파싱
  • 자기가 만들지 않은 workspace/tab/pane/session을 사용자의 명시적 요청 없이 닫지 않기
  • 활성 세션에서 herdr server stop 실행 금지
  • 메인 Herdr 프로세스 kill 금지. 격리가 필요한 실험은 명명 테스트 세션으로
  • CLI 서버 오류는 stderr에 JSON, 종료 코드 1. 문법 오류는 종료 코드 2

9. 알림

내장

# ~/.config/herdr/config.toml
[ui.toast]
delivery = "system"    # 데스크톱 알림 (바깥 터미널 경유)
# delivery = "terminal"  # 인앱 토스트

알림 시스템은 포커스를 인지해서 현재 활성 탭에 대한 방해성 알림을 억제하고, 백그라운드 이벤트만 오디오·TUI 토스트·데스크톱 알림으로 표면화합니다. Idle(Done)과 Blocked(Request) 전이에 사운드가 있으며, 에이전트별 사운드 오버라이드(default/on/off)를 감지된 라벨 키로 설정할 수 있습니다.

커스텀 알림

herdr notification show <> [--body TEXT] \
  [--position top-left|top-right|bottom-left|bottom-right] \
  [--sound none|done|request]

설정된 [ui.toast] 전달 방식을 따릅니다. --position은 인앱 토스트에만 영향을 주고, --sound는 기본 none이며 done/request는 기존 완료·주의필요 사운드를 알림이 표시될 때만 재생합니다.

커뮤니티 플러그인

플러그인특징
yankewei/herdr-focus-notifymacOS. blocked/done에 클릭 가능한 토스트, 클릭 시 해당 pane으로 포커스
cobanov/herdr-ntfyshntfy 푸시(폰 포함). Go 바이너리, 크로스 플랫폼
dot/herdr-terminal-notifiermacOS. 다층 설정 오버라이드, dotfiles 친화
speardragon/herdr-plugin-managerpopup에서 플러그인 설치/관리/마켓플레이스 브라우징
ogulcancelik/herdr-plugin-examples예제 쿡북 (agent-telegram-notify 등). 공식 유지보수 아님

⚠️ 플러그인을 쓰면 내장 토스트를 끄세요 (delivery = "terminal"). 아니면 알림이 두 번 옵니다.

popup ≠ 토스트

Herdr의 인앱 popup 오버레이는 별개 개념입니다. --width/--height로 셀 단위나 퍼센트 지정, 생략 시 터미널 절반. popup은 Herdr pane이 아니며 HERDR_PANE_ID를 내보내지 않고 pane/agent API에 참여하지 않습니다. Escape 포함 모든 입력을 받고 명령 종료 또는 close 요청 시 닫힙니다.


10. 설정

herdr --default-config          # 전체 기본 설정 출력
herdr server reload-config      # 재시작 없이 적용

파일: ~/.config/herdr/config.toml (없어도 동작)

주요 섹션: [keys] 키바인딩, [theme] 테마, [ui] 사이드바/UI 동작, [terminal] 셸 기본값, [update] 채널, [session] 세션 동작


11. 설치와 진단

# Linux / macOS
curl -fsSL https://herdr.dev/install.sh | sh

# Windows (프리뷰 베타)
powershell -ExecutionPolicy Bypass -c "irm https://herdr.dev/install.ps1 | iex"

# Homebrew / mise / Nix도 지원
herdr --version
herdr update

진단:

herdr status            # 런타임 요약
herdr status server
herdr status client

로그: ~/.config/herdr/herdr.log, herdr-client.log, herdr-server.log (앱/클라이언트/서버 모드별로 분리, 용량 상한 있음)


12. 설계 철학

제작자의 포지션 페이퍼 "Coding agents are becoming runtimes"(2026-06-10)가 Herdr의 설계 근거를 설명합니다.

핵심 주장:

  • 코딩 에이전트는 채팅 인터페이스에서 출발했지만 이제 저장소·터미널·에디터·CI·원격 머신에 살면서 명령을 실행하고 권한을 요청하고 서브에이전트를 스폰하고 멈추고 재개하고 실패하고 복구합니다. 이건 런타임 행동입니다
  • 모델과 호스팅 API와 구독 가격은 벤더의 것이지만, 개발자 터미널에서 도는 CLI는 개발자 환경의 일부입니다
  • 프로젝트 지침 포맷(AGENTS.md vs CLAUDE.md)의 분화는 Python 패키징이 겪은 표준 드리프트의 초기 단계입니다
  • "훅"은 각 에이전트가 자기 경계를 스스로 정의하기 때문에 이식 가능한 라이프사이클 계약을 제공하지 못합니다. 최소 계약은 working / blocked / idle 세 상태로 충분합니다
  • OpenCode는 session.idle, session.status, session.error, permission.asked, permission.replied 같은 세션 레벨 이벤트를 노출해서 오케스트레이션 도구가 필요로 하는 형태에 더 가깝습니다
  • Herdr는 에이전트별 지원 매트릭스(검증된 라이프사이클 신호 vs 관찰 감지)를 공개할 예정입니다
  • 요청: 지루한 부분을 표준화하라. 모델·UX·플래닝·속도·가격·안전성·취향으로 경쟁하되, 저장소에 지침 파일이 다섯 개 필요한지나 외부 도구가 에이전트의 blocked 여부를 알 수 있는지로 경쟁하지 말 것

읽을 때 감안할 점: 이건 중립적 분석이 아니라 아래층 도구 제작자의 주장입니다. 라이프사이클 표준화의 최대 수혜자는 Herdr 같은 오케스트레이터입니다. CLAUDE.md 유지에도 벤더 나름의 기술적 이유가 있을 수 있고 글은 그 반론을 다루지 않습니다. AGENTS.md의 6만 프로젝트 수치도 자기 서술 인용입니다.

다만 "터미널 활동량은 증거이고 라이프사이클이 진짜다"라는 핵심 관찰은 이해관계와 무관하게 타당합니다.


13. 한계와 주의사항

항목내용
tmux 중첩 금지Herdr pane 안에서 tmux 세션을 열면 에이전트 상태 감지가 비활성화됩니다. 얹는 레이어가 아니라 대체재입니다
중첩 실행 차단Herdr는 nested launch를 설계상 막습니다. HERDR_ENV=1이면 이미 안에 있는 것
alternate screen긴 응답 회수가 구조적으로 취약. 파일 핸드오프가 확실한 우회
unknown완료의 증거가 아님. 자동화에서 성공으로 처리하면 조용히 틀립니다
턴 미추적라이프사이클 상태만 추적. 이미 바쁜 에이전트에 프롬프트+--wait는 오해를 낳음
화면 히스토리 보안켜면 pane 출력이 디스크에 남습니다. 시크릿 포함 가능
핸드오프 중 끊김진행 중인 wait/구독/요청은 보존되지 않음. 재연결·재시도 필요
성숙도0.x 버전대. 감지 매니페스트가 핫리로드되지만 UI 변화에 따른 오탐 가능

14. 참고 링크

Backlinks 2