1강 ~ 4강 실습 중심 ⏱ 약 100분

 

0. "1강 ~ 4강 실습 준비" 학습 목표

→ inventory DB와 세 실습 테이블을 구축하고, 역할별 계정으로 MCP를 읽기 전용 연결하는 전체 흐름을 확인합니다.

더보기

0.1 학습 대상과 선수 지식

 

이 강의는 다음 학습자를 대상으로 합니다.

  • VS Code와 Python을 이용한 소프트웨어 개발 학습 중에 있으며, Ubuntu 터미널을 다뤄본 학습자
  • MySQL 기본 SQL을 실행할 수 있는 학습자
  • Claude Code에서 대화를 시작하고 권한 요청을 확인할 수 있는 학습자
  • MCP가 AI 도구와 외부 시스템을 연결하는 통로라는 기본 개념을 학습한 학습자

이 강의에서는 다음 내용을 처음부터 다시 설명하지 않습니다.

  • MySQL 설치와 서비스 관리의 전체 절차
  • CREATE TABLE, INSERT, SELECT, UPDATE, DELETE의 문법 일반
  • VS Code 설치와 기본 편집 방법.
  • Claude Code 설치와 기본 대화 방법
  • MCP 프로토콜의 내부 동작 원리
  • Python과 PySide6의 기본 문법

단, 다음 작업은 1강의 본 실습에 포함합니다.

  • 이 과정에서 사용할 inventory DB 생성
  • 세 실습 테이블과 기준 데이터 생성
  • 역할별 MySQL 계정 생성
  • 이 과정 DB에 MySQL MCP 연결
  • 읽기 전용 계정의 최소 권한 경계 검증

 

 

 

0.2 "1강 ~ 4강 실습 준비"  진행 순서

 

실제 실습은 다음 세 단계로 진행합니다.

1강. 실습 DB와 기준 데이터 구축
  ↓
2강. DB 관리자 권한과 DB 사용자 계정 분리 이해
  ↓
3강. MCP DB 연동
  ↓
4강. MCP DB 사용자 계정의 권한 검증

 

1강에서는 관리자 계정을 실습 DB·테이블·기준 데이터 구축에 사용하면서,

관리자 계정의 이해와 실습 데이터 구축을 진행합니다.

 

2강에서는 이전 단계에서 확인한 관리자 계정 권한을 MCP에 연결하면 안 되는 이유를 이해하고,

inventory_reader, inventory_operator, inventory_app 계정을 역할별로 분리하는 방법을 알아봅니다.

이 시점에는 SQL 자동 실행 금지와 관리자 연결 정보 저장 금지만 먼저 적용합니다.

 

3강에서는 inventory_reader계정을 MySQL MCP에 연결합니다.

 

4강에서는 inventory_reader계정의 권한을 검증합니다. 이 과정에서 앞으로 사용할 계정들의 Claude Code가 MCP를 통해 DB에 접근하는 경로와 Python 소스 코드가 MySQL Driver를 통해 DB에 접근하는 경로가 서로 다르다는 점을 확인합니다.

 

이 시리즈는 (1) DB 구축, (2) 계정 분리와 (3) MCP 연결, (4) 권한 검증과 완료 기준까지 총 4개의 글로 나누어 진행합니다. 이번 (1)에서는 실습 시작 상태 확인과 DB 구축까지 진행합니다.

 

 

 

0.3 실습 화면 구성과 입력창 용어 통일

 

여러분이 실습 환경 설정 후, 사용할 화면 구성 입니다. 

 


1. VS Code editor

ex) 소스코드 에디터에 입력하세요.

Source Code, SQL Script, markdown 같은 문장들은 VS Code editor 에서 편집하고,

 

2. Shell Prompt, (Termianl, Console)

ex) 쉘 프롬프트에 입력하세요.

$가 보이는 통합 터미널에서 sudo mysql·pwd·find·claude mcp add는 Ubuntu 명령이므로 터미널의 $ 화면에서 터미널 명령을 실행합니다.

 

3. MySQL Prompt

ex) MySQL 프롬프트에 입력하세요.

mysql>로 시작하는 곳에서 CREATE DATABASE·SELECT는 SQL 쿼리를 입력하고

 

4. Claude Prompt 

ex) 클로드 코드 프롬프트에 입력하세요.

클로드에게 명령 입력에 사용

[Ubuntu 셸]
student@ubuntu:~/projects/inventory-mcp-project$

