기본부터 고급까지, 25개 스텝으로 MySQL 8을 처음부터 끝까지 익힙니다. 모든 예제는 실제로 돌아가는 MySQL 8.0에서 검증했고, 교재의 결과는 여러분 화면의 결과와 정확히 일치합니다.
문제가 생기면 언제든 ./install.sh를 다시 실행하세요. 완전한 초기 상태로 돌아갑니다.
그래도 안 되면 docker compose down -v && docker compose up -d.
mysql 클라이언트가 없다면:
brew install mysql-client(macOS) 컨테이너 안에서 써도 됩니다:docker exec -it learn-mysql8 mysql -ulearner -plearn1234 shop
SQL을 한 줄도 못 써도 됩니다. 여기서 시작합니다.
| Step | 주제 | 핵심 내용 |
|---|---|---|
| 01 | 환경 구축과 첫 접속 | Docker, mysql CLI, sql_mode, 시스템 변수 |
| 02 | 테이블과 데이터 타입 | CREATE/ALTER, DECIMAL vs FLOAT, DATETIME vs TIMESTAMP |
| 03 | 예제 DB 구축과 탐색 | shop 스키마, ER 파악법, 정합성 검증 |
| 04 | SELECT 기본 | SELECT/FROM/WHERE/ORDER BY/LIMIT, DISTINCT, 별칭 |
| 05 | 연산자와 조건 | BETWEEN/IN/LIKE/REGEXP, NULL 3값 논리, 페이징 |
| 06 | 집계와 GROUP BY | COUNT/SUM/AVG, HAVING, ONLY_FULL_GROUP_BY, ROLLUP |
| 07 | JOIN | INNER/LEFT/CROSS/SELF, ON vs WHERE 함정, 안티 조인 |
여기부터가 진짜 SQL입니다.
| Step | 주제 | 핵심 내용 |
|---|---|---|
| 08 | 서브쿼리 | 스칼라/파생테이블, IN vs EXISTS, NOT IN + NULL 함정 |
| 09 | CTE와 재귀 쿼리 | WITH, 재귀 CTE(조직도 전개, 날짜 채우기) |
| 10 | 집합 연산 | UNION/UNION ALL, INTERSECT/EXCEPT(8.0.31+) |
| 11 | 데이터 변경 | INSERT/UPDATE/DELETE, UPSERT, REPLACE의 함정 |
| 12 | 내장 함수 | 문자열/숫자/날짜/조건/형변환, 함수가 인덱스를 죽이는 문제 |
| 13 | 제약조건과 정규화 | PK/UNIQUE/CHECK/FK, ON DELETE 옵션, 1NF~3NF와 반정규화 |
| 14 | 뷰와 생성 컬럼 | VIEW, 갱신 가능한 뷰, VIRTUAL vs STORED, 함수 기반 인덱스 |
이 코스의 심장부입니다. 100만 행 테이블로 직접 측정합니다.
| Step | 주제 | 핵심 내용 |
|---|---|---|
| 15 | 인덱스 | B+Tree, 클러스터드 인덱스, 복합 인덱스 컬럼 순서, 커버링 인덱스 |
| 16 | EXPLAIN과 옵티마이저 | 실행계획 완전 해독, EXPLAIN ANALYZE, 힌트, 히스토그램 |
| 17 | 윈도우 함수 | ROW_NUMBER/RANK, LAG/LEAD, 프레임 절, 누적합·이동평균 |
| Step | 주제 | 핵심 내용 |
|---|---|---|
| 18 | JSON | JSON_EXTRACT, ->>, JSON_TABLE, JSON 인덱싱 |
| 19 | 트랜잭션과 락 | ACID, 격리 수준 4단계 재현, MVCC, 갭 락, 데드락 분석 |
| 20 | 저장 프로그램 | 프로시저/함수/커서/트리거/이벤트 |
| 21 | 파티셔닝 | RANGE/LIST/HASH, 파티션 프루닝, DROP PARTITION으로 즉시 삭제 |
| Step | 주제 | 핵심 내용 |
|---|---|---|
| 22 | 계정과 보안 | GRANT/REVOKE, ROLE(8.0), 최소 권한, 비밀번호 정책 |
| 23 | 백업과 복제 | mysqldump, PITR, binlog, GTID, 복제 2노드 실제 구성 |
| 24 | 모니터링과 튜닝 | 슬로우 쿼리, performance_schema, sys, 트러블슈팅 플레이북 |
| 25 | 종합 실습 | 매출 리포트, 코호트/RFM 분석, 느린 쿼리 튜닝, 스키마 설계 |
권장 학습 방법
index.md를 읽으며 직접 타이핑해서 실행합니다. 복붙하지 마세요.exercise.sql을 풀고 solution.sql로 채점합니다.shop가상의 온라인 쇼핑몰입니다.
| 테이블 | 행 수 | 비고 |
|---|---|---|
categories | 17 | 자기참조 계층 |
customers | 30 | 등급/도시/포인트. 전화번호 NULL 3명 |
products | 40 | attrs JSON 컬럼. NULL 2개 |
orders | 600 | 2024-01-02 ~ 2025-12-30 |
order_items | 1,200 | 주문당 1~3개 |
payments | 540 | PENDING 주문 60건엔 결제 없음 |
reviews | 80 | 후기 없는 상품 24개 |
employees | 18 | 자기참조 조직도 |
tally | 10,000 | 숫자 1~10000 (데이터 생성 보조) |
access_logs | 1,000,000 | 인덱스 없음 — Step 15에서 직접 붙입니다 |
시드 스크립트는 RAND()를 쓰지 않고 나머지 연산(%) 으로 값을 만듭니다. 그래서 누가 몇 번을 실행하든 완전히 동일한 데이터가 나오고, 교재의 모든 예제 결과가 여러분 화면과 일치합니다. 결과가 다르면 바로 뭔가 잘못됐다는 뜻입니다.
NULL, 빈 관계, 편향된 분포 등 학습에 필요한 함정을 의도적으로 심어 두었습니다. 각 스텝에서 재료로 씁니다.
customers, orders, products …)은 읽기만 하세요.s11_, s13_ 같은 접두사가 붙은 사본 테이블에서 진행합니다. 각 스텝 교재에 안내가 있습니다.틀린 채로 돌아가는 SQL을 잡는 데 집중했습니다. 문법 에러는 금방 고칠 수 있지만, 에러 없이 조용히 잘못된 답을 내는 쿼리가 진짜 위험합니다. 예를 들면:
NOT IN (서브쿼리)에 NULL이 하나 섞이면 결과가 통째로 사라집니다 (Step 08)COUNT(*)를 세면 고객 수가 아니라 주문 수가 나옵니다 (Step 03, 07)LEFT JOIN의 조건을 WHERE에 쓰면 INNER JOIN이 되어버립니다 (Step 07)FLOAT로 저장하면 0.1 + 0.2 ≠ 0.3이 되어 정산이 어긋납니다 (Step 02)LAST_VALUE()는 기본 프레임 때문에 마지막 값을 주지 않습니다 (Step 17)각 스텝의 ⚠️ 함정 블록을 특히 눈여겨 보세요.
| 항목 | 값 |
|---|---|
| MySQL | 8.0 (검증: 8.0.46) |
| 접속 | 127.0.0.1:3307 |
| 계정 | learner / learn1234 (관리용: root / root1234) |
| DB | shop |
| 문자셋 | utf8mb4 / utf8mb4_0900_ai_ci |
| 타임존 | Asia/Seoul (+09:00) |
| 설정 | docker/conf/my.cnf — 슬로우 쿼리 로그 ON, 엄격 모드 유지 |
학습용
learner계정에는 편의를 위해 권한을 넉넉히 주었습니다. 운영에서는 절대 이러면 안 됩니다. 올바른 권한 설계는 Step 22에서 배웁니다.