트러블슈팅
이 워크숍을 만들고 테스트하는 동안 확인된 모든 실패에 대한 증상, 원인, 해결책 참고 문서로, 어디서 나타나는지에 따라 묶어 두었습니다.
아래 모든 항목은 이 워크숍을 만들고 테스트하는 동안 실제로 발생한 실패입니다. 증상을 찾고, 원인을 읽고, 해결책을 적용하세요. 여기에 맞는 것이 없다면 코딩 에이전트에게 문제를 넘기세요 - 자율 진행 가이드에 에이전트를 강사로 만들어 주는, 바로 붙여넣을 수 있는 프롬프트가 있습니다.
Windows와 WSL 2
wsl --install을 사용할 수 없거나 도움말만 출력됨
- 증상 - 관리자 PowerShell이
wsl --install을 인식하지 못하거나, Ubuntu를 설치하는 대신 도움말을 출력합니다. - 원인 - Windows 버전이 워크숍 최소 요구사항보다 낮거나, 대기 중인 업데이트가 적용되지 않았거나, 회사 정책이 WSL을 비활성화했습니다.
- 해결책 - Windows Update를 실행하고 Windows 11 또는 Windows 10 버전 2004(빌드 19041) 이상인지 확인하세요. 재시작한 뒤 Microsoft의 수동 WSL 설치 절차를 따르세요. 관리되는 머신에서는 관리자가 필요한 Windows 기능을 허용해야 합니다.
PowerShell에서 명령이 "not recognized"로 나옴
-
증상 - PowerShell이 워크숍의
./preflight.sh,export,source또는 다른 Bash 명령을 거부합니다. -
원인 - Windows 설치에서는 명시적으로 표시된 WSL 부트스트랩에만 PowerShell을 사용합니다. 워크숍 명령은 WSL 2의 Ubuntu 안에서 실행됩니다.
-
해결책 - 시작 메뉴에서 Ubuntu를 열고, 앱 디렉터리로 돌아가 거기서 preflight를 실행하세요:
cd ~/ClickHouse_Demos/workshops/build_workshop/app ./preflight.sh
저장소가 /mnt/c 아래에 있음
-
증상 - Docker 바인드 마운트가 느리고, 스크립트에 권한이나 줄바꿈 문자 관련 실패가 나거나, 저장소 경로가
/mnt/c/Users/...로 시작합니다. -
원인 - 저장소가 WSL의 Linux 파일시스템 대신 Windows 파일시스템에 클론되었습니다.
-
해결책 - 커밋하지 않은 작업이 필요할 때만 기존 복사본을 남기세요. 그렇지 않다면 Ubuntu를 열고 Linux 홈 디렉터리에 깨끗한 복사본을 클론하세요:
cd ~ git config --global core.autocrlf input git clone https://github.com/ClickHouse/ClickHouse_Demos.git cd ClickHouse_Demos git switch build-workshop-v1 cd workshops/build_workshop/app cp .env.workshop.example .env.workshop
Ubuntu가 WSL 1으로 실행 중
-
증상 -
wsl --list --verbose가 Ubuntu를VERSION 1로 표시하거나, Docker Desktop이 배포판과 통합할 수 없습니다. -
원인 - 배포판이 WSL 2보다 오래되었거나, WSL 1을 기본값으로 설치되었습니다.
-
해결책 - PowerShell을 관리자로 열어 변환한 뒤, Ubuntu를 다시 여세요:
wsl --set-version Ubuntu 2 wsl --set-default-version 2 wsl --list --verbose
Ubuntu 안에서 docker를 사용할 수 없음
- 증상 - Docker Desktop이 실행 중인데 Ubuntu가
docker: command not found라고 하거나 데몬에 접근할 수 없습니다. - 원인 - Docker Desktop의 WSL 엔진이나 Ubuntu 통합이 비활성화되어 있습니다.
- 해결책 - Docker Desktop -> Settings -> General -> Use the WSL 2 based engine와
Resources -> WSL Integration -> Ubuntu를 활성화하고 변경을 적용한 뒤, PowerShell에서
wsl --shutdown을 실행하고 Ubuntu를 다시 여세요. 그러면docker version이 Client와 Server 섹션을 모두 보여줘야 합니다.
WSL 또는 Docker의 메모리가 6 GB 미만
-
증상 - preflight가 메모리 부족을 보고하거나,
docker info --format 'Docker memory: {{.MemTotal}} bytes'가6442450944바이트보다 적은 값을 출력합니다. -
원인 - Docker Desktop의 WSL 2 백엔드는 WSL 가상 머신의 메모리 한도를 사용합니다.
-
해결책 - Docker Desktop을 닫고 PowerShell을 열어 8 GB WSL 한도를 만드세요:
@('[wsl2]', 'memory=8GB', 'processors=4') | Set-Content -Encoding ascii "$env:USERPROFILE\.wslconfig" wsl --shutdownDocker Desktop을 시작하고 Ubuntu를 다시 여세요.
docker info명령과 preflight를 다시 실행하세요.
스크립트가 /usr/bin/env: 'bash\r': No such file or directory를 출력함
-
증상 -
.sh파일이 즉시 실패하고 오류에bash\r또는^M이 포함됩니다. -
원인 - Windows CRLF 줄바꿈이 저장소가 요구하는 LF 줄바꿈을 대체했습니다.
-
해결책 - Ubuntu에서 Git의 WSL 정책을 설정하고 깨끗한 체크아웃을 복원하세요:
git config --global core.autocrlf input git status --short git add --renormalize .무엇이든 폐기하거나 커밋하기 전에
git status를 확인하세요. 체크아웃에 필요한 작업이 없다면~/ClickHouse_Demos에 새로 클론하는 것이 가장 안전한 복구 방법입니다.
OAuth가 Windows 브라우저를 열지 않음
- 증상 - MCP 로그인이 URL을 출력하지만 브라우저 창이 열리지 않습니다.
- 원인 - 코딩 에이전트가 WSL 안에서 실행 중이고 브라우저 전달이 불가능하거나 회사 정책으로 차단되었습니다.
- 해결책 - Ubuntu에서 전체 로그인 URL을 복사해 평소 쓰는 Windows 브라우저에 붙여넣으세요. 거기서 승인을 완료한 뒤 Ubuntu 터미널로 돌아오세요.
Docker
컨테이너가 "Created" 상태에 머물러 시작되지 않음
- 증상 -
docker info는 정상 응답하지만,docker compose ... up이 컨테이너를Created상태로 남기고 아무것도 healthy가 되지 않습니다. - 원인 - Docker 엔진이 막혀 있습니다: 데몬은 응답하지만 실제로 컨테이너를 시작하지 못합니다. 라이브 실행 중 OrbStack에서 확인되었습니다.
- 해결책 - Docker 엔진(Docker Desktop, OrbStack 또는 Colima)을 재시작하고 Running으로 보고할
때까지 기다린 뒤, 스택을 다시 띄우세요. 클론한 저장소 안 어디에서든
cd "$(git rev-parse --show-toplevel)/workshops/build_workshop/app" && ./preflight.sh를 실행하세요. 일회용 컨테이너를 테스트로 실행해 스택 시작 전에 이 문제를 잡아냅니다.
up 실행 시 "port is already allocated"
- 증상 -
docker compose ... up이Bind for 0.0.0.0:8080 failed: port is already allocated(또는:8000)로 실패합니다. - 원인 - 다른 프로세스나 오래된 워크숍 컨테이너가 이미 그 호스트 포트를 점유하고 있습니다.
- 해결책 - 클론한 저장소 안 어디에서든
cd "$(git rev-parse --show-toplevel)/workshops/build_workshop/app" && ./preflight.sh를 실행하세요. 무엇이 포트를 점유하고 있는지 알려주고, 기본 포트 + 20000 규칙에 따라 설정해야 할 정확한 오버라이드를 출력합니다. 예를 들어set FRONTEND_HOST_PORT=28080 in .env.workshop입니다. 오버라이드 변수는FRONTEND_HOST_PORT,BACKEND_HOST_PORT이며, 옵저버빌리티 오버레이에는OTEL_GRPC_HOST_PORT/OTEL_HTTP_HOST_PORT가 있습니다. 제안된 값을 설정하고 preflight를 다시 실행한 뒤 스택을 시작하세요. 호스트 포트만 바뀌고 컨테이너 내부 포트는 그대로이므로 안전합니다.
"platform does not match" 경고
- 증상 - pull이나 up 시 Docker가 플랫폼 불일치 경고를 출력합니다(예:
linux/amd64대linux/arm64). - 원인 - 이미지가 여러분 머신과 다른 CPU 아키텍처용으로 빌드되었으며, Apple Silicon에서 흔합니다.
- 해결책 - 무해합니다. 실패가 아니라 경고이며, 이미지는 에뮬레이션으로 실행됩니다. 그대로 진행하게 두세요.
ClickHouse Cloud
idle 상태 이후 첫 요청이 느리거나 한 번 500을 반환함
- 증상 - 서비스가 idle 상태였다가 첫 쿼리나 대시보드 로드가 느리거나, 요청이 한 번 500을 낸 뒤 정상 동작합니다.
- 원인 - Cloud 서비스는 idle 상태에서 0으로 스케일되고 깨어나는 데 약 30초가 걸립니다. 첫 요청이 그 기상 비용을 부담합니다. 백엔드는 이미 첫 연결에 더 긴 타임아웃을 허용하고 한 번 재시도합니다.
- 해결책 - 그냥 다시 시도하거나 약 30초 기다리세요. 결함이 아닙니다. 이것은 07 테스트, 실패, 수정에서도 중요합니다: 깨어나는 중인 서비스는 fault 03의 타임아웃을 더 쉽게 발동시킵니다.
서비스 비밀번호를 잃어버림
- 증상 -
default사용자 비밀번호를 저장하지 않아 찾을 수 없습니다. - 원인 - 생성 흐름을 벗어난 뒤에는 서비스 비밀번호가 다시 표시되지 않습니다.
- 해결책 - 서비스를 열고 Settings에서
default사용자 비밀번호를 재설정한 뒤,.env.workshop의CLICKHOUSE_PASSWORD를 갱신하세요. 호스트는 Connect 모달에서 항상 확인할 수 있습니다.
매니지드 Postgres 비밀번호를 잃어버림
- 증상 -
clickhousectl cloud postgres create가 준 일회성postgres관리자 비밀번호를 저장하지 않았습니다. - 원인 - 한 번만 표시되며, 베타 상태인
postgres get/listAPI는 인스턴스가 정상이어도 빈 결과나 FORBIDDEN을 반환할 수 있습니다. - 해결책 -
clickhousectl cloud postgres reset-password <service-id>를 실행한 뒤, 새 비밀번호를.env.workshop(PGPASSWORD)과 ClickPipe 연결에 사용하세요.
ClickHouse Cloud에 접근할 수 없음
-
증상 - preflight가 연결 점검에서 FAIL을 내거나 백엔드가 연결할 수 없고, the command below이 실패합니다.
CLICKHOUSE_HOST=$(sed -n 's/^CLICKHOUSE_HOST=//p' .env.workshop | tail -n 1) CLICKHOUSE_PORT=$(sed -n 's/^CLICKHOUSE_PORT=//p' .env.workshop | tail -n 1) curl "https://$CLICKHOUSE_HOST:$CLICKHOUSE_PORT/ping" -
원인 - wifi, VPN 또는 방화벽, 잘못된 호스트(
CLICKHOUSE_HOST에 스킴이나 포트를 붙여넣은 경우), TLS나 포트 불일치, 또는 Cloud IP 접근 목록이 여러분의 IP를 차단하고 있습니다. -
해결책 -
CLICKHOUSE_HOST가 순수 호스트명(https://없음, 포트 없음)이고,CLICKHOUSE_PORT=8443,CLICKHOUSE_SECURE=true인지 확인하세요. VPN과 방화벽을 점검하고, 서비스의 IP 접근 목록이 여러분의 주소를 허용하는지 확인하세요. preflight가 구체적인 실패 원인 - DNS, 거부, 타임아웃, TLS 핸드셰이크 - 를 알려줍니다.
클라이언트가 Unknown settings: ... skipping을 출력함
- 증상 - 쿼리는 성공하지만 실행할 때마다 알 수 없는 설정 경고가 출력됩니다.
- 원인 - 로컬에 설치된 클라이언트가 Cloud 서버보다 새로워서, 그 서버 릴리스가 인식하지 못하는 설정을 보냅니다.
- 해결책 - Module 00 Step 6의 클라이언트 버전 맞추기 명령을 다시 실행하세요. 그 명령은
clickhousectl로 Cloud 서버 버전을 읽고 대응되는 major/minor 클라이언트 릴리스를 선택합니다.--no-warnings로 모든 클라이언트 경고를 숨기지 마세요.
CDC (모듈 03)
ClickPipe 생성 시 table realtime_trips exists and is not empty가 나옴
-
증상 - ClickPipe 리소스는 존재하지 않는데,
default.realtime_trips에 이미 행이 있어서 다시 만들기가 실패합니다. -
원인 - ClickPipe를 삭제하면 소스의 복제 슬롯은 제거되지만 대상 테이블은 남을 수 있습니다. 새 파이프는 비어 있지 않은 그 테이블을 덮어쓰지 않습니다.
-
해결책 - 타임스탬프가 붙은 백업 이름으로 기존 원본 행을 보존한 뒤 파이프를 다시 만드세요. service-ID 자리표시자는 한 번만 바꾸면 됩니다. 아래 명령은 기존 materialized view가 있을 때 그것도 보존합니다:
CH_SERVICE_ID=<clickhouse-service-id> BACKUP_SUFFIX=$(date -u +%Y%m%d%H%M%S) if clickhousectl cloud service query --id "$CH_SERVICE_ID" \ --query "EXISTS TABLE nyc_tlc_data.realtime_trips_to_taxi_trips_mv" | grep -q 1; then clickhousectl cloud service query --id "$CH_SERVICE_ID" --query " RENAME TABLE nyc_tlc_data.realtime_trips_to_taxi_trips_mv TO nyc_tlc_data.realtime_trips_to_taxi_trips_mv_backup_${BACKUP_SUFFIX} " fi clickhousectl cloud service query --id "$CH_SERVICE_ID" --query " RENAME TABLE default.realtime_trips TO default.realtime_trips_backup_${BACKUP_SUFFIX} "Module 03 Step 3을 다시 실행하고, Step 4에서 정식 materialized view를 다시 만들기 전에 새
default.realtime_trips테이블을 기다리세요. 타임스탬프가 붙은 백업은 그 데이터가 더 이상 필요하지 않다고 확인한 뒤에만 나중에 삭제하세요.
ClickPipe가 "Provisioning"에 멈춤
- 증상 - 파이프를 만든 뒤 한동안 Provisioning으로 표시됩니다.
- 원인 - 스냅샷과 인프라 시작에는 보통 몇 분이 걸리지만, 이 작은 테이블에서도 10분을 넘길 수 있습니다.
- 해결책 - 콘솔에서, 또는
clickhousectl cloud clickpipe list <clickhouse-service-id>와clickhousectl cloud clickpipe get <clickhouse-service-id> <clickpipe-id>를 함께 사용해 진행 상황을 확인하세요. 처음 몇 분 동안은 상태나updatedAt값이 진행되는 한 계속 기다리세요. 10분이 지나도 갱신 없이 여전히 Provisioning이라면,pg-trip-writer로그가 계속 insert하고 있는지 확인하고, 호스트·자격 증명·publication·테이블 매핑을 다시 점검하고, 파이프가 보고한 오류를 살펴보세요. 첫 파이프가 프로비저닝 중일 때 두 번째 파이프나 materialized view를 만들지 마세요. 소스 점검이 통과하고 Cloud가 조치 가능한 오류를 보고하지 않으면,get출력을 저장해 강사나 ClickHouse Cloud 지원에 에스컬레이션하세요.
ClickHouse에 행이 도착하지 않음
- 증상 - 파이프는 Running이지만 대상 행 수가 늘지 않고 Ops 대시보드도 움직이지 않습니다.
- 원인 - 기본 동기화 간격이 약 60초이므로 지연을 예상해야 합니다. 또는 생성기가 insert하지 않거나, 파이프가 읽는 publication이 존재하지 않습니다.
- 해결책 - 최소 60초 기다리세요.
pg-trip-writer로그에inserted N trips가 보이고,created publication pub_taxi(여러분의 인스턴스) 또는publication ... already exists(강사가 제공한 매니지드 대체 인스턴스) 중 하나가 보이는지 확인하세요. 파이프 상태가 Running인지 확인하세요. publication이 없으면 파이프가 읽을 것이 없습니다 - 생성기는 여러분이 관리자인 인스턴스에 대해 첫 실행에서 그것을 만듭니다.
materialized view에 행이 없음
-
증상 -
realtime_trips는 채워지는데, (CDC materialized view가 공급하는)taxi_trips는 계속 비어 있습니다. -
원인 - materialized view가 ClickPipe 대상이 존재하기 전에 만들어졌거나,
default.realtime_trips의 CLI 대상을 읽지 않습니다. -
해결책 - 대상 테이블을 기다린 뒤, Module 03, Step 4에서 완전한 materialized view 명령을 복사하세요. 먼저 소스를 확인하세요:
clickhousectl cloud service query --id <clickhouse-service-id> --query " SELECT database, name, engine FROM system.tables WHERE name = 'realtime_trips' "materialized view는 자신이 존재한 이후에 삽입된 행을 처리합니다. 생성 후에도 trip writer를 계속 실행하세요.
복제 슬롯이 멈춤
- 증상 - 파이프가 멈추고 소스 Postgres에서 WAL이 증가합니다.
- 원인 - 멈춘 슬롯이 WAL을 보유하며, 재동기화는 새 슬롯을 만듭니다.
- 해결책 - 여러분 소유의 매니지드 Postgres(슬롯 하나, 충분한 여유)에서는 콘솔에서 파이프를
재동기화하면 됩니다. 파이프를 삭제하면 소스의 슬롯이 제거됩니다. 강사가 제공하는 매니지드 대체
풀은 강사 측 사안입니다 -
infra/README.md를 참고하세요.
환경 변수
셸의 export가 .env.workshop을 덮어씀
- 증상 -
.env.workshop에 값을 설정했는데 컨테이너가 다른 값을 사용합니다(주로 오래된OPENAI_API_KEY,LANGFUSE_*또는CLICKHOUSE_PASSWORD). - 원인 -
docker compose는${VAR}를 셸에서 먼저 보간하며, export된 셸 변수가 파일보다 우선합니다. - 해결책 - compose를 실행하는 셸에서
unset OPENAI_API_KEY LANGFUSE_PUBLIC_KEY LANGFUSE_SECRET_KEY LANGFUSE_BASE_URL CLICKHOUSE_PASSWORD를 실행한 뒤 스택을 다시 띄우세요. preflight는 이를 감지하면 경고합니다.
.env.workshop에 중복 키가 있음
- 증상 - 파일에 설정한 값이 무시됩니다.
- 원인 - 같은 키가 두 번 나타나며,
docker compose의미에 맞게 마지막 항목이 우선합니다 (preflight도 같은 방식으로 읽습니다). - 해결책 - 앞쪽 중복을 제거해 의도한 값만 남기세요.
채팅 (모듈 08)
POST /api/chat이 설치 안내와 함께 503을 반환함
- 증상 - 채팅 패널에 설치 안내가 표시되고
/api/chat이 503을 반환하지만, 앱의 나머지는 정상입니다. - 원인 - 백엔드에
OPENAI_API_KEY가 설정되지 않았습니다. - 해결책 -
.env.workshop에OPENAI_API_KEY를 추가한 뒤docker compose --env-file .env.workshop -f docker-compose.workshop.yml -f docker-compose.otel.yml up -d --build backend를 실행하세요. 이 키가 필요한 기능은 채팅뿐입니다.
첫 OpenAI 키를 만들 수 없음
- 증상 - 새 계정에서 OpenAI가 API 키를 발급하지 않습니다.
- 원인 - 새 계정은 일회성 전화 인증이 필요하고 무료 크레딧이 없습니다.
- 해결책 - 전화 인증을 완료한 뒤 Settings -> Billing에서 결제 수단을 추가하고 최소 $5의 선불 크레딧을 구매하세요. 추가한 $5를 넘겨 청구되지 않도록 자동 충전을 끄세요 (설치 중 기본값으로 켜져 있습니다).
MCP와 OAuth (모듈 00과 06)
MCP 엔드포인트에서 401
-
증상 -
https://mcp.clickhouse.cloud/mcp(또는/clickstack)에 접근하면 401이 반환됩니다. -
원인 - 브라우저 OAuth 흐름을 완료하기 전에는 정상입니다. 이 엔드포인트는 인증이 필요합니다.
-
해결책 - 에이전트에 서버를 추가한 뒤, 사용하는 도구의 명령으로 OAuth 흐름을 실행하고 브라우저에서 승인하세요:
- Claude Code -
/mcp를 실행하고 서버를 선택해 승인하세요(또는claude mcp login <name>). - Codex CLI -
codex mcp login <name>. - Cursor - MCP 설정 창을 열고 서버의 authorize/login 컨트롤을 클릭하세요.
또한 여러분의 서비스에서 Connect with MCP 토글이 켜져 있는지 확인하세요.
- Claude Code -
회사 노트북이 MCP나 OAuth를 차단함
- 증상 - 에이전트가 MCP 서버를 추가할 수 없거나 OAuth 리다이렉트가 차단됩니다.
- 원인 - 관리되는 노트북 정책이 MCP 서버 추가나 외부로 나가는 OAuth를 차단합니다.
- 해결책 - 개인 머신이 가장 빠른 대안입니다.
Windsurf가 네이티브 HTTP로 연결하지 못함
- 증상 - Windsurf가 MCP 엔드포인트에 연결하지 못하거나 OAuth가 불안정합니다.
- 원인 - Windsurf는 네이티브 streamable HTTP가 아니라
mcp-remote를 통해 연결합니다. - 해결책 -
mcp-remote명령 형태를 사용하세요:{ "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.clickhouse.cloud/mcp"] }(모듈 06에서 ClickStack MCP를 연결할 때는/mcp를/clickstack으로 바꾸세요).