[MySQL 접속 후]
mysql>

[Claude Code]
자연어 요청을 입력하는 패널

 

 

 

0.4 학습 목표

 

"1강. ~ 4강. 실습 준비"를 마치면 다음 작업을 수행할 수 있습니다.

  1. inventory DB에 세 실습 테이블과 기준 데이터를 구축할 수 있습니다.
  2. 구축에 사용한 MySQL 관리자 권한을 확인할 수 있습니다.
  3. MCP, 실행 하니스, PySide6 앱의 DB 계정을 역할별로 분리할 수 있습니다.
  4. 각 계정에 담당 작업에 필요한 최소 권한만 부여할 수 있습니다.
  5. Claude Code의 MCP 접근과 Python 소스 코드의 Driver 접근을 구분할 수 있습니다.
  6. Claude Code를 inventory_reader 계정의 MySQL MCP에 연결할 수 있습니다.
  7. MCP 조회 성공과 쓰기 차단을 각각 확인할 수 있습니다.
  8. inventory_operator가 제한된 변경만 수행하고 DELETE·DDL은 수행할 수 없음을 검증할 수 있습니다.

 

1. "1강" 학습 목표

→ inventory DB와 세 실습 테이블을 구축하고, 역할별 계정으로 MCP를 읽기 전용 연결하는 전체 흐름을 확인합니다.

더보기

1.1 진행 순서

 

이 단계에서는 터미널과 Claude Code를 사용하여 프로젝트 구조를 만들고,

Claude가 제안한 SQL을 검토한 뒤 관리자 연결에서 직접 실행하여 기준 데이터를 완성합니다.

실습 환경 점검
  ↓
프로젝트 구조 생성
  ↓
Claude Code에 SQL 초안 요청
  ↓
테이블·제약 조건·기준 데이터 검토
  ↓
관리자 연결에서 직접 실행
  ↓
8건 / 16건 / 0건 검증

 

 

 

1.2 완성할 결과물

 

1강 강의 완료 시 다음 상태가 만들어져야 합니다.

inventory-mysql-app/
├── db/
│   ├── schema.sql
│   └── roles.sql
├── harness/
└── app/

inventory DB
├── products                 8건
├── stock_logs              16건
└── operation_requests       0건

DB 접근 경로와 계정
├── Claude Code MCP  ───── inventory_reader
├── Python 하니스    ───── inventory_operator
└── PySide6 앱       ───── inventory_app

 

harnessapp 폴더는 이후 강의에서 사용합니다. 1강에서는 폴더만 준비하고 Python 코드를 작성하지 않습니다.

 

2. 실습 환경 점검

→ MySQL, Claude Code, Node.js 실행 상태와 구축용 관리자 연결을 먼저 확인합니다.

더보기

2.1 실습에 사용할 툴 설치 상태 확인하기

 

Ubuntu 쉘 프롬프트 에서 다음 명령을 실행합니다.

[화면 캡처: mysql·claude·node·npm·npx 버전이 모두 출력되는 터미널 화면]
mysql --version
claude --version
node --version
npm --version
npx --version

 

확인 기준은 다음과 같습니다.

  • mysql이 버전 번호를 출력합니다.
  • claude가 버전 번호를 출력합니다.
  • node, npm, npx가 버전 번호를 출력합니다.

이 강의의 목표는 설치가 아니라 역할별 계정과 권한 경계를 구성하는 것입니다. 실행할 수 없는 도구가 있으면 해당 도구의 기존 설치 자료를 먼저 확인한 후 이 강의로 돌아옵니다.

 

 

2.2 MySQL 서버 실행 상태 확인하기

 

단순히 MySQL 확인 이후, MySQL 실행중인지 확인해야 합니다.

Ubuntu 환경에서는 다음 명령으로 서비스 상태를 확인합니다.

[화면 캡처: MySQL 서비스가 active (running)으로 표시된 화면]
sudo systemctl status mysql --no-pager

 

active (running)이 아니라면 서비스를 시작합니다.

sudo systemctl start mysql
sudo systemctl status mysql --no-pager

 

 

 

2.3 DB 관리자 계정 확인하기

 

수업 환경에서 비밀번호 인증 방식으로 사용하던 로컬 관리자 계정으로 접속합니다.

mysql -u root -p

 

만약, Ubuntu의 소켓 인증 방식으로 관리자 계정을 사용하고 있다면 다음 명령을 실행합니다.

