[TIL] Windows(Git Bash)에서 PostgreSQL + Claude Code MCP 연결하기

728x90

[TIL] Windows(Git Bash)에서 PostgreSQL + Claude Code MCP 연결하기

맥 기준 튜토리얼(brew install postgresql)을 윈도우 Git Bash 환경으로 옮기면서,
PostgreSQL MCP와 GitHub MCP를 Claude Code에 붙이기까지 겪은 과정과 삽질 기록.


목표

  1. Windows에 PostgreSQL 설치하고 샘플 DB 만들기
  2. Claude Code에 PostgreSQL MCP 등록해서 자연어로 DB 분석하기
  3. Claude Code에 GitHub MCP 등록해서 내 저장소 활동 분석하기

1. PostgreSQL 설치 (macOS → Windows 변환)

macOS Windows (Git Bash)
brew install postgresql winget install PostgreSQL.PostgreSQL.17
brew services start postgresql net start postgresql-x64-17 (관리자 권한)
createdb myapp_db createdb -U postgres myapp_db
psql myapp_db << EOF Git Bash에서는 heredoc 그대로 사용 가능
export PATH="$PATH:/c/Program Files/PostgreSQL/17/bin"   # psql, createdb 경로 추가
export PGUSER=postgres                                     # 기본 접속 계정
export PGPASSWORD=postgres                                 # 접속 비밀번호
export PGCLIENTENCODING=UTF8                               # 한글 깨짐 방지

createdb myapp_db

샘플 스키마

회원 → 주문 → 주문상세 ← 상품 구조로 구성했다.

users 1 ──< N orders 1 ──< N order_items N >── 1 products
psql -d myapp_db << 'EOF'
CREATE TABLE users (
    id          SERIAL PRIMARY KEY,
    name        VARCHAR(50)  NOT NULL,
    email       VARCHAR(100) NOT NULL UNIQUE,
    created_at  TIMESTAMP    NOT NULL DEFAULT NOW()
);

CREATE TABLE products (
    id     SERIAL PRIMARY KEY,
    name   VARCHAR(100)  NOT NULL,
    price  NUMERIC(10,2) NOT NULL CHECK (price >= 0),
    stock  INT           NOT NULL DEFAULT 0
);

CREATE TABLE orders (
    id          SERIAL PRIMARY KEY,
    user_id     INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    status      VARCHAR(20) NOT NULL DEFAULT 'pending',
    ordered_at  TIMESTAMP   NOT NULL DEFAULT NOW()
);

CREATE TABLE order_items (
    id          SERIAL PRIMARY KEY,
    order_id    INT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
    product_id  INT NOT NULL REFERENCES products(id),
    quantity    INT NOT NULL CHECK (quantity > 0),
    unit_price  NUMERIC(10,2) NOT NULL   -- 주문 당시 가격 보존
);

INSERT INTO users (name, email) VALUES
('김철수', 'chulsoo@example.com'),
('이영희', 'younghee@example.com'),
('박민수', 'minsu@example.com');

INSERT INTO products (name, price, stock) VALUES
('무선 키보드', 49000, 30), ('게이밍 마우스', 35000, 50),
('27인치 모니터', 289000, 10), ('USB-C 허브', 25000, 100);

INSERT INTO orders (user_id, status) VALUES (1, 'paid'), (2, 'shipped'), (1, 'pending');

INSERT INTO order_items (order_id, product_id, quantity, unit_price) VALUES
(1, 1, 1, 49000), (1, 2, 2, 35000), (2, 3, 1, 289000), (3, 4, 3, 25000);
EOF
  • 'EOF'처럼 따옴표를 붙이면 bash가 SQL 안의 $를 변수로 해석하지 않는다.
  • SERIAL은 자동 증가 PK, REFERENCES ... ON DELETE CASCADE는 부모 삭제 시 자식도 삭제.

2. 설치하면서 겪은 문제들

export PATH 오타로 PATH가 통째로 날아감

export PATH="$/c/Program Files/PostgreSQL/17/bin"       # ❌ 기존 PATH 사라짐
export PATH="$PATH:/c/Program Files/PostgreSQL/17/bin"  # ✅

