1. 오늘 한 일 (What I Did)
1-1. Docker로 MySQL 설치하고 실행하기
1-1-1. 명령어로 MySQL 실행
docker run --name mysql -e MYSQL_ROOT_PASSWORD=1234 -d -p 3306:3306 mysql:latest
이 명령어 하나로 MySQL이 내 컴퓨터에 설치되고 실행됐다!
- --name mysql: 컨테이너 이름을 'mysql'로 지정
- -e MYSQL_ROOT_PASSWORD=1234: 관리자 비밀번호를 1234로 설정
- -p 3306:3306: MySQL 기본 포트 연결
- -d: 백그라운드에서 실행
1-1-2. Docker Desktop GUI와 터미널 이름이 달라서 헷갈렸던 문제
- Docker Desktop에서는: practice-hanbi로 보임
- 터미널에서는: mysql로 보임
- 해결: docker ps 명령어로 확인한 이름이 진짜! → mysql 사용/ 문제는 없었으나 정리하고 싶은 강박으로 컨테이너 삭제하고 다시 마듬
1-1-3. MySQL에 접속하는 과정
# 1단계: Docker 컨테이너 안으로 들어가기
docker exec -it mysql bash
# 2단계: 이제 MySQL 접속하기
mysql -uroot -p
# 비밀번호: 1234
처음엔 맥 터미널에서 바로 mysql 명령어를 쳤다가 "command not found" 에러를 봤다. MySQL은 Docker 컨테이너 안에 있으니까 먼저 컨테이너로 들어가야 한다는 걸 배웠다!
1-1-4. docker-compose.yml 파일 만들기
긴 Docker 명령어를 매번 치기 귀찮으면 파일로 만들 수 있다.
version: "3.8"
services:
db:
image: mysql:latest
container_name: mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 1234
TZ: Asia/Seoul
volumes:
- ./mysql:/var/lib/mysql # 데이터 저장 위치
- 파일 위치: 프로젝트 최상위 폴더 (package.json이랑 같은 위치)
- 실행 방법: docker compose up -d
1-1-5. 데이터베이스와 사용자 만들기
-- 1. 데이터베이스 만들기
CREATE DATABASE todo_list_db;
-- 2. 새 사용자 만들기
CREATE USER 'hanbi'@'%' IDENTIFIED BY '1234';
-- 'hanbi': 사용자 이름
-- '%': 어디서든 접속 가능 (localhost만 하려면 'localhost')
-- '1234': 비밀번호
-- 3. 권한 주기
GRANT ALL PRIVILEGES ON todo_list_db.* TO 'hanbi'@'%';
-- todo_list_db의 모든 권한을 hanbi에게 줌
-- 4. 권한 적용
FLUSH PRIVILEGES;
1-2. 할일 관리 앱을 위한 테이블 5개 설계
이런 구조로 설계했다.
👤 User (사용자)
└── 📁 Project (프로젝트)
└── 📋 Board (칸반 보드: To Do, In Progress, Done)
└── ✅ Task (할 일)
└── 📝 Sub_task (세부 할 일)
1-3. schema.sql 파일 작성하고 실행하기
프로젝트 폴더에 schema.sql 파일을 만들고 테이블 생성 코드를 작성했다.
실행 방법 3가지를 시도했다.
- VS Code SQLTools에서 실행 → 연결 문제로 실패
- MySQL 안에서 복사-붙여넣기 → 성공!
- 터미널에서 파일 실행 → 이것도 성공!
docker exec -i mysql mysql -uhanbi -p1234 todo_list_db < schema.sql
2. 새로 이해한 것 (What I Learned)
2-1. Docker가 뭔지 이해했다
Docker = 내 컴퓨터 안의 작은 컴퓨터
- 예전: MySQL을 내 맥에 직접 설치 → 지우기 어렵고 꼬임
- 지금: Docker 컨테이너에 설치 → 필요없으면 컨테이너만 삭제하면 깔끔!
컨테이너 vs 이미지
- 이미지 = 붕어빵 틀 (MySQL 설치 파일)
- 컨테이너 = 붕어빵 (실제로 실행 중인 MySQL)
2-2. SQL 테이블 만드는 기본 문법
CREATE TABLE 테이블이름 (
컬럼이름 데이터타입 제약조건,
컬럼이름 데이터타입 제약조건,
-- 마지막엔 콤마 없음!
);
2-3. 데이터 타입 종류와 언제 쓰는지
숫자 타입
- TINYINT: 아주 작은 숫자 (0~255) → 우선순위 같은 거
- INT: 보통 숫자 (-21억~21억) → 순서, 개수
- BIGINT: 엄청 큰 숫자 → ID값 (나중에 데이터 많아져도 OK)
문자 타입
- VARCHAR(100): 최대 100자 → 이름, 제목
- VARCHAR(255): 최대 255자 → 이메일, URL
- TEXT: 아주 긴 글 → 본문, 설명
시간 타입
- TIMESTAMP: 날짜+시간 → 언제 만들었는지, 언제 수정했는지
2-4. Primary Key와 Foreign Key 이해
Primary Key (PK) = 주민등록번호
id BIGINT AUTO_INCREMENT PRIMARY KEY
- 각 행을 구분하는 고유 번호
- 자동으로 1, 2, 3... 증가
- 절대 중복 안 됨, 비어있을 수 없음
Foreign Key (FK) = 다른 테이블 가리키는 화살표
user_id BIGINT,
FOREIGN KEY (user_id) REFERENCES user(id)
- 예: project 테이블의 user_id = 1 → user 테이블의 id = 1인 사람 것
- 없는 번호는 못 넣음 (user 테이블에 1번이 없으면 에러)
2-5. 테이블 삭제 순서가 중요한 이유!
잘못된 순서 (에러 발생)
DROP TABLE user; -- ❌ "project가 user를 참조 중이라 못 지워!"
올바른 순서 (자식부터 삭제)
DROP TABLE sub_task; -- 5층 (제일 아래)
DROP TABLE task; -- 4층
DROP TABLE board; -- 3층
DROP TABLE project; -- 2층
DROP TABLE user; -- 1층 (제일 위)
레고 탑 부수기랑 똑같다! 위에서부터 하나씩 빼야 안 무너진다.
2-6. 왜 모든 테이블에 user_id가 있을까?
이론적으로는: project만 user_id 가지고, 나머지는 project 통해서 찾으면 됨
실무에서는:
-- user_id 없으면 (느림 - JOIN 3번!)
SELECT * FROM task t
JOIN board b ON t.board_id = b.id
JOIN project p ON b.project_id = p.id
WHERE p.user_id = 1;
-- user_id 있으면 (빠름 - JOIN 없이!)
SELECT * FROM task WHERE user_id = 1;
"한비가 만든 모든 할일 보여줘" 같은 질문에 바로 답할 수 있다!
2-7. CASCADE 옵션 이해하기
ON DELETE CASCADE = 연쇄 삭제
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE
- 사용자 삭제 → 그 사람의 프로젝트도 자동 삭제
- 편하지만 위험할 수 있음
ON DELETE SET NULL = NULL로 바꾸기
FOREIGN KEY (board_id) REFERENCES board(id) ON DELETE SET NULL
- 보드 삭제 → 태스크는 남지만 board_id가 NULL이 됨
- "보드 없는 태스크"가 됨 (백로그 상태)
3. 실수했던 부분들 (What I Struggled With)
3-1. 콤마(,) 때문에 고생한 이야기
실수 1: 마지막에 콤마 넣음
-- 틀린 코드
CREATE TABLE user (
id BIGINT PRIMARY KEY,
name VARCHAR(100), -- 마지막인데 콤마 있음!
);
실수 2: 필요한 곳에 콤마 빼먹음
-- 틀린 코드
update_at TIMESTAMP -- 콤마 없음!
CONSTRAINT ... -- 에러 발생!
실수 3: CONSTRAINT 뒤에 콤마
-- 틀린 코드
CONSTRAINT user_project_fk FOREIGN KEY ..., -- 마지막인데 콤마!
);
콤마 규칙 정리
- 테이블 안에서 마지막 빼고 다 콤마!
- 닫는 괄호 ) 앞에는 절대 콤마 없음!
- 헷갈리면 마지막 줄 확인!
3-2. CONSTRAINT 이름 중복 문제
-- 에러: 같은 이름을 여러 번 사용
board 테이블: CONSTRAINT user_project_id_fk ...
task 테이블: CONSTRAINT user_project_id_fk ... -- "이미 있는 이름!"
해결: 각자 다른 이름 사용
- project 테이블: user_project_id_fk
- board 테이블: user_board_id_fk
- task 테이블: user_task_id_fk
3-4. Foreign Key 참조 실수
-- 틀린 코드 (task 테이블에서)
FOREIGN KEY (board_id) REFERENCES task(id) -- task? 아니야!
-- 맞는 코드
FOREIGN KEY (board_id) REFERENCES board(id) -- board가 맞아!
board_id는 board 테이블을 가리켜야 하는데 task를 가리키게 써서 에러!
3-5. 오타들
- oder_no → order_no (order 스펠링)
- lowlest → lowest (최하위 스펠링)
- create_at 뒤에서 줄바꿈해서 문법 에러
3-6. VS Code 연결 실패
SQLTools 연결할 때 고급 설정 건드렸다가 에러:
- Authentication Protocol: default → 그냥 비워둠
- SSL: Enabled → Disabled로 변경
교훈: 모르는 설정은 건드리지 말자!
'TIL' 카테고리의 다른 글
2025-08-10 NestJS UsersService CRUD 구현 및 DTO 작성 (2) | 2025.08.11 |
---|---|
2025-08-09 NestJS + TypeORM DB 연동 (4) | 2025.08.10 |
2025-08-03 (10) | 2025.08.03 |
2025-07-31 (5) | 2025.07.31 |
2025-07-30 (4) | 2025.07.31 |