sudo mysql

 

두 방법 중 현재 정상적으로 동작하는 한 가지 방법만 사용합니다. 이 강의를 진행하기 위해 root의 인증 플러그인을 변경하지 않습니다.

 

 

 

2.4 실습 도구들의 입력 위치 구분하기

 

이번 강의에서는 세 도구의 입력 위치를 구분해서 사용합니다. 터미널의 쉘 프롬프트는 위에서 확인했습니다. 

여기에 MySQL Prompt, Claude Prompt 를 같이 사용하게 됩니다.

 

터미널에서 MySQL 관리자 계정으로 접속하면 프롬프트가 $에서 mysql>로 바뀝니다. 다시 터미널 명령을 실행하려면 exit;로 MySQL을 종료합니다.

[화면 캡처: mysql 프롬프트 입력창 화면]

 

터미널에서 Claude를 실행하면 프롬프트가 변경됩니다. 마찬가지로 /exit 를 입력하면 Claude 를 종료합니다.

[화면 캡처: claude code 프롬프트 입력창 화면]

 

화면의 프롬프트 입력할 내용
$ 터미널 명령 mkdir, cd, mysql, claude
mysql> SQL과 MySQL 클라이언트 명령 SHOW TABLES;, SELECT ...;, exit
Claude Code 대화 입력창 자연어 요청과 /mcp 명령 SQL 초안 요청, MCP 상태 확인

 

 

 

2.5 실습 DB 와 중복되는지 확인하기

 

MySQL 프롬프트에서 서버 버전을 확인하고, 실습에 사용할 inventory DB 가 중복 생성되어 있는지 확인합니다.

[화면 캡처: SELECT VERSION()과 SHOW DATABASES 실행 결과]
SELECT VERSION();
SHOW DATABASES LIKE 'inventory';

 

만약, 기존 inventory DB가 조회되면 즉시 삭제하지 않습니다. 다른 수업이나 개인 프로젝트의 데이터인지 먼저 확인합니다. 기존 DB 를 삭제하는 경우 다음 명령을 실행합니다.

DROP DATABASE IF EXISTS inventory;

 

다시 DB 조회 명령을 실행 할 때, 결과에 Empty set이 뜨거나 inventory가 조회되지 않는다면 안전하게 삭제가 완료된 것입니다.

 

💡 팁: 관리자 계정은 실습 환경 준비 중  2강의 DB 구축과 3강의 역할별 계정 구성에만 사용합니다. 

 

▶ 지금 해보세요

  1. 터미널에서 다섯 가지 도구의 버전을 확인합니다.
  2. MySQL 서비스 상태를 확인하고 필요하면 시작합니다.
  3. 관리자 계정으로 접속해 서버 버전과 기존 inventory DB 유무를 확인합니다.

✔ 확인 기준: Claude Code와 npx가 정상 실행되고, MySQL 서버가 정상 실행 중이고, DB 관리자 계정으로 실행할 수 있으며, 기존에 inventory DB가 중복되는지 여부를 확인했습니다.

 

3. 프로젝트 구조 만들기

→ 프로젝트 구조를 만들고, Claude가 제안한 SQL을 검토한 뒤 관리자 연결에서 직접 실행해 기준 데이터를 완성합니다.

더보기

방법1. 쉘 프롬프트에서 프로젝트 구성하기

 

새 프로젝트 폴더 구로를 생성하고, SQL 스크립트 파일을 생성합니다.

# 프로젝트 생성 명령
mkdir -p ~/projects/inventory-mysql-app/db
mkdir -p ~/projects/inventory-mysql-app/harness
mkdir -p ~/projects/inventory-mysql-app/app
cd ~/projects/inventory-mysql-app
touch db/schema.sql
touch db/roles.sql

 

 

생성 결과를 확인합니다.

# 하위 2단계 파일 폴더 출력, 정렬
find . -maxdepth 2 -print | sort

 

 

똑같은 방법을 Claude Code로 진행하기 위해, 생성된 폴더를 삭제하고 다시 진행하겠습니다.

다음 명령을 실행해 주세요.

# 홈 디렉터리 이동, 프로젝트 폴더 강제 삭제
cd ~
rm -rf ~/projects

 

 

 

방법 2. Claude Code 사용하기

 

Claude Code를 시작합니다.

claude

 

 

