본문으로 건너뛰기
페이지 목차
이 페이지에서 검색

AI 드리븐

이 페이지에 묻기

AI 드리븐 · 현재 차시와 목차 본문에서만 찾아 답합니다. 답을 지어내지 않고 해당하는 대목을 그대로 보여 주며, 여기에 없으면 없다고 알려 드립니다.

생성형 AI가 아니라 이 페이지 본문을 찾아 그대로 보여 주는 방식입니다. 외부로 나가는 요청이 없습니다.

AI · DEVELOPMENT

AI 드리븐

생성 수정

요구사항과 역할 정의부터 구현·검증·배포·운영까지, AI와 함께 개발하며 사람이 판단할 기준을 정리합니다.

26개 문서 · 2일차 · 13 / 26

12차시 · 데이터 관리 역할

지도 위치 : 2일차 · 구현과 검증 · 구현 | 이전: 11차시 프론트엔드 역할: 화면과 경계 | 다음: 13차시 검증 ① 코드·동작 점검 키워드 : 데이터의 영구 저장, 데이터 구조와 규칙, 파괴 방지 강제 장치

이 차시를 다 읽으면

  1. 데이터를 둘 수 있는 네 곳을 디스크 ↔ 메모리 축에 놓고, 예약 · 결제가 왜 DB에 있어야 하는지 말할 수 있다.
  2. 제약조건 을 유와 종차로 정의하고, 코드의 검사와 달리 코드에 버그가 있어도 지켜지는 이유를 설명할 수 있다.
  3. 트랜잭션 을 정의하고, 클래스온에서 묶어야 할 변경 한 쌍을 댈 수 있다.
  4. 마이그레이션 을 정의하고, 이미 적용된 파일을 고치지 않는 이유와 위험 단어 다섯 개를 말할 수 있다.
  5. 파괴 방지 장치를 여러 층 으로 두는 이유와, 훅 이 지침 파일의 "하지 마"와 어떻게 다른지 설명할 수 있다.

0. 이 차시의 판별 축

#축왼쪽 (0)오른쪽 (1)이 축으로 갈리는 것큰 축 (README 5장)
1꺼도 남는가디스크 — DB, 파일 저장소메모리 — 변수, 캐시예약 · 결제를 어디에 두는가① 디스크 ↔ 메모리
2누가 규칙을 지키는가부탁 — 코드의 검사, 지침 파일의 "DROP 하지 마"강제 — DB 제약조건, 훅, 계정 권한버그 · 실수가 있어도 지켜지는가부탁 ↔ 강제
3되돌릴 수 있는가코드 · 설정 파일 — 다시 쓰면 됨데이터 삭제 — 돌아오지 않음어디에 가장 강한 장치를 두는가되돌릴 수 있는가
4구조 변경이 기록되는가DB 관리 도구로 직접 변경마이그레이션 파일로 변경다른 환경에 똑같이 재현되는가① 디스크 ↔ 메모리 (기록이 남는가)

이 차시가 답하는 질문은 "사라지면 돌아오지 않는 것을 어떻게 지키는가" 입니다. 코드는 다시 쓰면 되지만 데이터는 그렇지 않습니다(축 3). 그래서 규칙을 부탁(코드 · 지침)이 아니라 강제(DB 자체 · 훅) 에 새깁니다(축 2). 앞에서 배운 강제 사다리(2차시)를 처음으로 본격적으로 쓰는 차시입니다.


1. 데이터의 영구 저장

저장 위치서버를 재시작하면0절 축 1쓰임
메모리 (프로그램 안의 변수)사라짐메모리계산 중 임시값
캐시사라질 수 있음메모리 쪽자주 읽는 값을 빠르게
데이터베이스 (DB)유지디스크예약, 결제, 사용자
파일 저장소유지디스크클래스 사진

