🗄️ BONUS CONTENT
DB 완강 요약 워크시트
강의에서 배운 핵심 내용을 한눈에. DBeaver 옆에 띄워놓고 바로 참고하세요!
✏️
CRUD 기본
생성 · 조회 · 수정 · 삭제1 데이터베이스 조작
| 하고 싶은 것 | SQL | 예시 |
|---|---|---|
| DB 목록 보기 | SHOW databases; | |
| DB 만들기 | CREATE DATABASE 이름; | CREATE DATABASE school; |
| DB 선택하기 | USE 이름; | USE school; |
| DB 삭제하기 | DROP DATABASE 이름; | DROP DATABASE school; |
2 테이블 조작
| 하고 싶은 것 | SQL | 예시 |
|---|---|---|
| 테이블 목록 보기 | SHOW tables; | |
| 테이블 만들기 | CREATE TABLE 이름 (...); | 아래 참고 👇 |
| 칼럼 추가 | ALTER TABLE 이름 ADD 칼럼 타입; | ALTER TABLE student ADD email VARCHAR(50); |
| 칼럼 삭제 | ALTER TABLE 이름 DROP 칼럼; | ALTER TABLE student DROP email; |
| 칼럼 수정 | ALTER TABLE 이름 MODIFY COLUMN ...; | ALTER TABLE student MODIFY name VARCHAR(30) NOT NULL; |
| 테이블 삭제 | DROP TABLE 이름; | DROP TABLE student; |
SQL — 테이블 생성 예시
CREATE TABLE student ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30) NOT NULL, age INT NOT NULL, class INT, height FLOAT );
3 CRUD 4종 세트
| 작업 | SQL | 예시 |
|---|---|---|
| C 생성 | INSERT INTO 테이블(칼럼) VALUES(값); | INSERT INTO student(name, age) VALUES("딩코", 17); |
| R 조회 | SELECT 칼럼 FROM 테이블 [WHERE]; | SELECT * FROM student WHERE age = 17; |
| U 수정 | UPDATE 테이블 SET 칼럼=값 [WHERE]; | UPDATE student SET age = 18 WHERE name = '딩코'; |
| D 삭제 | DELETE FROM 테이블 [WHERE]; | DELETE FROM student WHERE name = '딩코'; |
🚨
UPDATE, DELETE에서 WHERE를 빼먹으면 전체 레코드가 변경/삭제됩니다!
실무에서 가장 무서운 실수. 항상 WHERE를 먼저 확인하세요.
실무에서 가장 무서운 실수. 항상 WHERE를 먼저 확인하세요.
🔍
SELECT 심화
다양하게 데이터 뽑기| 하고 싶은 것 | SQL | 예시 |
|---|---|---|
| 중복 제거 | SELECT DISTINCT 칼럼 FROM 테이블; | SELECT DISTINCT name FROM student; |
| 개수 세기 | SELECT COUNT(*) FROM 테이블; | SELECT COUNT(*) FROM student; |
| 최솟값 / 최댓값 | MIN(칼럼), MAX(칼럼) | SELECT MAX(height) FROM student; |
| 합계 / 평균 | SUM(칼럼), AVG(칼럼) | SELECT AVG(height) FROM student; |
| 그룹으로 묶기 | GROUP BY 칼럼 | SELECT class, AVG(height) FROM student GROUP BY class; |
| 그룹 조건 | HAVING 조건 | HAVING AVG(height) > 175 |
| 정렬 | ORDER BY 칼럼 DESC/ASC | ORDER BY height DESC |
| 개수 제한 | LIMIT 숫자 | LIMIT 3 |
| 별칭 | AS 별칭 | SELECT AVG(height) AS avg_height |
💡
WHERE vs HAVING — WHERE는 그룹화 전에 필터링, HAVING은 그룹화 후에 필터링! 면접 단골 질문입니다.
SQL 실행 순서
작성 순서와 다릅니다! DB가 내부적으로 처리하는 순서:
FROM→
ON→
JOIN→
WHERE→
GROUP BY→
HAVING→
SELECT→
DISTINCT→
ORDER BY→
LIMIT
서브쿼리
SQL — WHERE절 서브쿼리
-- "수학" 수업을 듣는 학생의 id 찾기 SELECT student.id FROM student INNER JOIN student_class ON student.id = student_class.student_id WHERE student_class.class_id = ( SELECT id FROM class WHERE name = "수학" );
SQL — FROM절 서브쿼리 (별칭 필수!)
SELECT AVG(avg_height) FROM ( SELECT class, AVG(height) AS avg_height FROM student GROUP BY class ) AS avg_height_per_class;
🔗
JOIN
테이블 합치기🎯
INNER JOIN
양쪽 테이블에 모두 있는 데이터만 가져와!
"정보가 다 채워진 것만 보여줘"
"정보가 다 채워진 것만 보여줘"
⬅️
LEFT JOIN
왼쪽 테이블은 전부 + 오른쪽은 있으면 붙여!
"없어도 일단 전부 보여줘"
"없어도 일단 전부 보여줘"
➡️
RIGHT JOIN
LEFT JOIN의 반대.
실무에서는 거의 안 씀
실무에서는 거의 안 씀
SQL — JOIN 기본 문법
-- class와 class_info를 합쳐서 조회 SELECT * FROM class INNER JOIN class_info ON class.id = class_info.class_id;
💰
트랜잭션
메이플 거래창은 왜 안전할까?SQL — 트랜잭션 기본 흐름
SET AUTOCOMMIT=0; -- 자동커밋 끄기 START TRANSACTION; -- 트랜잭션 시작 UPDATE student SET name = "서빈2" WHERE id = 8; DELETE FROM student WHERE id = 9; COMMIT; -- ✅ 확정! DB에 반영 -- 또는 ROLLBACK; -- ⏪ 되돌려! 이전 상태로 복구
⚠️
CREATE, ALTER, DROP은 ROLLBACK으로 되돌릴 수 없습니다! 테이블 구조 변경은 신중하게.📚
인덱스
두꺼운 책의 책갈피 🔖| 하고 싶은 것 | SQL |
|---|---|
| 인덱스 만들기 | CREATE INDEX 인덱스이름 ON 테이블(칼럼); |
| 복합 인덱스 만들기 | CREATE INDEX 인덱스이름 ON 테이블(칼럼1, 칼럼2); |
| 인덱스 삭제 | DROP INDEX 인덱스이름 ON 테이블; |
| 실행계획 확인 | EXPLAIN SELECT * FROM 테이블 WHERE 조건; |
인덱스 언제 걸고 / 안 걸고?
✅ 걸면 좋은 경우
• SELECT가 자주 일어나는 칼럼
• WHERE, JOIN, ORDER BY에 자주 쓰이는 칼럼
• 카디널리티가 높은 칼럼 (값이 다양한 것)
• WHERE, JOIN, ORDER BY에 자주 쓰이는 칼럼
• 카디널리티가 높은 칼럼 (값이 다양한 것)
❌ 안 걸어야 할 경우
• INSERT/UPDATE/DELETE가 매우 빈번한 테이블
• 데이터 수가 적은 테이블
• 카디널리티가 낮은 칼럼 (성별처럼 2~3개뿐)
• 데이터 수가 적은 테이블
• 카디널리티가 낮은 칼럼 (성별처럼 2~3개뿐)
복합 인덱스 순서
카디널리티가 높은 칼럼을 앞에!
-- ✅ category 종류가 더 다양 → 앞에! CREATE INDEX idx ON book (category, is_adult); -- ❌ is_adult는 true/false 2개뿐 → 분류 효과 낮음 CREATE INDEX idx ON book (is_adult, category);
EXPLAIN으로 풀스캔 확인하기
| type 값 | 의미 | 판정 |
|---|---|---|
ALL | 테이블 전체를 처음부터 끝까지 뒤짐 | 🚨 풀스캔 |
index | 인덱스 전체를 스캔 | ⚠️ 주의 |
range | 인덱스 범위 검색 | ✅ 양호 |
ref | 인덱스로 매칭되는 행 탐색 | ✅ 좋음 |
eq_ref | PK/UNIQUE로 정확히 1건 매칭 | ✅ 매우 좋음 |
const | PK로 딱 1건 찾음 | ✅ 최고 |
📖
핵심 용어집
강의 속 비유와 함께| 용어 | 한줄 설명 | 강의 속 비유 |
|---|---|---|
| 데이터베이스 | 정형화된 데이터들의 묶음 | 엑셀 파일 모음 📁 |
| DBMS | DB를 관리하는 시스템 (MySQL 등) | 엑셀 프로그램 자체 |
| 테이블 | 칼럼과 타입이 정의된 데이터 명세서 | "학생", "선생님", "수업" |
| 레코드 | 테이블에 들어가는 실제 데이터 한 줄 | 딩코, 12살, 1반, 156cm |
| 필드 | 테이블의 각 열 (= 칼럼 = 속성) | 이름, 나이, 반, 키 |
| 기본 키 (PK) | 레코드를 고유하게 식별. 중복·NULL 불가 | 학생 번호 (1번 딩코, 2번 딩코) |
| 외래 키 (FK) | 다른 테이블의 PK를 가리키는 칼럼 | 수업의 "담당 선생님 번호" |
| 스키마 | DB의 구조 + 제약조건의 전체 설계도 | 학교의 전체 운영 규칙 |
| NULL | 아직 정해지지 않은 빈 값 | 아직 반 배정 안 된 학생 |
| 풀스캔 | 테이블 전체를 처음부터 끝까지 뒤지는 것 | 두꺼운 책 1페이지부터 끝까지 📚 |
| 인덱스 | 자주 찾는 값의 위치를 미리 저장 | 두꺼운 책의 책갈피 🔖 |
| 카디널리티 | 칼럼 값의 고유한 종류 수 | "성별"보다 "카테고리"가 높음 |
| 트랜잭션 | 하나의 작업 단위로 묶인 SQL 묶음 | 메이플 거래: 동시에 교환 💰 |
| COMMIT | 트랜잭션 결과를 DB에 확정 반영 | 확정 도장 쾅! 🔨 |
| ROLLBACK | 트랜잭션 결과를 되돌림 | Ctrl + Z ⏪ |
| 갱신 이상 | 중복 데이터 일부만 수정 → 불일치 | 조정식 → 조증식 일부만 변경 |
🔗
연관관계 한눈에 보기
💑
1:1 관계
하나의 레코드가 상대방 테이블의 딱 하나와 연결
예: 수업 ↔ 수업 상세정보
FK 위치: 어느 쪽이든 OK
예: 수업 ↔ 수업 상세정보
FK 위치: 어느 쪽이든 OK
👨👦👦
1:N 관계
하나의 레코드가 상대방의 여러 개와 연결
예: 선생님(1) → 수업(N)
FK 위치: N쪽 테이블에!
예: 선생님(1) → 수업(N)
FK 위치: N쪽 테이블에!
👨👨👧👧
M:N 관계
양쪽 모두 상대방의 여러 개와 연결
예: 학생(M) ↔ 수업(N)
→ 연결 테이블 별도 생성!
예: 학생(M) ↔ 수업(N)
→ 연결 테이블 별도 생성!
SQL — 1:N 관계 (FK를 N쪽에)
CREATE TABLE class ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30) NOT NULL, teacher_id INT NOT NULL, FOREIGN KEY (teacher_id) REFERENCES teacher(id) );
SQL — M:N 관계 (연결 테이블)
CREATE TABLE student_class ( student_id INT NOT NULL, class_id INT NOT NULL, FOREIGN KEY (student_id) REFERENCES student(id), FOREIGN KEY (class_id) REFERENCES class(id) );
🛡️
ACID 성질
트랜잭션의 4가지 안전 보장A 원자성
전부 반영되거나, 전혀 반영 안 되거나.
All or Nothing
🎮 메이플 거래: 돈만 빠지고 아이템 안 오는 일은 없다
All or Nothing
🎮 메이플 거래: 돈만 빠지고 아이템 안 오는 일은 없다
C 일관성
작업 전후로 데이터 규칙이 항상 지켜짐
🍛 배민: 재고보다 더 많이 주문되면 안 된다
🍛 배민: 재고보다 더 많이 주문되면 안 된다
I 격리성
동시 실행되는 트랜잭션끼리 서로 간섭 불가
🏧 내 거래 끝나기 전에 다른 사람이 끼어들 수 없다
🏧 내 거래 끝나기 전에 다른 사람이 끼어들 수 없다
D 지속성
커밋된 결과는 영구적으로 보존
💾 DB가 꺼져도 데이터는 살아있다
💾 DB가 꺼져도 데이터는 살아있다
🏷️
데이터 타입 요약
자주 쓰는 것만!| 저장할 데이터 | 추천 타입 | 예시 |
|---|---|---|
| 정수 (나이, 번호) | INT | age INT |
| 실수 (키, 가격) | FLOAT / DOUBLE | height FLOAT |
| 짧은 문자열 (이름) | VARCHAR(길이) | name VARCHAR(30) |
| 긴 문자열 (설명) | TEXT | description TEXT |
| 정해진 값만 (성별) | ENUM | gender ENUM('M','F') |
| 날짜 | DATE | birth_date DATE |
| 날짜 + 시간 | DATETIME | created_at DATETIME |
| 참 / 거짓 | BOOLEAN | is_graduated BOOLEAN |
🔒
제약조건 요약
| 제약조건 | 효과 | 예시 |
|---|---|---|
NOT NULL | 빈 값(NULL) 저장 불가 | name VARCHAR(30) NOT NULL |
UNIQUE | 중복 값 저장 불가 (NULL은 허용) | email VARCHAR(50) UNIQUE |
PRIMARY KEY | NOT NULL + UNIQUE. 테이블당 1개 | id INT PRIMARY KEY |
FOREIGN KEY | 다른 테이블의 PK를 참조 | FOREIGN KEY (teacher_id) REFERENCES teacher(id) |
DEFAULT | 값 안 넣으면 기본값 자동 저장 | is_graduated BOOLEAN DEFAULT FALSE |
AUTO_INCREMENT | 레코드 생성 시 숫자 자동 증가 | id INT AUTO_INCREMENT PRIMARY KEY |
🤖
AI 검증 체크리스트
실행 전 5초 확인!👑
AI가 쿼리를 짜줬다면, 복사해서 바로 실행하지 마세요!
아래 5가지만 빠르게 확인하면 대참사를 막을 수 있습니다.
아래 5가지만 빠르게 확인하면 대참사를 막을 수 있습니다.
- JOIN 종류가 맞는가? — 교집합이면 INNER, 한쪽 전부면 LEFT
- WHERE 조건이 있는가? — UPDATE/DELETE에 WHERE 없으면 🚨 전체 변경
- LIMIT이 있는가? — 데이터 많은 테이블에서 SELECT * 하면 서버 과부하
- 테이블 관계가 맞는가? — M:N인데 FK 하나만 있으면 설계 오류
- EXPLAIN 떠봤는가? — type이 ALL이면 인덱스 필요
AI한테 더 똑똑하게 질문하는 법
❌ 나쁜 프롬프트
"학생 데이터 조회하는 쿼리 짜줘"✅ 좋은 프롬프트
"student 테이블에서 class가 1이고 height가 170 이상인
학생의 name과 height를 키 내림차순으로 상위 10명만
조회하는 쿼리 짜줘.
인덱스는 (class, height)에 복합 인덱스가 걸려있어."🎯
핵심: 테이블 구조 + 조건 + 정렬 + 제한 + 인덱스 정보를 같이 주면 AI가 훨씬 정확한 쿼리를 짜줍니다!
여러분은 이제 AI가 짜준 쿼리를 검증하는 '사령관'입니다 🔥
이 치트시트를 옆에 두고, AI의 결과물을 평가하고 승인하는 연습을 해보세요.