Node.js + SQLite · Prisma ORM · MongoDB 기초
Node.js에서 SQLite를 다루는 가장 인기 있는 better-sqlite3 라이브러리로 prepare/run/get/all 메서드를 익히고, Express와 결합한 CRUD API를 만듭니다. 차세대 ORM Prisma로 schema.prisma 파일에 모델을 정의하고, 마이그레이션으로 DB 스키마를 관리하며, 자동 생성된 Client로 타입 안전한 CRUD를 작성합니다. NoSQL의 대표 MongoDB의 문서·컬렉션 개념, Atlas 무료 클러스터 생성, Mongoose로 Node에서 연결, Schema/Model 정의와 CRUD를 익힙니다.
이 강의에서 배우는 것
- 1better-sqlite3를 설치하고 DB를 연다
- 2prepare로 쿼리를 컴파일한다
- 3run/get/all 메서드를 적절히 사용한다
- 4위치/이름 파라미터 바인딩으로 SQL 인젝션을 방지한다
- 5ORM의 개념과 장단점을 이해한다
- 6Prisma의 동작 흐름(schema → migrate → Client)을 안다
- 7schema.prisma의 모델/필드/속성을 작성한다
- 8prisma migrate dev로 마이그레이션을 적용한다
- 9Prisma Client의 create/findMany/update/delete를 사용한다
- 10include로 관계 데이터를 함께 조회한다
- 11Database/Collection/Document/Field 개념을 안다
- 12MongoDB Atlas 무료 클러스터를 생성하고 접속 URL을 얻는다
- 13Mongoose로 연결, Schema/Model을 정의한다
- 14create/find/findById/findByIdAndUpdate/findByIdAndDelete를 사용한다
- 15MongoDB와 RDB 중 적합한 상황을 판단한다
Node.js + SQLite
Node.js에서 SQLite를 다루는 가장 인기 있는 better-sqlite3 라이브러리로 prepare/run/get/all 메서드를 익히고, Express와 결합한 CRUD API를 만듭니다.
1. better-sqlite3 소개
- 동기식(Synchronous) API — async/await 불필요
- 빠른 성능
- Prepared Statement로 SQL 인젝션 방지
- TypeScript 타입 정의 내장
npm install better-sqlite3
npm install express2. 기본 사용법
const Database = require('better-sqlite3');
const db = new Database('library.db'); // 없으면 자동 생성3. prepare / run / get / all
prepare — SQL 준비
const stmt = db.prepare('SELECT * FROM books WHERE id = ?');run — INSERT/UPDATE/DELETE
const insert = db.prepare('INSERT INTO books (title, author) VALUES (?, ?)');
const result = insert.run('클린 코드', '로버트 마틴');
console.log(result.lastInsertRowid); // 삽입된 행의 ID
console.log(result.changes); // 영향받은 행 수get — 단일 행
const book = db.prepare('SELECT * FROM books WHERE id = ?').get(1);
// { id: 1, title: '클린 코드', author: '로버트 마틴' } | undefinedall — 여러 행
const books = db.prepare('SELECT * FROM books WHERE category = ?').all('프로그래밍');
// 배열 (없으면 빈 배열)4. 메서드 비교
| 메서드 | 용도 | 반환값 |
|---|---|---|
| run() | INSERT/UPDATE/DELETE | { lastInsertRowid, changes } |
| get() | SELECT 단일 | 객체 또는 undefined |
| all() | SELECT 여러 | 배열 (빈 배열 가능) |
5. 파라미터 바인딩
// 위치 (?)
db.prepare('SELECT * FROM books WHERE price > ? AND category = ?').all(20000, '프로그래밍');
// 이름 (@)
db.prepare('SELECT * FROM books WHERE price > @minPrice AND category = @cat')
.all({ minPrice: 20000, cat: '프로그래밍' });절대 문자열 결합으로 쿼리 만들지 마세요. SQL 인젝션 위험.
6. 테이블 초기화
db.exec(`
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author TEXT NOT NULL,
price INTEGER DEFAULT 0
)
`);7. ORM의 개념
SQL 방식
const book = db.prepare('SELECT * FROM books WHERE id = ?').get(1);ORM 방식 (Prisma)
const book = await prisma.book.findUnique({ where: { id: 1 } });- 장점: SQL 직접 안 써도 됨, 타입 안전, 마이그레이션 도구
- 단점: 복잡한 쿼리는 표현 어려움, 추가 학습 비용
Prisma ORM
차세대 ORM Prisma로 schema.prisma 파일에 모델을 정의하고, 마이그레이션으로 DB 스키마를 관리하며, 자동 생성된 Client로 타입 안전한 CRUD를 작성합니다.
1. Prisma란
schema.prisma (모델 정의)
↓ npx prisma migrate dev
DB 테이블 자동 생성
↓
Prisma Client (자동 생성 코드)
↓
JavaScript 코드에서 타입 안전한 DB 조작// 기존 (better-sqlite3)
const users = db.prepare('SELECT * FROM users WHERE age > ?').all(20);
// Prisma
const users = await prisma.user.findMany({
where: { age: { gt: 20 } }
});2. 설치 및 초기화
npm init -y
npm install @prisma/client
npm install -D prisma
npx prisma init --datasource-provider sqliteprisma/
└── schema.prisma ← 모델 정의
.env ← DATABASE_URL3. schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
createdAt DateTime @default(now())
}
model Post {
id Int @id @default(autoincrement())
title String
content String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}| 속성 | 설명 |
|---|---|
| @id | 기본키 |
| @default(autoincrement()) | 자동 증가 |
| @unique | 유니크 |
| @default(now()) | 현재 시각 |
| @updatedAt | 수정 시 자동 갱신 |
| @relation | 관계 정의 |
4. 마이그레이션
npx prisma migrate dev --name init # 생성·적용
npx prisma migrate status # 목록
npx prisma studio # GUI 도구5. Prisma Client CRUD
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
// Create
const user = await prisma.user.create({
data: { email: 'kim@example.com', name: '김철수' }
});
// Read - many
const users = await prisma.user.findMany();
// Read - 조건/정렬/제한
const active = await prisma.user.findMany({
where: { posts: { some: { published: true } } },
orderBy: { createdAt: 'desc' },
take: 10,
});
// Read - 단일
const user = await prisma.user.findUnique({ where: { id: 1 } });
// Update
await prisma.user.update({
where: { id: 1 },
data: { name: '김영수' }
});
// Delete
await prisma.user.delete({ where: { id: 1 } });6. 관계 데이터
// include로 관련 데이터 함께 조회
const userWithPosts = await prisma.user.findUnique({
where: { id: 1 },
include: { posts: true }
});
// 기존 유저와 연결
const post = await prisma.post.create({
data: {
title: '첫 번째 포스트',
content: '내용',
author: { connect: { id: 1 } }
}
});
// 중첩 create
const userWithPost = await prisma.user.create({
data: {
name: '이영희',
email: 'lee@example.com',
posts: { create: [{ title: '포스트 1', content: '내용 1' }] }
}
});MongoDB 기초
NoSQL의 대표 MongoDB의 문서·컬렉션 개념, Atlas 무료 클러스터 생성, Mongoose로 Node에서 연결, Schema/Model 정의와 CRUD를 익힙니다.
1. NoSQL — 문서/컬렉션
| SQL | MongoDB | 설명 |
|---|---|---|
| 데이터베이스 | Database | 같음 |
| 테이블 | Collection | 문서의 묶음 |
| 행(Row) | Document | 하나의 데이터 |
| 열(Column) | Field | 데이터의 속성 |
| 기본키(PK) | _id | 자동 ObjectId |
{
"_id": "64a7c8e3f9b12345678abcde",
"title": "오늘 할 일",
"content": "MongoDB 공부하기",
"tags": ["공부", "개발"],
"author": { "name": "김철수", "email": "kim@example.com" },
"createdAt": "2024-03-15T10:00:00.000Z"
}관련 데이터를 문서 안에 중첩(embed) 가능 → JOIN 없이 하나의 쿼리로 조회.
2. MongoDB Atlas 무료 클러스터
- https://www.mongodb.com/atlas 접속 → 회원가입
- Build a Database → Free (M0) 선택
- AWS / Seoul (ap-northeast-2)
- Create
- Database Access — 사용자 추가 (비밀번호 기록!)
- Network Access — Allow Access from Anywhere
- Connect → Connection String 복사
mongodb+srv://username:password@cluster0.xxxxx.mongodb.net/myDB?retryWrites=true&w=majority3. Mongoose 연결
npm install mongoose express dotenv# .env
MONGODB_URI=mongodb+srv://username:password@cluster0.xxxxx.mongodb.net/myDBconst mongoose = require('mongoose');
mongoose.connect(process.env.MONGODB_URI)
.then(() => console.log('MongoDB 연결 성공'))
.catch((err) => console.error('연결 실패:', err));4. Schema / Model
const mongoose = require('mongoose');
const memoSchema = new mongoose.Schema(
{
title: { type: String, required: true },
content: { type: String, required: true },
tags: [String],
isPublic: { type: Boolean, default: false },
},
{ timestamps: true } // createdAt, updatedAt 자동
);
// 컬렉션명은 자동으로 소문자 복수형 (Memo → memos)
const Memo = mongoose.model('Memo', memoSchema);
module.exports = Memo;5. CRUD
Create
// new + save
const memo = new Memo({ title: '제목', content: '내용', tags: ['공부'] });
await memo.save();
// create (권장)
const memo = await Memo.create({ title: '제목', content: '내용' });Read
const memos = await Memo.find();
const memos = await Memo.find({ tags: '공부' });
const memos = await Memo.find().sort({ createdAt: -1 }).limit(10);
const memo = await Memo.findById('64a7c8e3f9b12345678abcde');
const memo = await Memo.findOne({ title: '오늘 할 일' });Update
const updated = await Memo.findByIdAndUpdate(
id,
{ title: '새 제목' },
{ new: true } // 수정 후 문서 반환
);Delete
await Memo.findByIdAndDelete(id);6. 언제 MongoDB?
MongoDB 유리
- 데이터 구조가 자주 바뀌는 프로젝트
- 문서 안에 배열/중첩 객체가 많은 경우 (태그, 댓글 배열)
- 대용량 비정형 데이터 (로그, 이벤트)
- 빠른 수평 확장이 필요한 경우
RDB 유리
- 데이터 간 복잡한 관계가 많은 경우
- 금융/결제 등 트랜잭션 무결성 중요
- 정해진 스키마로 데이터 일관성 중요
댓글 0
아직 댓글이 없습니다. 첫 댓글을 남겨 주세요.
댓글은 회원만 쓸 수 있습니다.
광고·욕설·비방·개인정보·불법 내용이 담긴 댓글은 숨기거나 지웁니다. 댓글은 닉네임과 함께 공개됩니다. 개인정보처리방침