터미널 명령으로도 프로젝트 뼈대를 만들 수 있지만, Claude Code에 요청해 같은 결과를 만들 수도 있습니다. 다음 프롬프트를 Claude Code 대화 입력창에 입력합니다.

~/projects/inventory-mysql-app 경로에 프로젝트 뼈대를 만들어줘.

조건:
- ~/projects 폴더가 없으면 먼저 만든다.
- db/schema.sql과 db/roles.sql은 빈 파일로 만든다.
- harness와 app은 빈 폴더로 만든다.
- 아직 파일 내용은 작성하지 않는다.
- 터미널 명령과 SQL은 실행하지 않는다.

먼저 생성할 경로를 보여주고,
내가 승인한 뒤에만 파일과 폴더를 만들어줘.

 

Claude Code를 사용하더라도 생성할 경로를 먼저 검토하고 승인합니다.

✔ 확인 기준: db/schema.sqldb/roles.sql이 빈 파일로 존재하고, harnessapp이 빈 폴더로 존재하며, Claude Code가 inventory-mysql-app 폴더에서 실행됩니다.

 

 

이 단계에서 작성된 내용은 프로젝트 구조 입니다.

inventory-mysql-app/  # ☑️ ✏️ 프로젝트 구조 생성
├── db/
│   ├── schema.sql    # ☑️ (빈 파일)
│   └── roles.sql     # ☑️ (빈 파일)
├── harness/          # ☑️ (빈 폴더)
└── app/              # ☑️ (빈 폴더)

inventory DB                      # ❌
├── products                 8건  # ❌
├── stock_logs              16건  # ❌
└── operation_requests       0건  # ❌

DB 접근 경로와 계정
├── Claude Code MCP  ───── inventory_reader   # ❌
├── Python 하니스    ───── inventory_operator  # ❌
└── PySide6 앱       ───── inventory_app       # ❌

 

 

4. SQL 초안 만들기

→ 프로젝트 구조를 만들고, Claude가 

더보기

4.1 세 테이블의 역할

 

이제 실제 프로젝트에 사용할 DB의 Table을 설계합니다.

이번 강의에서 만드는 세 테이블은 실습 계속 사용하는 공통 기준 데이터입니다.

 

products — 상품 정보와 현재 재고를 보관합니다.

주요 데이터는 상품명, 카테고리, 단가, 현재 재고, 재주문 기준입니다.

 

stock_logs — 재고가 변경된 이력을 보관합니다.

주요 데이터는 대상 상품, 입고·출고·조정 구분, 변경 수량, 변경 전 재고, 변경 후 재고, 변경 요청 ID입니다. 기존 기준 데이터 16건은 승인·요청 관리 기능을 만들기 전에 입력한 이력이므로 request_idNULL입니다. 6강 이후 통제된 출고 실행으로 생성되는 이력은 operation_requests.request_id와 1:1로 연결합니다.

 

operation_requests — 실제 변경을 실행하기 전에 요청 내용과 처리 상태를 기록합니다.

주요 데이터는 요청 ID, 작업 유형, 대상 상품, 수량, 요청 상태, 요청자와 승인자, 요청·승인·완료 시각입니다. request_id를 기본키로 사용하여 같은 요청 ID가 두 번 등록되는 것을 DB 수준에서 차단합니다.

 

테이블 역할 1강 완료 기준
products 상품 정보와 현재 재고 보관 8건
stock_logs 재고 변경 이력 보관 16건
operation_requests 변경 실행 전 요청 내용과 처리 상태 기록 0건

 

 

 

4.2 Claude 에게 스키마와 기준 데이터 SQL 초안 요청하기

 

Claude Code 대화 입력창에 다음 프롬프트를 입력합니다. Claude가 파일을 수정하거나 SQL을 실행하지 않도록 통제 문장을 포함합니다.

[화면 캡처: Claude Code가 스키마 SQL 초안과 테이블별 제약 조건을 설명하고 승인을 기다리는 화면]
inventory 재고 관리 실습용 db/schema.sql 초안을 작성해줘.

조건:
- products, stock_logs, operation_requests 세 테이블을 만든다.
- products는 상품명, 카테고리, 단가, 현재 재고, 재주문 기준을 가진다.
- operation_requests.request_id는 CHAR(36) 기본키다.
- stock_logs.request_id는 NULL을 허용하는 UNIQUE 외래 키다.
- stock_logs에는 변경 전 재고와 변경 후 재고를 기록한다.
- 상품 8개와 입출고 이력 16건을 넣는다.
- operation_requests는 비어 있어야 한다.
- utf8mb4를 사용한다.