데이터베이스 — [저장소]인데, [ 데이터를 표(테이블) 형태로 영구 저장하고, 규칙과 동시 접근을 스스로 관리한다 ]는 점에서 그냥 파일에 적어 두는 것과 구별된다.

⚠️ "남은 자리 수를 서버 메모리에 들고 있다가 가끔 저장" 같은 설계는 서버가 재시작되거나 서버가 두 대가 되는 순간 숫자가 틀어집니다. 돈과 자리는 언제나 디스크(DB)가 기준 입니다.


2. 데이터 구조 — 클래스온의 표

users(id, email, name, phone, created_at)
classes(id, title, studio_name, price, ...)
sessions(id, class_id → classes, date, capacity, remaining)      # 날짜별 회차
reservations(id, user_id → users, session_id → sessions, headcount, amount, status, created_at)
payments(id, reservation_id → reservations, pg_payment_key, amount, status, ...)

🔍 읽는 포인트 : 괄호 안이 각 표의 칸(열)이고, →는 "다른 표의 행을 가리킨다" 는 뜻입니다. 예약은 사용자와 회차를, 결제는 예약을 가리킵니다.


3. ⭐ 데이터 규칙 — 제약조건

3.1 정의

제약조건 (Constraint) — [데이터 규칙]인데, [ DB가 스스로 지켜서, 어떤 코드가 어떤 경로로 쓰든 규칙을 어기는 쓰기를 거부한다 ]는 점에서 서버 코드 안의 입력 검사와 구별된다.

제약조건뜻클래스온 예
PRIMARY KEY행을 하나로 식별모든 표의 id
FOREIGN KEY다른 표에 실제로 있는 값만없는 회차에 대한 예약 불가
NOT NULL비워 둘 수 없음amount, status
UNIQUE중복 불가users.email, payments.pg_payment_key (같은 결제를 두 번 기록하지 않음, 16차시)
CHECK값의 범위remaining >= 0, headcount BETWEEN 1 AND 4

상태 값은 정해진 것만 — reservations.status는 PENDING_PAYMENT · CONFIRMED · CANCELLED · REFUNDED 같은 정해진 목록 중 하나로 제한합니다(16차시의 상태 전이).

3.2 경계 — 코드의 검사 ↔ 제약조건

서버 코드의 검사 (10차시)DB 제약조건
0절 축 2부탁 — 코드가 지키기로 한 것강제 — DB가 거부
코드에 버그가 있으면뚫린다그래도 지켜진다
다른 경로(관리 스크립트, 다른 서버, AI가 직접 실행한 질의)로 쓰면검사를 거치지 않는다그래도 지켜진다
실패 메시지친절하게 만들 수 있음투박함 → 서버가 받아서 바꿔 줌

둘 다 둡니다. 코드 검사는 사용자에게 좋은 메시지를 주고, 제약조건은 마지막 방어선 입니다. CHECK (remaining >= 0) 하나가 있으면, 코드의 동시성 버그로 자리를 초과 차감하려 해도 DB가 거부합니다.

앞으로 다시 만납니다 — 13차시에서 두 사람이 동시에 마지막 자리를 예약하는 경쟁 상태를 볼 때, 이 CHECK가 "마지막 방어선"으로 다시 나옵니다. 16차시에서는 UNIQUE가 중복 결제 기록을 막습니다.

3.3 반례 — 이건 제약조건이 아닙니다

대상왜 아닌가
지침 파일의 "남은 자리는 음수가 되면 안 된다"에이전트에게 하는 부탁 . DB는 모름
서버 코드의 if (remaining < 0) throw코드 검사. 그 코드를 거치지 않는 경로에서는 무력
화면의 "인원 1~4" 입력 제한편의용 (11차시)

4. 트랜잭션 — 함께 성공하거나 함께 실패

트랜잭션 (Transaction) — [DB 작업 단위]인데, [ 여러 변경을 하나로 묶어 모두 반영되거나 하나도 반영되지 않게 한다 ]는 점에서 변경을 하나씩 따로 저장하는 것과 구별된다.

