본문으로 건너뛰기

💾 데이터베이스란?

📖 정의

데이터베이스(Database, DB)는 체계적으로 구조화된 데이터의 집합입니다. DBMS(Database Management System, 데이터베이스 관리 시스템)는 데이터베이스를 생성하고, 관리하고, 접근하는 소프트웨어입니다. 데이터베이스는 데이터를 효율적으로 저장하고 검색할 수 있게 해주며, 여러 사용자가 동시에 안전하게 접근할 수 있습니다.

🎯 비유로 이해하기

도서관 시스템

데이터베이스를 도서관에 비유하면:

  • 데이터베이스: 전체 도서관
  • 테이블: 각 섹션 (소설, 과학, 역사 등)
  • 행(Row): 개별 책
  • 열(Column): 책의 속성 (제목, 저자, 출판연도 등)
  • 기본키(Primary Key): 도서 고유번호
  • DBMS: 사서와 관리 시스템
도서관 (데이터베이스)
├─ 소설 섹션 (테이블)
│ ├─ 책 1: 해리포터, J.K. 롤링, 1997
│ ├─ 책 2: 반지의 제왕, 톨킨, 1954
│ └─ 책 3: 어린왕자, 생텍쥐페리, 1943
├─ 과학 섹션 (테이블)
│ ├─ 책 1: 코스모스, 칼 세이건, 1980
│ └─ 책 2: 이기적 유전자, 리처드 도킨스, 1976
└─ 대출 기록 (테이블)
├─ 기록 1: 회원123, 해리포터, 2024-01-15
└─ 기록 2: 회원456, 코스모스, 2024-01-20

⚙️ 작동 원리

1. 데이터베이스 구조

데이터베이스 (Database)
└─ 테이블 (Table)
├─ 행 (Row/Record) - 개별 데이터 항목
│ └─ 예: 한 명의 사용자 정보
└─ 열 (Column/Field) - 데이터 속성
└─ 예: 이름, 이메일, 나이

2. 관계형 데이터베이스 예시

-- 사용자 테이블
users 테이블
┌────┬─────────┬──────────────────┬─────┐
│ id │ name │ email │ age │
├────┼─────────┼──────────────────┼─────┤
1 │ 김철수 │ chulsoo@mail.com25
2 │ 이영희 │ younghee@mail.com30
3 │ 박민수 │ minsoo@mail.com28
└────┴─────────┴──────────────────┴─────┘

-- 주문 테이블
orders 테이블
┌────┬─────────┬─────────────┬───────┐
│ id │ user_id │ product │ price │
├────┼─────────┼─────────────┼───────┤
11 │ 노트북 │ 1500
21 │ 마우스 │ 30
32 │ 키보드 │ 80
└────┴─────────┴─────────────┴───────┘

└─ 외래키: users 테이블의 id를 참조

3. CRUD 작업

CRUD는 데이터베이스의 4가지 기본 작업입니다:

C - Create  (생성): 새 데이터 추가
R - Read (읽기): 데이터 조회
U - Update (수정): 기존 데이터 변경
D - Delete (삭제): 데이터 제거

💡 실제 예시

SQL로 CRUD 작업하기

-- CREATE (생성): 테이블 만들기
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- CREATE (생성): 데이터 추가
INSERT INTO users (name, email, age)
VALUES ('김철수', 'chulsoo@mail.com', 25);

INSERT INTO users (name, email, age)
VALUES
('이영희', 'younghee@mail.com', 30),
('박민수', 'minsoo@mail.com', 28);

-- READ (읽기): 모든 사용자 조회
SELECT * FROM users;

-- READ (읽기): 조건부 조회
SELECT name, email FROM users
WHERE age >= 28;

-- READ (읽기): 정렬하여 조회
SELECT * FROM users
ORDER BY age DESC;

-- READ (읽기): 검색
SELECT * FROM users
WHERE name LIKE '김%';

-- UPDATE (수정): 데이터 변경
UPDATE users
SET age = 26
WHERE name = '김철수';

-- UPDATE (수정): 여러 필드 수정
UPDATE users
SET email = 'new@mail.com', age = 31
WHERE id = 2;

-- DELETE (삭제): 데이터 제거
DELETE FROM users
WHERE id = 3;

-- DELETE (삭제): 조건부 삭제
DELETE FROM users
WHERE age < 20;

Node.js에서 데이터베이스 사용

const mysql = require('mysql2/promise');