아직 파일을 수정하거나 SQL을 실행하지 마.
먼저 전체 SQL 초안과 테이블별 제약 조건을 설명하고
내 검토를 기다려줘.

 

 

 

4.3 Claude Code가 제안한 SQL 검토하기

 

SQL을 실행하기 전에 다음 네 영역을 확인합니다. 네 영역을 모두 확인한 뒤에만 db/schema.sql 작성을 승인합니다.

 

테이블 생성 순서와 관계

  • products가 먼저 생성되는가?
  • operation_requestsproducts를 참조하는가?
  • stock_logsproductsoperation_requests를 참조하는가?

 

요청 ID 제약

  • operation_requests.request_id가 기본키인가?
  • stock_logs.request_idNULL을 허용하는가?
  • stock_logs.request_idUNIQUE 제약이 있는가?
  • stock_logs.request_idoperation_requests.request_id를 참조하는가?

 

기준 데이터

  • 상품 행이 정확히 8개인가?
  • 입출고 이력 행이 정확히 16개인가?
  • 초기 입출고 이력의 request_id가 모두 NULL인가?
  • operation_requests에 초기 데이터가 들어 있지 않은가?

 

실행 안전성

  • 기존 DB를 무조건 삭제하는 DROP DATABASE가 없는가?
  • 불필요한 사용자 생성이나 권한 변경 SQL이 섞이지 않았는가?
  • Claude Code가 SQL을 자동으로 실행하지 않았는가?

 

 

 

4.4 db/schema.sql 초안 구현안

 

다음 SQL은 과정기준표의 세 테이블·8개·16건·0건 기준을 실행 가능한 형태로 구현한 초안입니다. Claude Code가 제안한 결과를 다음 코드와 대조합니다.

CREATE DATABASE IF NOT EXISTS inventory
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_0900_ai_ci;

USE inventory;