묶지 않으면묶으면
① 자리 1 차감(성공) → ② 예약 생성 중 오류(실패) → 자리만 줄고 예약은 없음② 실패 시 ①도 취소 → 처음 상태 그대로

클래스온에서 반드시 묶을 쌍은 "회차의 남은 자리 차감 + 예약 생성" 입니다. 10차시 원칙 표의 "함께 성공하거나 함께 실패"가 이것입니다.

⚠️ 트랜잭션은 한 요청 안의 묶음 을 지켜 줍니다. 두 요청이 동시에 같은 자리를 노리는 문제는 트랜잭션만으로 다 풀리지 않습니다. 그 이야기가 13차시입니다.

💡 비유는 마지막에 — 계좌 이체에서 "내 통장 출금"과 "상대 통장 입금"은 한 묶음입니다. 출금만 되고 입금이 안 된 상태는 허용되지 않습니다.


5. 마이그레이션 — 구조 변경을 파일로

5.1 정의와 원칙

마이그레이션 (Migration) — [DB 구조 변경 방식]인데, [ 변경을 순번 붙은 파일로 남기고 그 순서대로 적용한다 ]는 점에서 DB 관리 도구로 직접 접속해 바꾸는 방식과 구별된다.

apps/api/migrations/
├── 001_create_users.sql
├── 002_create_classes_and_sessions.sql
└── 003_create_reservations.sql

🔍 읽는 포인트 : 파일 이름 앞의 번호가 적용 순서 입니다. 새 변경은 항상 새 번호의 새 파일 로 추가됩니다.

마이그레이션으로 얻는 것0절의 어느 축
누가 · 언제 · 무엇을 바꿨는지 Git에 남음축 4 (기록)
다른 환경(시험 · 운영)에 같은 순서로 똑같이 적용축 4 (재현), 15차시
리뷰할 수 있음 — 운영에 닿기 전에 위험을 볼 기회축 3 (되돌릴 수 없는 것 앞에 관문)

⚠️ 이미 적용된 마이그레이션 파일은 고치지 않습니다. 이미 적용된 환경은 그 파일을 다시 실행하지 않으므로, 고쳐 봐야 환경마다 구조가 달라질 뿐입니다. 바꾸려면 새 파일을 추가합니다.

5.2 ⭐ SQL을 못 읽어도 잡을 수 있는 위험 단어

단어뜻신호
DROP TABLE / DROP DATABASE표 · DB 통째로 삭제❌ 멈춤
TRUNCATE표의 모든 행 삭제❌ 멈춤
DELETE (특히 WHERE 없이)행 삭제 (조건 없으면 전부)❌ 멈춤
ALTER ... DROP COLUMN칸 삭제 — 그 칸의 데이터도 사라짐❌ 멈춤
RENAME이름 변경 — 옛 이름을 쓰는 코드가 깨짐⚠️ 확인

하나라도 보이면 멈추고 7절 실습의 질문을 던집니다. 반대로 CHECK · UNIQUE · NOT NULL은 규칙을 더하는 단어입니다(README 9.5).


6. ⭐ 파괴 방지 강제 장치

6.1 왜 여러 층인가

에이전트는 문제를 "해결"하려다 표를 지우고 다시 만드는 방법을 고를 수 있습니다. 로컬에서는 괜찮지만 운영 DB라면 사고입니다. 장치 하나는 언젠가 뚫리므로 여러 겹으로 막습니다.

층장치막는 것
에이전트훅 — 위험한 명령을 실행 직전에 검사해 차단DROP TABLE, TRUNCATE 실행
에이전트권한 — 운영 DB 접속 정보 파일 읽기 거부 (14차시)운영 DB 접근 자체
DB계정 분리 — 앱이 쓰는 계정은 행 읽기 · 쓰기만, 표 삭제 권한 없음코드 · 에이전트의 실수
운영백업과 복구 연습그래도 일어난 사고
리뷰마이그레이션 파일 확인 (5.2 + 교차 질문)의도된 파괴적 변경