// 데이터베이스 연결
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10
});

// CREATE - 사용자 추가
async function createUser(name, email, age) {
const [result] = await pool.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[name, email, age]
);
console.log('생성된 ID:', result.insertId);
return result.insertId;
}

// READ - 모든 사용자 조회
async function getAllUsers() {
const [rows] = await pool.execute('SELECT * FROM users');
return rows;
}

// READ - 특정 사용자 조회
async function getUserById(id) {
const [rows] = await pool.execute(
'SELECT * FROM users WHERE id = ?',
[id]
);
return rows[0];
}

// UPDATE - 사용자 정보 수정
async function updateUser(id, name, email, age) {
const [result] = await pool.execute(
'UPDATE users SET name = ?, email = ?, age = ? WHERE id = ?',
[name, email, age, id]
);
console.log('수정된 행:', result.affectedRows);
return result.affectedRows;
}

// DELETE - 사용자 삭제
async function deleteUser(id) {
const [result] = await pool.execute(
'DELETE FROM users WHERE id = ?',
[id]
);
console.log('삭제된 행:', result.affectedRows);
return result.affectedRows;
}

// 사용 예시
async function main() {
try {
// 생성
const userId = await createUser('김철수', 'chulsoo@mail.com', 25);

// 조회
const users = await getAllUsers();
console.log('모든 사용자:', users);

// 특정 사용자 조회
const user = await getUserById(userId);
console.log('특정 사용자:', user);

// 수정
await updateUser(userId, '김철수', 'new@mail.com', 26);

// 삭제
await deleteUser(userId);
} catch (error) {
console.error('에러:', error);
}
}

main();

ORM 사용 (Sequelize)

const { Sequelize, DataTypes } = require('sequelize');

// 데이터베이스 연결
const sequelize = new Sequelize('myapp', 'root', 'password', {
host: 'localhost',
dialect: 'mysql'
});

// 모델 정의 (테이블 구조)
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
age: {
type: DataTypes.INTEGER
}
});

// CRUD 작업 (SQL 없이 JavaScript로!)
async function ormExample() {
// CREATE - 생성
const user = await User.create({
name: '김철수',
email: 'chulsoo@mail.com',
age: 25
});
console.log('생성:', user.toJSON());

// READ - 조회
const allUsers = await User.findAll();
console.log('모든 사용자:', allUsers);

// READ - 조건 조회
const youngUsers = await User.findAll({
where: { age: { [Sequelize.Op.gte]: 20 } },
order: [['age', 'DESC']]
});

// READ - 한 개 조회
const oneUser = await User.findOne({
where: { email: 'chulsoo@mail.com' }
});

// UPDATE - 수정
await User.update(
{ age: 26 },
{ where: { name: '김철수' } }
);

// DELETE - 삭제
await User.destroy({
where: { id: 1 }
});
}

관계 설정 (JOIN)

// 사용자와 주문의 관계 설정
const User = sequelize.define('User', {
name: DataTypes.STRING,
email: DataTypes.STRING
});

const Order = sequelize.define('Order', {
product: DataTypes.STRING,
price: DataTypes.DECIMAL(10, 2)
});

// 관계 정의: 한 사용자는 여러 주문 가능
User.hasMany(Order);
Order.belongsTo(User);

// JOIN 쿼리
async function getUserWithOrders(userId) {
const userWithOrders = await User.findOne({
where: { id: userId },
include: Order // JOIN
});

console.log(userWithOrders.toJSON());
// {
// id: 1,
// name: '김철수',
// email: 'chulsoo@mail.com',
// Orders: [
// { product: '노트북', price: 1500 },
// { product: '마우스', price: 30 }
// ]
// }
}

🤔 자주 묻는 질문

Q1. 데이터베이스를 사용하는 이유는?

A: 파일 시스템보다 많은 장점이 있습니다:

❌ 파일 시스템 (예: users.txt)
├─ 데이터 중복 가능
├─ 동시 접근 문제
├─ 백업/복구 어려움
├─ 보안 취약
└─ 검색 느림

✅ 데이터베이스
├─ 데이터 무결성 보장
├─ 동시성 제어 (여러 사용자)
├─ 백업/복구 자동화
├─ 접근 권한 관리
├─ 빠른 검색 (인덱스)
└─ 트랜잭션 지원

Q2. 어떤 데이터베이스를 선택해야 하나요?

A: 프로젝트 요구사항에 따라 다릅니다:

// 관계형 데이터베이스 (SQL)
MySQL / PostgreSQL / SQLite
├─ 장점: 정확한 데이터 구조, 트랜잭션
├─ 단점: 유연성 낮음, 확장성 제한
└─ 적합: 금융, 전자상거래, 사용자 관리

// 비관계형 데이터베이스 (NoSQL)
MongoDB / Redis / Cassandra
├─ 장점: 유연한 스키마, 수평 확장
├─ 단점: 복잡한 관계 처리 어려움
└─ 적합: 소셜미디어, 실시간 분석, 캐싱

Q3. 인덱스(Index)란?

A: 데이터 검색 속도를 높이는 자료구조입니다:

-- 인덱스 없이 검색
SELECT * FROM users WHERE email = 'test@mail.com';
-- → 100만 개 행을 모두 확인 (느림)

-- 인덱스 생성
CREATE INDEX idx_email ON users(email);

-- 인덱스로 검색
SELECT * FROM users WHERE email = 'test@mail.com';
-- → 인덱스로 바로 찾기 (빠름!)

-- 단점: 데이터 삽입/수정 시 인덱스도 갱신 (쓰기 느려짐)

비유: 책의 목차나 색인처럼, 원하는 내용을 빠르게 찾을 수 있게 해줍니다.

Q4. 트랜잭션(Transaction)이란?

A: 여러 작업을 하나의 단위로 묶어 처리하는 것입니다:

// 은행 송금 예시
async function transferMoney(fromId, toId, amount) {
const connection = await pool.getConnection();

try {
// 트랜잭션 시작
await connection.beginTransaction();

// 1. 보내는 사람 잔액 감소
await connection.execute(
'UPDATE accounts SET balance = balance - ? WHERE id = ?',
[amount, fromId]
);

// 2. 받는 사람 잔액 증가
await connection.execute(
'UPDATE accounts SET balance = balance + ? WHERE id = ?',
[amount, toId]
);

// 모두 성공 → 확정
await connection.commit();
console.log('송금 완료!');

} catch (error) {
// 에러 발생 → 모두 취소
await connection.rollback();
console.log('송금 실패, 롤백됨');
throw error;
} finally {
connection.release();
}
}

// ACID 원칙
// Atomicity (원자성): 전부 실행 or 전부 취소
// Consistency (일관성): 규칙 위반 안 됨
// Isolation (독립성): 다른 트랜잭션과 독립
// Durability (영속성): 완료 후 영구 저장

Q5. SQL Injection이란?

A: 악의적인 SQL 코드를 주입하는 공격입니다:

// ❌ 위험한 코드 (SQL Injection 취약)
const email = req.body.email; // "admin@mail.com' OR '1'='1"
const query = `SELECT * FROM users WHERE email = '${email}'`;
// 실행: SELECT * FROM users WHERE email = 'admin@mail.com' OR '1'='1'
// → 모든 사용자 정보 유출!

// ✅ 안전한 코드 (Prepared Statement)
const [rows] = await pool.execute(
'SELECT * FROM users WHERE email = ?',
[email] // 자동으로 이스케이프됨
);

// ORM 사용 (자동 방어)
const user = await User.findOne({
where: { email: email } // 안전함
});

🎓 다음 단계

데이터베이스를 이해했다면, 다음을 학습해보세요:

  1. SQL vs NoSQL - 데이터베이스 선택 가이드
  2. Node.js란? - 백엔드 개발
  3. API란? - 데이터베이스와 프론트엔드 연결

실습해보기

# MySQL 설치 및 실행
brew install mysql # macOS
sudo apt install mysql # Linux

# 데이터베이스 접속
mysql -u root -p

# 데이터베이스 생성
CREATE DATABASE myapp;
USE myapp;

# 테이블 생성 및 데이터 추가
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
email VARCHAR(100)
);

INSERT INTO users (name, email) VALUES ('김철수', 'test@mail.com');
SELECT * FROM users;

🎬 마무리

데이터베이스는 모든 애플리케이션의 핵심입니다:

  • 데이터베이스: 구조화된 데이터 집합
  • CRUD: 생성, 조회, 수정, 삭제 - 기본 작업
  • 테이블: 데이터를 행과 열로 구조화
  • 관계: 테이블 간의 연결 (JOIN)
  • 트랜잭션: 안전한 데이터 처리

데이터베이스를 잘 이해하면 안정적이고 확장 가능한 애플리케이션을 만들 수 있습니다! 💾✨