증상: net: command not found. net.exe가 있는 C:\Windows\System32까지 PATH에서 빠졌기 때문. 창을 새로 열면 복구된다.

System error 5 / Access is denied

net start는 관리자 권한이 필요하다. 다만 설치 직후엔 서비스가 이미 떠 있는 경우가 많으니 먼저 확인.

sc query postgresql-x64-17    # STATE: 4 RUNNING 이면 시작할 필요 없음

③ 관리자 Git Bash에서 붙여넣기가 안 됨

관리자 권한으로 열면 mintty가 아닌 기본 콘솔 창으로 열려 Ctrl+V^V로 입력된다.
관리자 작업은 스크립트 파일로 만들어두고 관리자 창에선 bash ~/script.sh 한 줄만 타이핑하는 게 편했다.

set -e를 터미널에 직접 치면 안 됨

스크립트용 옵션이다. 인터랙티브 셸에서 켜두면 명령 하나만 실패해도 터미널 창이 닫힌다.

export 없이 변수 설정 → 비밀번호가 전달 안 됨

PGPASSWORD=1234          # 현재 셸 변수일 뿐, createdb 같은 자식 프로세스에 전달 안 됨
export PGPASSWORD=1234   # 환경변수로 내보내야 전달됨

export 후엔 암호: 프롬프트가 더 이상 안 뜬다. 그런데도 인증 실패면 비밀번호 자체가 틀린 것.
winget 설치는 비밀번호 설정 단계가 없어서, 결국 실제 비밀번호는 postgres였다.

오타 주의: PGCLIENTENCOODING ❌ → PGCLIENTENCODING


3. PostgreSQL MCP 등록

MSYS_NO_PATHCONV=1 claude mcp add mcp-cafedb -s user -- \
  cmd /c npx -y @modelcontextprotocol/server-postgres \
  "postgresql://postgres:postgres@localhost:5432/myapp_db"
부분 의미
MSYS_NO_PATHCONV=1 Git Bash가 /cC:/ 경로로 바꿔버리는 것을 막음
claude mcp add ~/.claude.json에 MCP 서버 설정을 기록 (서버를 바로 띄우는 건 아님)
mcp-cafedb 서버 이름표. 도구 이름이 mcp__mcp-cafedb__query 형태가 됨
-s user 모든 폴더에서 사용 (local: 현재 폴더만 / project: .mcp.json으로 팀 공유)
-- 여기부터는 claude 옵션이 아니라 서버 실행 명령
cmd /c Windows의 npx.cmd 배치 파일이라 cmd를 거쳐야 실행됨
npx -y 패키지를 설치 확인 질문 없이 바로 실행
server-postgres 읽기 전용 트랜잭션으로 SQL 실행 + 테이블 스키마 제공
접속 URL postgresql://사용자:비밀번호@호스트:포트/DB (:가 아니라 @ 주의)
claude mcp list              # ✓ Connected 확인
claude mcp get mcp-cafedb    # 저장된 설정 확인

설정은 어디에 저장되나?

scope 위치
user ~/.claude.json 최상위 mcpServers
local ~/.claude.json > projects["경로"].mcpServers
project 프로젝트 루트의 .mcp.json

-s user로 등록했다면 .mcp.json은 존재하지 않는다.

결과

Claude Code에서 데이터베이스 사용자 현황을 분석해줘라고 하니 Called mcp-cafedb 3 times 후 가입자 3명, 주문 전환율 2/3, 무주문 사용자(박민수)까지 분석해줬다.

MCP를 진짜 썼는지 확인하는 법: Claude Code에서 Ctrl + O로 도구 호출 내역을 펼친다.
mcp__서버명__도구명이면 MCP 사용, Bash(git ...)이면 터미널 명령으로 우회한 것.


4. GitHub MCP 등록 — 삽질의 연속

처음 손으로 작성한 설정 (문제 3개)

"mcpServers": {
  "github": {
    "command": "docker",
    "args": ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
             "ghcr.io/github/github-mcp-server"],
    "env": {
      "GITHUB_PERSONAL_ACCESS_TOKEN": ${env:GITHUB_TOKEN}"
    }
  }
}
  1. JSON 문법 오류: 값 앞의 여는 따옴표 " 누락
  2. ${env:VAR}는 VS Code 문법: 참조한 GITHUB_TOKEN 환경변수 자체가 시스템에 없어서 토큰이 비어 있었음
  3. projects["C:/Users/admin"] 아래에 작성 → 홈 폴더에서 claude를 켰을 때만 동작하는 local scope