6.2 훅 — 에이전트가 잊어도 작동하는 장치

앞에서 배운 훅 (2차시)은 정해진 시점에 자동으로 실행되는 검사입니다. 여기서는 "에이전트가 명령을 실행하기 직전"에 겁니다.

// .claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": ".claude/hooks/block-destructive-sql.sh" }]
      }
    ]
  }
}

🔍 읽는 포인트 : PreToolUse(도구 쓰기 직전 ) + Bash(명령 실행) = "에이전트가 명령을 실행하기 직전마다 이 스크립트를 돌린다".

#!/bin/bash
# .claude/hooks/block-destructive-sql.sh
# 실행하려는 명령이 표준입력으로 JSON 형태로 들어옴
cmd=$(jq -r '.tool_input.command')
if echo "$cmd" | grep -qiE 'drop (table|database)|truncate'; then
  echo "파괴적인 SQL은 차단됩니다. 마이그레이션 파일로 작성하고 사람의 검토를 받으세요." >&2
  exit 2   # 2 = 차단하고 이유를 에이전트에게 전달
fi
exit 0

🔍 읽는 포인트 : grep 줄의 단어 목록 (막을 것)과 exit 2( 차단 )만 보면 됩니다. exit 0은 통과입니다.

지침 파일의 "DROP 하지 마"훅
0절 축 2부탁강제
에이전트가 잊거나, 맥락이 길어져 밀려나면어긴다그래도 막힌다
막는 범위에이전트가 기억하는 한 전부적어 둔 단어만 — 목록에 없는 방법은 통과

⚠️ 마지막 줄이 훅의 한계입니다. 예를 들어 DB 관리 도구를 다른 방식으로 부르면 이 단어 검사를 피할 수 있습니다. 그래서 6.1처럼 DB 계정 권한 이 아래에서 한 번 더 받칩니다.

💡 비유는 마지막에 — 지침 파일은 사내 규정집 , 훅은 출입 게이트 , DB 계정 권한은 금고 자체의 잠금 입니다. 규정을 잊어도 게이트가, 게이트를 돌아가도 금고가 막습니다.


7. 클래스온에 적용하면 — 데이터 역할

# .claude/agents/data.md
## 책임
- 표 구조, 제약조건, 마이그레이션 파일 작성
## 하지 않는 일
- 이미 적용된 마이그레이션 파일 수정
- 운영 DB에 직접 접속하거나 명령 실행
- DROP / TRUNCATE / 조건 없는 DELETE 실행 (훅으로도 차단됨)
## 완료 조건
- 새 마이그레이션을 로컬에 적용한 출력 원문
- 제약조건 위반 시도(음수 자리, 중복 결제 키)가 DB에서 거부된 출력 원문

🔍 읽는 포인트 : 완료 조건의 둘째 줄 — 규칙이 실제로 거부하는 것을 보여 달라 는 요구입니다. "제약조건을 걸었습니다"라는 주장 대신 증거를 받습니다.


8. 실습 — 맡기고 검수하기

지시

1. 2절의 표 구조로 마이그레이션 파일을 만들고 로컬 DB에 적용해줘. 3.1의 제약조건을 모두 포함해.
2. 아래 쓰기를 DB에 직접 시도하고, 각각 거부된 출력 원문을 붙여줘.
   - sessions.remaining을 -1로 만들기
   - 같은 pg_payment_key로 payments 행 두 개 넣기
   - headcount 5인 예약 넣기
3. 6.2의 훅을 설치한 뒤, 로컬 DB에 "DROP TABLE reservations"를 실행해 봐. 차단 메시지 원문을 붙여줘.
4. 방금 만든 마이그레이션에 대해: 기존 데이터를 지우거나 바꾸거나 읽을 수 없게 만드는 경우가 있어?
   예/아니오로 먼저 답하고, 근거와 되돌리는 방법을 말해줘.