CREATE TABLE IF NOT EXISTS products (
  product_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  product_name VARCHAR(100) NOT NULL UNIQUE,
  category VARCHAR(50) NOT NULL,
  unit_price DECIMAL(10, 2) UNSIGNED NOT NULL,
  stock_quantity INT UNSIGNED NOT NULL DEFAULT 0,
  reorder_level INT UNSIGNED NOT NULL DEFAULT 0,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
    ON UPDATE CURRENT_TIMESTAMP,
  CONSTRAINT chk_products_unit_price
    CHECK (unit_price >= 0),
  CONSTRAINT chk_products_stock_quantity
    CHECK (stock_quantity >= 0),
  CONSTRAINT chk_products_reorder_level
    CHECK (reorder_level >= 0)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS operation_requests (
  request_id CHAR(36) PRIMARY KEY,
  operation_type VARCHAR(30) NOT NULL,
  product_id INT UNSIGNED NOT NULL,
  quantity INT UNSIGNED NOT NULL,
  status ENUM('PLANNED', 'APPROVED', 'COMPLETED', 'FAILED')
    NOT NULL DEFAULT 'PLANNED',
  requested_by VARCHAR(100) NOT NULL,
  approved_by VARCHAR(100) NULL,
  requested_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  approved_at DATETIME NULL,
  completed_at DATETIME NULL,
  CONSTRAINT chk_operation_requests_quantity
    CHECK (quantity > 0),
  CONSTRAINT fk_operation_requests_product
    FOREIGN KEY (product_id)
    REFERENCES products(product_id)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS stock_logs (
  log_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  product_id INT UNSIGNED NOT NULL,
  request_id CHAR(36) NULL,
  movement_type ENUM('IN', 'OUT', 'ADJUSTMENT') NOT NULL,
  quantity INT UNSIGNED NOT NULL,
  stock_before INT UNSIGNED NOT NULL,
  stock_after INT UNSIGNED NOT NULL,
  note VARCHAR(255) NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_stock_logs_request_id
    UNIQUE (request_id),
  CONSTRAINT chk_stock_logs_quantity
    CHECK (quantity > 0),
  CONSTRAINT fk_stock_logs_product
    FOREIGN KEY (product_id)
    REFERENCES products(product_id),
  CONSTRAINT fk_stock_logs_request
    FOREIGN KEY (request_id)
    REFERENCES operation_requests(request_id)
) ENGINE=InnoDB;

INSERT INTO products
  (
    product_id,
    product_name,
    category,
    unit_price,
    stock_quantity,
    reorder_level
  )
VALUES
  (1, '기계식 키보드', '주변기기', 89000.00, 25, 10),
  (2, '무선 마우스', '주변기기', 45000.00, 40, 12),
  (3, 'USB-C 허브', '주변기기', 65000.00, 8, 10),
  (4, '27인치 모니터', '디스플레이', 320000.00, 14, 5),
  (5, '노트북 거치대', '주변기기', 38000.00, 30, 8),
  (6, '웹캠', '주변기기', 78000.00, 3, 6),
  (7, '외장 SSD 1TB', '저장장치', 145000.00, 18, 7),
  (8, '블루투스 스피커', '오디오', 99000.00, 11, 4)
ON DUPLICATE KEY UPDATE
  product_name = VALUES(product_name),
  category = VALUES(category),
  unit_price = VALUES(unit_price),
  stock_quantity = VALUES(stock_quantity),
  reorder_level = VALUES(reorder_level);

INSERT INTO stock_logs
  (
    log_id,
    product_id,
    request_id,
    movement_type,
    quantity,
    stock_before,
    stock_after,
    note,
    created_at
  )
VALUES
  (1, 1, NULL, 'IN', 30, 0, 30, '초기 입고',
   '2026-07-01 09:00:00'),
  (2, 1, NULL, 'OUT', 5, 30, 25, '초기 출고',
   '2026-07-02 10:00:00'),
  (3, 2, NULL, 'IN', 50, 0, 50, '초기 입고',
   '2026-07-01 09:10:00'),
  (4, 2, NULL, 'OUT', 10, 50, 40, '초기 출고',
   '2026-07-02 10:10:00'),
  (5, 3, NULL, 'IN', 15, 0, 15, '초기 입고',
   '2026-07-01 09:20:00'),
  (6, 3, NULL, 'OUT', 7, 15, 8, '초기 출고',
   '2026-07-02 10:20:00'),
  (7, 4, NULL, 'IN', 20, 0, 20, '초기 입고',
   '2026-07-01 09:30:00'),
  (8, 4, NULL, 'OUT', 6, 20, 14, '초기 출고',
   '2026-07-02 10:30:00'),
  (9, 5, NULL, 'IN', 40, 0, 40, '초기 입고',
   '2026-07-01 09:40:00'),
  (10, 5, NULL, 'OUT', 10, 40, 30, '초기 출고',
   '2026-07-02 10:40:00'),
  (11, 6, NULL, 'IN', 10, 0, 10, '초기 입고',
   '2026-07-01 09:50:00'),
  (12, 6, NULL, 'OUT', 7, 10, 3, '초기 출고',
   '2026-07-02 10:50:00'),
  (13, 7, NULL, 'IN', 25, 0, 25, '초기 입고',
   '2026-07-01 10:00:00'),
  (14, 7, NULL, 'OUT', 7, 25, 18, '초기 출고',
   '2026-07-02 11:00:00'),
  (15, 8, NULL, 'IN', 16, 0, 16, '초기 입고',
   '2026-07-01 10:10:00'),
  (16, 8, NULL, 'OUT', 5, 16, 11, '초기 출고',
   '2026-07-02 11:10:00')
ON DUPLICATE KEY UPDATE
  product_id = VALUES(product_id),
  request_id = VALUES(request_id),
  movement_type = VALUES(movement_type),
  quantity = VALUES(quantity),
  stock_before = VALUES(stock_before),
  stock_after = VALUES(stock_after),
  note = VALUES(note),
  created_at = VALUES(created_at);
방금 검토한 확정 SQL을 db/schema.sql에 작성해줘.

조건:
- 보여준 확정 SQL의 테이블명, 열 이름, 제약 조건, 기준 데이터를 바꾸지 않는다.
- db/schema.sql 이외의 파일은 수정하지 않는다.
- SQL과 터미널 명령은 실행하지 않는다.

변경할 파일과 내용을 다시 보여주고 내 승인을 기다려줘.

 

변경 대상이 db/schema.sql 한 파일인지 확인한 뒤 파일 작성만 승인합니다.

 

 

 

4.5 db/schema.sql 초안 작성하기

[화면 캡처: Claude Code가 db/schema.sql 파일에 스크립트 작성하도록 요청]

 

이 단계에서 작성된 내용은 db/schema.sql 파일의 스크립트 입니다.

inventory-mysql-app/  # ✅ 프로젝트 구조 생성
├── db/
│   ├── schema.sql    # ☑️ ✏️ 테이블 설계
│   └── roles.sql     # ✅ (빈 파일)
├── harness/          # ✅ (빈 폴더)
└── app/              # ✅ (빈 폴더)

inventory DB                     # ❌
├── products                 8건 # ❌
├── stock_logs              16건 # ❌
└── operation_requests       0건 # ❌

DB 접근 경로와 계정
├── Claude Code MCP  ───── inventory_reader   # ❌
├── Python 하니스    ───── inventory_operator  # ❌
└── PySide6 앱       ───── inventory_app       # ❌

 

 

5. 데이터 입력하기

→ 프로젝트 구조를 만들고, Claude가 제안한 SQL을 검토한 뒤 관리자 계정에서 직접 실행해 기준 데이터를 완성합니다.

더보기

5.1 DB 관리자 계정에서 db/schema.sql 스키마 실행하기

 

Claude Code를 종료하거나, 별도의 터미널 쉘 프롬프트로 열고 프로젝트 폴더로 이동합니다. 이전 단계에서 생성한 SQL db/schema.sql 파일 실행은 $ MySQL 프롬프트에서 수행해야 합니다.

cd ~/projects/inventory-mysql-app

 

방법 1. root -p 접속 방식

# mysql -u root -p로 schema.sql을 실행
mysql -u root -p < db/schema.sql
# root 계정 접속, inventory DB 선택
mysql -u root -p inventory

 

방법 2. sudo mysql 접속 방식

sudo mysql < db/schema.sql
sudo mysql inventory

 

 

 

5.2 DB 구조와 기준 데이터 검증하기

 

MySQL 입력창에서 다음 SQL을 실행합니다.

[화면 캡처: SHOW TABLES와 세 테이블의 COUNT(*) 결과 화면]
SHOW TABLES;
SELECT COUNT(*) AS products_count FROM products;
SELECT COUNT(*) AS stock_logs_count FROM stock_logs;
SELECT COUNT(*) AS operation_requests_count FROM operation_requests;
SELECT
  product_id,
  product_name,
  stock_quantity,
  reorder_level
FROM products
ORDER BY product_id;

SELECT
  COUNT(*) AS stock_logs_with_request_id
FROM stock_logs
WHERE request_id IS NOT NULL;

 

결과를 다음 기준과 대조합니다.

확인 항목 기대 결과
테이블 수 3개
products 8건
stock_logs 16건
operation_requests 0건
stock_logs.request_id IS NOT NULL 0건
재고가 재주문 기준 이하인 상품 USB-C 허브, 웹캠

 

이 단계에서 작성된 내용은 inventory DB 테이블과 Data 입니다.

inventory-mysql-app/  # ✅ 프로젝트 구조 생성
├── db/
│   ├── schema.sql    # ✅ 테이블 설계
│   └── roles.sql     # ✅ (빈 파일)
├── harness/          # ✅ (빈 폴더)
└── app/              # ✅ (빈 폴더)

inventory DB                     # ☑️ ✏️ DB 구현
├── products                 8건 # ☑️ ✏️ 테이블과 데이터 구현 
├── stock_logs              16건 # ☑️ ✏️ 테이블과 데이터 구현
└── operation_requests       0건 # ☑️ ✏️ 테이블과 데이터 구현

DB 접근 경로와 계정
├── Claude Code MCP  ───── inventory_reader   # ❌
├── Python 하니스    ───── inventory_operator  # ❌
└── PySide6 앱       ───── inventory_app       # ❌

 

▶ 지금 해보세요

  1. Claude Code가 제안한 SQL을 네 영역으로 나누어 검토합니다.
  2. db/schema.sql 한 파일만 작성하도록 승인합니다.
  3. 관리자 연결에서 SQL 파일을 직접 실행합니다.
  4. 테이블 구조와 기준 데이터를 직접 조회합니다.

✔ 확인 기준: 세 테이블이 생성되었고, 상품 8개와 입출고 이력 16건이 조회되며, operation_requests는 비어 있고, 기존 입출고 이력 16건의 request_id가 모두 NULL이며, 관리자 계정 정보가 프로젝트 파일이나 Claude Code 대화에 저장되지 않았습니다.