TypeORM 실무 — Raw Query를 ORM으로 변환CRUD 비교전체 조회// Raw SQLconst [users] = await pool.query('SELECT * FROM users');// TypeORMconst users = await userRepository.find();단건 조회// Raw SQLconst [rows] = await pool.query('SELECT * FROM users WHERE id = ?', [id]);const user = rows[0];if (!user) throw new Error('Not found');// TypeORMconst user = await userRepository.findOne({ where: { id } });if (!user) thro..
SQL
TypeORM 기초ORM(Object-Relational Mapping) = 객체와 테이블을 연결해주는 것. SQL 대신 TypeScript 코드로 DB를 조작한다.설치 & 세팅npm install typeorm reflect-metadata mysql2tsconfig.json:{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true }}src/data-source.ts:import { DataSource } from 'typeorm';export const AppDataSource = new DataSource({ type: 'mysql', host: 'localhost', port: 33..
쿼리 최적화EXPLAIN 심화EXPLAIN SELECT u.name, COUNT(o.id) as order_countFROM users uLEFT JOIN orders o ON u.id = o.user_idWHERE u.created_at > '2026-01-01'GROUP BY u.id;| table | type | key | rows | Extra ||-------|-------|-------------|--------|-------------|| u | ALL | NULL | 100000 | Using where || o | ref | idx_user_id | 3 | Using index |u 테이블에서 type: ALL, k..
외래키 / 정규화외래키 (Foreign Key)외래키 없으면 존재하지 않는 user_id를 가진 주문을 삽입하거나, 주문이 있는 유저를 삭제해도 DB가 막지 못한다. 고아 데이터가 쌓인다.CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, product VARCHAR(100), FOREIGN KEY (user_id) REFERENCES users(id));-- 존재하지 않는 user_id 삽입 시-- ERROR 1452: Cannot add or update a child row-- 주문 있는 유저 삭제 시-- ERROR 1451: Cannot delete or update a parent rowON DELETE 옵션-- 유저 삭제 시 주문도 같이 삭..
트랜잭션 & ACID여러 쿼리를 하나의 작업 단위로 묶는 것. 중간에 실패하면 전부 없던 일로 돌린다.기본 사용법START TRANSACTION;UPDATE accounts SET balance = balance - 100000 WHERE id = 'A';UPDATE accounts SET balance = balance + 100000 WHERE id = 'B';COMMIT; -- 둘 다 성공하면 확정-- 실패하면 ROLLBACK → 둘 다 없던 일로ACIDA — Atomicity (원자성)전부 성공하거나, 전부 실패하거나. 중간 상태는 없다.C — Consistency (일관성)트랜잭션 전후로 데이터 규칙이 깨지지 않는다.(예: 잔액은 0 이상이어야 한다는 규칙이 트랜잭션 후에도 유지)I — Is..
인덱스 (Index)인덱스가 없으면 MySQL은 조건에 맞는 행을 찾기 위해 테이블 전체를 처음부터 끝까지 읽는다. 이를 풀스캔(Full Table Scan)이라 한다.B-Tree 구조인덱스는 내부적으로 B-Tree(Balanced Tree)로 저장된다. [M] ← 루트 / \ [D,H] [R,V] ← 중간 노드 / | \ / | \ [A][E][J][P][S][X] ← 리프 (실제 행 위치 저장)항상 정렬된 상태 유지탐색: O(log n) → 100만 건도 약 20번 비교로 찾음=, >, , BETWEEN, LIKE 'soo%' 에 효과적..
Upsert query?- 중복되는 값이 있다면 UPDATE, 없다면 INSERT- 수정 로직 짤때 바뀐 값만 UPDATE하고, 수정하면서 새로운 값을 넣어줘야할 때는 INSERT를 해준다.- 리프레시 토큰을 예시로 들어보면 사용자의 정보가 이미 있고 refresh_token 값만 바꿔주고 싶을때 Upsert를 사용하면 된다.INSERT INTO refresh_token (user_id, refresh_token)VALUES (#{userId}, #{refreshToken}) ON DUPLICATE KEYUPDATE refresh_token = #{refreshToken}
Mysql 비밀번호 관련 정책 에러 초기 비밀번호를 찾고, 새로 설정해주는 과정에서 발생된 에러다. 이유는 내가 바꾸려는 비밀번호가 정책에 맞지 않았기 때문(길이, 대문자, 소문자 포함 등) 정책 기준을 낮춰 진행하려 했으나 초기 비밀번호 설정 후에 진행하라고 해서 초기 비밀번호를 새로운 비밀번호로 설정해준 후 정책 기준을 내려 내가 원하는 비밀번호로 바꾸는 과정을 거쳤다. # 초기 비번 설정 ALTER USER 'root'@'localhost' IDENTIFIED BY '초기에 설정된 비밀번호'; # 정책 확인 SHOW VARIABLES LIKE 'validate_password%'; # 정책 변경 SET GLOBAL validate_password.policy=LOW; # 비번 다시 변경 ALTER ..
초기 비밀번호 찾기 mysql 설치 후 초기 비밀번호는 랜덤으로 지정된다. sudo grep 'temporary password' /var/log/mysqld.log 나는 두번째꺼로 했을때 접속이 됐다. 비밀번호 변경 Mysql 접속 후 ALTER문 활용해서 변경해주면 된다. alter user 'root'@'localhost' identified by '새로운 비밀번호'
SQL - JOIN 정리 예시 테이블 Table: employees +--------+--------------+------------+---------+ | emp_id | emp_name | hire_date | dept_id | +--------+--------------+------------+---------+ | 1 | Ethan Hunt | 2001-05-01 | 4 | | 2 | Tony Montana | 2002-07-15 | 1 | | 3 | Sarah Connor | 2005-10-18 | 5 | | 4 | Rick Deckard | 2007-01-03 | 3 | | 5 | Martin Blank | 2008-06-24 | NULL | +--------+--------------+--..