결과는 [시도 | 기대 | 실제 결과 | 통과?] 표로.

받을 증거

  • 마이그레이션 적용 출력, 제약조건 위반 시도 3건의 거부 출력 원문
  • 훅 차단 메시지 원문
  • 4번 질문에 대한 예/아니오 답과 근거

내가 직접 확인할 것

볼 것이걸로 아는 것 / 왜 내가 보는가
DB를 표 형태로 보여 주는 도구(TablePlus, DBeaver, 관리형 DB의 웹 화면)로 표를 직접 연다엑셀처럼 생겨서 코드 없이 "예약이 몇 건인지", "남은 자리가 맞는지"를 볼 수 있습니다. 13차시 행동 시험 뒤의 결과 확인에 계속 씁니다. ⚠️ 운영 DB는 읽기 전용 계정으로만
마이그레이션 파일에서 5.2의 위험 단어 검색하나라도 있으면 멈춤
4번 질문을 다른 역할(13차시의 리뷰 역할)에게 따로 물어 답이 일치하는가만든 AI의 "안전합니다"는 주장일 뿐. 교차 검증 (README 9.1)
훅 차단 메시지를 눈으로 봤는가장치가 실제로 작동하는 것을 봐야 믿을 수 있습니다
운영 적용 전: 백업이 있는지 , 복구해 본 적이 있는지되돌릴 수 없는 작업 앞의 마지막 확인

부록 A. 스스로 확인하기

#질문답이 있는 곳
1저장 위치 네 곳을 디스크 ↔ 메모리 축에 놓으면?1
2제약조건을 유와 종차로 정의하면?3.1
3CHECK (remaining >= 0)이 코드 버그가 있어도 데이터를 지키는 원리는?3.2
4payments.pg_payment_key에 UNIQUE를 거는 이유는?3.1
5트랜잭션으로 묶어야 할 클래스온의 변경 한 쌍은? 트랜잭션이 풀지 못하는 문제는?4
6마이그레이션으로 얻는 세 가지는? 이미 적용된 파일을 왜 고치지 않는가?5.1
7SQL을 못 읽어도 찾을 수 있는 위험 단어 다섯 개는?5.2
8파괴 방지 장치를 여러 층으로 두는 이유는? 훅의 한계는?6.1, 6.2
9지침 파일의 "하지 마"와 훅은 어느 축에서 갈리는가?0, 6.2

부록 B. 자주 하는 실수

실수바로잡기
규칙을 코드에만 두고 DB 제약조건은 비워 둔다❌ 제약조건은 마지막 방어선 (3.2)
개발 중 DB 관리 도구로 구조를 직접 바꾼다❌ 다른 환경과 어긋납니다. 마이그레이션 파일로 (5.1)
이미 적용된 마이그레이션 파일을 고친다❌ 새 파일을 추가 (5.1)
앱이 DB 관리자 계정으로 접속한다❌ 앱 계정은 행 읽기 · 쓰기만 (6.1)
"훅을 걸었으니 DB는 안전하다"⚠️ 훅은 적어 둔 단어만 막습니다. 계정 권한이 함께 (6.2)
백업은 설정했지만 복구해 본 적이 없다⚠️ 복구 연습까지가 백업입니다 (6.1)
"제약조건을 걸었습니다"라는 보고를 그대로 받는다⭕ 위반 시도가 거부된 출력 을 받습니다 (7, 8)

부록 C. NotebookLM 복습 프롬프트

이 12차시 노트만 근거로 6문제를 내줘. 비전공자 기준으로.
"제약조건과 코드 검사의 차이(부탁↔강제)", "트랜잭션", "마이그레이션의 위험 단어", "훅과 지침 파일의 차이"는 반드시 포함해줘.
답은 내가 답한 다음에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.