ACE AI 스타트업 부트캠프 · Day 3 보충 가이드
Day 1에서 화면을 그렸고, Day 2에서 흐름을 그렸습니다. 오늘은 두 영역 밑에 위치하는 데이터의 뼈대를 구축합니다. 세션 시작 전 15분 동안 읽고 실습 동안 곁에 두세요.
목적이 명확하지 않은 정규화는 암기해야 할 규칙에 불과합니다.
집을 짓는 과정에 비유해 봅시다.
코딩은 Day 6에 시작됩니다. 만약 그때 배선 도면이 틀려 있다면, 이미 만든 모든 화면과 API를 다시 허물어야 합니다. 10일 부트캠프에서 이는 치명적입니다. 오늘 이 작업을 수행하는 이유입니다.
어려운 정의 대신 현실의 데이터 통증에서 출발해 봅시다.
온라인 강의 플랫폼을 만든다고 가정합시다. 처음에는 시트 하나로 모든 것을 기록합니다.
| # | 수강생 | 수강생 연락처 | 수강 과목 | 강사명 | 강사 연락처 | 수강료 (원) |
|---|---|---|---|---|---|---|
| 1 | 김철수 | 010-1111-1111 | AI 기획, 데이터 분석 | 이영희 | 010-9999-9999 | 1,200,000 |
| 2 | 박민수 | 010-2222-2222 | AI 기획 | 이영희 | 010-9999-9999 | 600,000 |
| 3 | 김철수 | 010-1111-1112 | 프롬프트 엔지니어링 | 최성민 | 010-8888-8888 | 900,000 |
이 시트는 이미 3가지 사고(이상 현상, Anomaly)를 예약해 두었습니다.
새 과목 "AI 윤리"를 개설했는데 아직 수강생이 없습니다. → 기록할 방법이 없습니다. 수강생이 없으면 행을 만들 수 없습니다.
김철수가 번호를 변경했습니다. → 김철수가 포함된 모든 행을 일일이 수정해야 합니다. 3행만 수정하면 1행과 불일치가 생깁니다. 어느 것이 진짜인가요?
박민수가 환불하여 2행을 삭제합니다. → "AI 기획"의 유일한 수강생 행이 지워지면서 과목 정보 자체가 함께 사라집니다.
한 시트를 목적별 전용 테이블로 분리하여 이 3가지 사고가 일어나지 않게 만드는 것입니다. 1NF/2NF/3NF는 테이블을 잘라내는 3단계 체크리스트입니다.
확인할 질문: 쉼표로 여러 값을 구겨 넣은 셀이 있는가?
표 A에서 수강 과목: "AI 기획, 데이터 분석"이 바로 그 사례입니다. "AI 기획 수강생이 몇 명인가?"를 집계하려면 텍스트를 쪼개야 하므로 관리가 복잡해집니다.
해결책: 행을 분리합니다. 한 셀에 하나의 값만 넣습니다 (김철수 행을 2개로 분리).
A,B,C 형태로 넣는 것입니다. 기획 문서에서는 자연스러워 보이지만 대표적인 1NF 위반입니다. 둘 이상의 값을 가질 수 있는 항목은 별도 테이블로 분리합니다.
1NF 적용 후 각 행은 (수강생 + 과목)이라는 2 부분 조합 이름표(식별자)로 구분됩니다.
확인할 질문: 이 셀의 값을 결정할 때 이름표 두 쪽이 모두 필요한가, 아니면 한 쪽만 필요한가?
| 컬럼명 | 값을 알기 위해 필요한 정보 | 판단 결과 |
|---|---|---|
| 수강 신청일 | 수강생 및 과목 — 둘 다 필요 | 현재 테이블 유지 |
| 수강생 연락처 | 수강생만 알면 됨 (과목 무관) | 분리 → 수강생 테이블로 이동 |
| 과목명 / 수강료 | 과목만 알면 됨 (수강생 무관) | 분리 → 과목 테이블로 이동 |
즉 2NF = "이름표 절반만으로 결정되는 컬럼은 그 절반을 따라 별도 테이블로 이동한다." 이 과정을 통해 수정 이상이 해결됩니다 (수강생 테이블에서 연락처를 한 번만 수정하면 끝).
분리된 과목 테이블을 봅시다: 과목ID, 과목명, 강사명, 강사연락처.
확인할 질문: 이 컬럼은 이름표(과목ID)가 결정하는가, 아니면 옆에 있는 다른 컬럼이 결정하는가?
해결책: 강사 테이블을 새로 만들고 과목 테이블에는 강사ID만 남겨둡니다.
정규화가 항상 정답일까요? 아닙니다. 정규화는 쓰기 일관성을 얻는 대신 읽기 성능을 일부 양보합니다. 5개 테이블로 쪼개면 화면 하나를 그릴 때 5번의 JOIN이 발생합니다.
결제금액이 상품의 현재 가격을 참조하면 안 됩니다. 나중에 상품 가격이 변경되면 과거 모든 영수증이 소급 변경됩니다. 특정 시점의 사실은 참조하지 않고 복사 저장합니다.기호 자체는 어렵지 않습니다. 어떤 기호를 선택해야 할지 결정하는 기준을 배우는 것이 핵심입니다.
ERD (Entity Relationship Diagram)란 쉽게 말해 "무엇이 존재하고 어떻게 연결되어 있는지 보여주는 그림"입니다.
| 종류 | 읽는 법 | 예시 | 실제 구현 방식 |
|---|---|---|---|
| 1:1 | 일대일 | 사용자 ↔ 프로필 상세 | 보통 한 테이블로 합칩니다. 분리한다면 이유를 기록하세요. |
| 1:N | 일대다 (가장 흔함) | 강사 1명 → 과목 여러 개 | "1" 쪽의 ID를 "N" 쪽 테이블에 넣습니다 (과목 테이블에 강사ID 보관). |
| N:M | 다대다 | 수강생 ↔ 과목 | DB에 직접 존재할 수 없습니다. 아래 내용을 참조하세요. |
↑ 1개의 엑셀 시트가 4개의 정규화된 테이블로 분리되었습니다. 수강생-과목 N:M 관계가 수강신청 연결 테이블을 통해 1:N 2개로 풀린 점에 주목하세요.
| 기호 | 의미 | Mermaid 표기 |
|---|---|---|
| || | 정확히 1개 (필수) | ||--|| |
| o| / |o | 0개 또는 1개 (선택) | |o--|| |
| o{ (까마귀 발) | 0개 이상 (선택) | ||--o{ |
| |{ | 1개 이상 (필수) | ||--|{ |
작은 동그라미는 "비어있어도 됨(선택)"을 의미합니다. 강사가 과목을 아직 배정받지 않아도 존재할 수 있다면 ||--o{를 씁니다. 반드시 최소 1개 이상 가져야 한다면 ||--|{를 씁니다. 이 차이가 나중에 "필수 입력 항목인가?" 규칙이 됩니다.
ENROLMENT.student_id는 STUDENT 테이블을 가리킵니다.오늘 팀이 결정해야 할 사항: "사용자가 계정을 탈퇴(삭제)할 때 관련 수강/결제 기록도 삭제할 것인가, 보존할 것인가?" — 이는 기술이 아닌 비즈니스 정책 문제입니다. 환불, 정산, 리포팅이 이 결정에 달려있으므로 기획자와 팀이 직접 결정해야 합니다.
데이터베이스는 3가지 삭제 옵션을 제공합니다: CASCADE (자식 데이터도 연쇄 삭제) / RESTRICT (자식 데이터가 있으면 삭제 거부) / SET NULL (연결만 끊고 기록 보존). 실제 서비스에서는 대부분 실제 삭제(Hard Delete)를 하지 않고 deleted_at 컬럼을 사용하는 논리 삭제(Soft Delete)를 적용합니다. 개인정보 보호법(파기 의무)과 거래 이력 보존 의무 간의 균형을 고려하여 탈퇴 시 익명화 처리할 항목과 보존할 항목을 결정하고 기록하세요.
아직 존재하지 않는 코드가 깨질 것을 상상해야 해서 어렵게 느껴집니다.
Schema (스키마) = 테이블 청사진. 어떤 컬럼이 존재하고 무슨 타입인지 정의한 데이터의 헌법입니다.
영향도 분석은 예측이 아니라 지도 읽기입니다. 한 컬럼에서 출발하여 연결선을 따라 "이 변경이 여기까지 미치는가?"를 확인하는 과정입니다.
↑ 컬럼 이름 하나 바꾸었을 뿐인데 최소 5곳이 흔들립니다. 그중 3곳은 코드가 아닌 문서와 사람입니다.
이 도미노 현상이 바로 "Task 02(용어 표준화)가 왜 중요한가?"에 대한 답입니다. 처음에 용어를 통일해 두면 이 도미노 현상 자체가 발생하지 않습니다. 용어 사전 정립은 가장 저렴하게 가입하는 보험입니다.
| 등급 | 변경 작업 내용 | 이유 | 조치 사항 |
|---|---|---|---|
| 안전 (Safe) | 선택(Null 허용) 컬럼 추가 | 기존 코드가 새 컬럼의 존재를 몰라도 무시하므로 영향 없음 | 즉시 진행 가능 |
| 주의 (Caution) | 컬럼명 변경, 필수(NotNull) 컬럼 추가 | 읽기 코드가 전부 깨지며, 기존 행에 채울 기본값이 필요함 | 영향도 목록 작성 후 진행 |
| 위험 (Dangerous) | 컬럼 삭제, 데이터 타입 변경, 테이블 분리 | 비가역적. 실제 데이터가 소멸하거나 유실될 위험이 큼 | 백업 + 전체 팀 합의 + 의사결정록 작성 |
Task 03 산출물로 아래 표 형식을 그대로 활용할 수 있습니다.
| 변경 항목 | 위험 등급 | 영향받는 API | 영향받는 화면 UI | 기존 데이터 조치 | 최종 의사결정 / 대안 |
|---|---|---|---|---|---|
| USER.phone → mobile | 주의 | GET /users, POST /signup | 마이페이지, 회원가입 폼 | 데이터 복사 후 기존 컬럼 2주간 유지 | 즉시 삭제 대신 당분간 양쪽 병행 유지 선택 |
| ENROLMENT에 pay_status 추가 | 안전 | GET /enrolments | 내 수강 목록 | 기본값 'pending' 적용 | 원안대로 진행 |
오늘 AI는 DB 설계자가 아니라 까칠한 검토자입니다. AI 답을 검증 없이 복사하면 왜 그것이 맞는지 배울 수 없습니다.
"우리 서비스 데이터베이스 설계해 줘."
맥락이 없어 뻔한 답변만 나오며, 설명할 수 없는 ERD를 얻게 됩니다.
"이 회의록에서 엔티티 후보를 추출하고, 각각 독립 테이블이 되어야 하는 이유를 근거와 함께 제시해 줘. 모호한 부분은 모호하다고 밝혀줘."
모두 체크했나요? 그렇다면 Day 4(API 설계) 준비가 완료되었습니다.
| 용어 | 쉬운 설명 | 중요한 이유 |
|---|---|---|
| Entity (엔티티) | 독립적으로 수량을 세는 핵심 데이터 개체 (테이블 1개) | 잘못 정의하면 테이블이 너무 많아지거나 부족해짐 |
| Attribute (속성) | 엔티티의 세부 특성 (컬럼 1개) | 엔티티인가 속성인가 구분하는 것이 데이터 설계의 핵심 |
| Schema (스키마) | 테이블 구조 청사진 (데이터의 헌법) | 스키마를 바꾸면 상위 모든 시스템이 영향받음 |
| Cardinality (수량성) | 관계에서 몇 대 몇인지 나타내는 수량 비율 | 1:N 관계를 반대로 맺으면 화면 조회가 불가능해짐 |
| Primary Key (PK, 주키) | 각 행을 식별하는 고유 번호 | 중복 데이터 여부를 판가름하는 기준 |
| Foreign Key (FK, 외래키) | 다른 테이블을 가리키는 참조 키 | 테이블과 테이블 사이를 연결해 주는 고리 |
| Referential Integrity (참조 무결성) | 참조하는 대상이 실제 존재해야 한다는 규칙 | 유령 데이터 및 고아 데이터 발생 방지 |
| Normalization (정규화) | 각 사실을 단 한 곳에만 기록하도록 분리하는 과정 | 데이터 간 모순과 불일치 현상 방지 |
| Anomaly (이상 현상) | 정규화하지 않아 발생하는 3가지 오류(삽입/수정/삭제) | 정규화를 수행하는 근본적인 이유 |
| Junction Table (연결 테이블) | N:M 관계를 풀기 위해 중간에 생성하는 테이블 | 누락할 경우 N:M 관계 표현 불가능 |
| Migration (마이그레이션) | 기존 저장 데이터를 새 구조로 이전하는 작업 | 스키마 변경 시 발생하는 실질적 작업 비용 |
| Mermaid | 텍스트로 다이어그램을 그리는 툴 | ERD를 코드처럼 버전 관리 가능하게 함 |
ACE AI 스타트업 부트캠프 · Day 3 보충 가이드 — 본 자료는 정규 교육과정(Day 3 AI 강의실)을 보완하는 수강생용 참고 교안입니다.
막혔을 때는 ① 본 가이드의 해당 섹션 확인 → ② 5가지 프롬프트로 Codex AI에 질문 → ③ 튜터 및 강사에게 질문 순서로 해결하세요. 동일한 문제로 20분 이상 고민하지 마세요.