증상

/mcp → Failed to reconnect to github: -32000
claude mcp get github → Status: ✘ Failed to connect

원인 1: Docker Desktop 데몬이 꺼져 있었음

failed to connect to the docker API at npipe:////./pipe/dockerDesktopLinuxEngine

docker --version은 클라이언트만 확인하므로 정상으로 나온다. 엔진이 떠 있는지는 docker info로 확인해야 한다.

docker info --format '{{.ServerVersion}}'   # 버전이 나오면 엔진 실행 중

→ Docker Desktop 설정에서 Start Docker Desktop when you sign in 체크.

원인 2: 토큰 환경변수가 없었음

MCP 서버 프로세스는 claude를 실행한 프로세스의 환경변수를 물려받는다.

토큰 저장 방식 적용 범위
export (현재 창) 그 창을 닫으면 사라짐
~/.bashrc에 추가 Git Bash에서 켠 claude만
setx (Windows 사용자 환경변수) 어디서 켜든 적용 ✅
setx GITHUB_TOKEN "ghp_..."    # 새로 여는 모든 프로그램에 적용 (기존 창엔 X)
  • echo '...' >> ~/.bashrc: echo는 print지만 >>파일 끝에 덧붙이기가 된다.
  • source ~/.bashrc: .bashrc는 창이 열릴 때만 읽히므로, 지금 창에 즉시 반영하려고 실행.

해결

  1. GitHub → Settings → Developer settings → Personal access tokens에서 repo scope 토큰 발급
  2. setx로 사용자 환경변수 등록
  3. Docker Desktop 실행
  4. Claude Code 완전 재시작/mcp 재연결 → 정상 연결

docker run --rm 유의사항

--rm은 컨테이너를 매번 새로 만들고 지운다. OAuth 기기 인증(device flow)으로 붙이면 재연결마다 인증을 반복할 수 있다. PAT를 환경변수로 고정해두면 이 반복을 피할 수 있다.


5. GitHub MCP로 해본 것

사용된 도구: mcp__github__get_me, search_repositories, list_pull_requests, list_commits

2026년 활동 요약

  • 활동 저장소 12개 / 커밋 약 199건 / 병합 PR 약 47건
  • 1위 citywatch-fe-lab: 커밋 76, PR 24 (전체 커밋의 38%)
  • 흐름: 연초 K8s(CKA) → 중반 FE 대형 프로젝트 → 최근 AI/LLM·추천 시스템 실습

최근 7일

  • movie_recommend_system: 임베딩/TF-IDF → Kiwi 형태소 분석 + BM25로 전환
  • AI_EXAMPLE: LLM function calling 기반 QA 프로그램
  • JS_Algorithm-DataStructuer: 코딩테스트 풀이

첫 분석은 MCP 인증 전이라 Claude가 GitHub REST API를 직접 호출해 우회했었다.
MCP 연결 후에는 mcp__github__* 도구로 조회된 것을 확인했다.


배운 점 정리

  • Git Bash ≠ Linux: /c 경로 변환(MSYS_NO_PATHCONV), .cmd 실행에 cmd /c 필요, 관리자 콘솔 붙여넣기 불가 등 Windows 특유의 함정이 있다.
  • export의 의미: 셸 변수와 환경변수는 다르다. 자식 프로세스(psql, MCP 서버)에 넘기려면 export 필수.
  • docker --version ≠ Docker 실행 중: 엔진 상태는 docker info.
  • 설정 파일은 손으로 쓰지 말고 claude mcp add: 따옴표 하나로 전체 설정이 깨진다.
  • MCP가 실패하면 Claude는 조용히 다른 방법(Bash, API 직접 호출)으로 우회한다. 결과만 보지 말고 Ctrl + O로 실제 호출 도구를 확인하자.
  • 토큰은 채팅창·블로그에 절대 붙여넣지 말 것. 노출됐다면 즉시 revoke 후 재발급.
728x90