데이터베이스 기초 (SQL vs NoSQL)
서버 메모리의 한계를 확인하고 관계형 SQL과 문서형 NoSQL의 구조·질의·확장 특성에 따라 저장소를 선택합니다.
앞 절에서는 Node.js와 Express.js로 RESTful API를 설계/구현하는 방법을 학습했습니다.
이제 클라이언트 요청에 맞춰 데이터를 주고받는 서버를 만들 수 있게 되었습니다.
하지만 우리가 앞 절에서 구현한 API는 사용자 데이터를 서버 메모리(let users = [...])에 임시로 저장했습니다.
서버를 재시작하면 모든 데이터가 사라지는 휘발성 방식이었죠.
실제 웹 애플리케이션에서는 사용자 정보, 게시물, 상품 목록, 주문 내역 등 방대한 데이터를 영구적으로 저장하고 관리해야 합니다.
또한, 여러 사용자가 동시에 데이터를 요청하거나 변경하는 상황을 안정적으로 처리할 수 있어야 합니다.
이 요구사항을 충족하기 위해 필요한 것이 데이터베이스(Database)입니다.
데이터베이스는 데이터를 체계적으로 저장/관리하는 백엔드 핵심 구성 요소이며, 이번 장에서는 기본 개념, 종류, 웹 애플리케이션 활용 방식을 정리합니다.
FLOWCHART · B99 WEB FUNDAMENTALS
접근 패턴 기반 데이터베이스 선택
저장소는 access pattern, relationship, integrity and transaction boundary, consistency, scaling and operations로 선택한다. 클라이언트는 DB에 직접 접근하지 않고 서버가 입력·권한·transaction과 공개 응답을 통제한다.
저장소 이름부터 고르지 않는다. 실제 query와 불변식을 먼저 적고, 둘 이상의 저장소를 쓰면 동기화 실패도 설계한다.
데이터베이스(Database)란?
데이터베이스 기초 (SQL vs NoSQL)에서는 데이터 위치, 요청 계약, 응답 처리 기준을 정리합니다.
데이터베이스는 조직적이고 구조화된 정보(데이터)의 집합입니다.
특정 목적을 위해 데이터를 저장하고, 필요할 때 쉽게 검색, 삽입, 업데이트, 삭제할 수 있도록 설계되었습니다.
- 영구성(Persistence): 데이터는 서버가 재시작되어도 사라지지 않고 영구적으로 저장됩니다.
- 일관성(Consistency): 데이터의 무결성을 유지하며, 미리 정의된 규칙에 따라 데이터가 정확하고 유효하게 유지됩니다.
- 동시성 제어(Concurrency Control): 여러 사용자가 동시에 데이터에 접근하고 변경하려 할 때, 데이터 충돌을 방지하고 정확성을 보장합니다.
- 데이터 독립성: 애플리케이션과 데이터가 분리되어, 한쪽의 변경이 다른 쪽에 미치는 영향을 최소화합니다.
이 항목들은 DBMS라는 이름만으로 자동 보장되는 성질이 아닙니다. 지속성은 실제 저장 방식과 커밋·복구 설정에 달려 있으며, Redis는 지속성 기록을 완전히 끄는 옵션도 제공합니다. 업무 데이터의 무결성은 선언한 제약과 애플리케이션의 검증으로 지켜야 하고, 동시 갱신은 트랜잭션과 격리 정책을 정해 처리해야 합니다. 예를 들어 MySQL의 커밋·롤백 조건과 트랜잭션 격리 수준을 확인해야 각 작업을 언제 확정하고 동시 요청을 어떻게 다룰지 설명할 수 있습니다.
데이터베이스를 관리하는 시스템을 데이터베이스 관리 시스템(DBMS: Database Management System)이라고 부릅니다.
DBMS는 사용자와 데이터베이스 사이에서 데이터를 생성, 관리, 검색하는 데 필요한 인터페이스를 제공합니다.
데이터베이스의 종류
데이터베이스는 크게 두 가지 주요 범주로 나눌 수 있습니다.
관계형 데이터베이스
관계형 데이터베이스 (RDBMS: Relational Database Management System)는 가장 전통적이고 널리 사용되는 데이터베이스 유형입니다.
데이터를 테이블(Table), 행(Row), 열(Column)의 형태로 구성합니다. 행을 식별할 기본 키(Primary Key)와 테이블 사이의 참조를 검사할 외래 키(Foreign Key)를 설계할 수 있습니다. 모든 테이블에 이 두 제약이 자동으로 생기는 것은 아닙니다. 예를 들어 MySQL의 CREATE TABLE 규약은 기본 키가 없는 테이블도 다룹니다.
- 데이터 모델: 관계형 모델
- 데이터 저장 방식: 테이블 (스프레드시트와 유사)
- 쿼리 언어: SQL (Structured Query Language)
-
주요 특징
- 정규화: 데이터 중복을 최소화하고 데이터 무결성을 유지하기 위해 데이터를 여러 테이블로 분리하는 과정.
- ACID 트랜잭션: 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability)을 보장하여 데이터의 신뢰성 확보. 특히 금융 시스템처럼 데이터의 정확성이 매우 중요한 곳에서 선호됩니다.
- 엄격한 스키마: 테이블을 생성할 때 미리 데이터의 구조(컬럼 이름, 데이터 타입 등)를 정의해야 합니다.
-
장점
- 데이터 일관성 및 무결성 보장.
- 정형화된 데이터에 강력.
- 관계가 복잡한 데이터 모델에 적합.
- 오랫동안 사용되어 안정적이고 성숙한 기술.
-
단점
- 데이터 스키마 변경 시 유연성이 떨어짐.
- 수평적 확장(Scale-out)이 어려움 (Scale-up은 가능).
- 반정형 데이터를 저장할 수 있는지와 그 질의 비용은 DBMS 기능에 따라 다름. 예를 들어 PostgreSQL은 JSON·JSONB 타입을 지원하므로 JSON이라는 이유만으로 관계형 DB를 제외하지 않습니다.
-
대표적인 예시
- MySQL: 가장 인기 있는 오픈소스 RDBMS.
- PostgreSQL: MySQL과 함께 강력한 오픈소스 RDBMS로, 더 많은 기능과 확장성을 제공합니다.
- Oracle: 엔터프라이즈 환경에서 널리 사용되는 상용 RDBMS.
- SQL Server: Microsoft에서 개발한 RDBMS.
- SQLite: 서버 없이 파일 형태로 데이터를 저장하는 경량 RDBMS (개발 및 소규모 앱에 적합).
NoSQL 데이터베이스
NoSQL (Not Only SQL) 데이터베이스는 관계형 데이터베이스의 한계(스키마 유연성 부족, 확장성 문제)를 극복하기 위해 등장한 비관계형 데이터베이스입니다.
데이터 저장 방식에 따라 다양한 유형으로 나뉩니다.
- 데이터 모델: 관계형 모델을 따르지 않음.
- 쿼리 언어: 각 유형 및 데이터베이스마다 다름. (SQL과 유사하거나 독자적인 API 사용)
-
주요 특징
- 스키마리스(Schemaless) 또는 유연한 스키마: 데이터의 구조가 미리 정의되지 않아 유연한 데이터 모델링이 가능합니다.
- 수평적 확장 용이: 분산 환경에서 대규모 데이터 처리 및 확장에 유리합니다.
- 비정형/반정형 데이터: 텍스트, 이미지, 로그 데이터 등 정형화되지 않은 데이터를 효율적으로 저장하고 처리할 수 있습니다.
- CAP 이론: 네트워크 분할이 생겼을 때, 한 복사본처럼 최신 연산 순서를 보장하는 일관성(C)과 실패하지 않은 노드의 모든 요청에 응답하는 가용성(A)을 동시에 보장할 수 없다는 제약입니다. SQL·NoSQL이라는 이름만으로 분할 시 정책을 정할 수는 없습니다.
-
장점
- 대규모 분산 환경에 적합.
- 유연한 스키마로 빠른 개발 및 변경 가능.
- 비정형 데이터 저장에 유리.
-
단점
- 데이터 일관성 보장이 관계형 DB보다 약할 수 있음.
- 문서형·키값형 모델에서 여러 데이터의 관계를 반복해서 결합하려면 추가 조회나 중복 관리 비용이 생길 수 있음. 반면 그래프 DB는 관계와 경로 탐색을 모델링하므로 복잡한 관계에 부적합하다는 평가를 NoSQL 전체에 적용하지 않습니다.
- 성숙도가 관계형 DB보다 낮을 수 있음.
-
대표적인 유형 및 예시
- 문서 지향 (Document-Oriented): 데이터를 JSON 또는 BSON(Binary JSON)과 같은 문서 형태로 저장합니다. (예: MongoDB, CouchDB)
- 키-값 (Key-Value): 가장 단순한 형태로, 키와 값의 쌍으로 데이터를 저장합니다. (예: Redis, DynamoDB)
- Wide-column / Column-family: 행 키와 컬럼 패밀리를 중심으로 데이터를 구성합니다. Cassandra·HBase가 대표적이며, 분석용 columnar 저장과 같은 분류는 아닙니다. 분석에 사용할 수 있다는 가능성과 저장 모델의 분류는 구분합니다.
- 그래프 (Graph): 노드와 엣지를 사용하여 데이터 간의 관계를 그래프 형태로 표현합니다. (예: Neo4j, Amazon Neptune)
웹 애플리케이션에서 데이터베이스의 역할
백엔드 서버와 데이터베이스는 다음과 같이 협력합니다.
데이터 저장: 사용자 가입, 게시물 작성, 상품 등록 등 클라이언트로부터 받은 데이터를 데이터베이스에 영구적으로 저장합니다.
데이터 조회: 클라이언트의 요청에 따라 데이터베이스에서 필요한 데이터를 검색하여 클라이언트에 응답합니다.
(예: 게시물 목록 가져오기, 특정 사용자 정보 조회)
데이터 업데이트: 기존 데이터의 내용을 변경합니다.
(예: 게시물 수정, 사용자 프로필 업데이트)
데이터 삭제: 더 이상 필요 없는 데이터를 데이터베이스에서 제거합니다.
(예: 회원 탈퇴, 게시물 삭제)
비즈니스 로직 지원: 복잡한 비즈니스 규칙(예: 재고 관리, 주문 처리, 권한 부여 등)을 수행할 때 데이터베이스의 데이터를 활용하거나 변경합니다.
백엔드 서버(Node.js + Express.js)는 데이터베이스와 직접 통신하며, 클라이언트(프론트엔드)는 백엔드 API를 통해 데이터베이스의 데이터에 간접적으로 접근하게 됩니다.
SQL 기초 (간략)
가장 널리 사용되는 관계형 데이터베이스 언어인 SQL의 기본적인 문법을 간략하게 살펴보겠습니다.
아래 코드는 MySQL 8.4 문법으로 읽습니다. USE, AUTO_INCREMENT, DATETIME 같은 표기는 모든 DBMS에서 그대로 통하는 공통 SQL 문법이 아닙니다. PostgreSQL이나 SQLite에 그대로 붙여 넣기 전에 해당 DBMS의 데이터베이스 선택·자동 증가·날짜 타입 문법을 확인해야 합니다.
실행하려면 MySQL 서버에 연결된 SQL 콘솔 또는 SQL 편집기가 먼저 필요합니다. Node.js의 터미널이나 브라우저 주소창에 SQL을 입력하는 방식은 아닙니다. 다음 순서는 새 실습용 mydatabase와 아직 없는 users 테이블을 전제로 하며, 계정에는 이 실습 DB를 만들고 테이블을 생성·조회·삽입·수정·삭제할 권한이 있어야 합니다. 이미 같은 이름의 DB나 테이블이 있는 환경에 반복 실행하는 절차는 별도로 정해야 합니다.
아래 행 변화는 자동 증가의 시작값과 간격이 기본값인 1이고, 다른 쓰기나 실패한 삽입 없이 두 INSERT를 한 번씩 실행하며, autocommit이 켜진 조건에서 예측합니다. created_at의 실제 시각은 실행 때 결정됩니다. MySQL의 DB 생성·선택과 자동 증가 예제가 이 전제를 설명합니다.
-
데이터베이스 생성/선택
CREATE DATABASE mydatabase; -- 데이터베이스 생성 USE mydatabase; -- 데이터베이스 선택 -
테이블 생성
CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, -- 정수형, 기본 키, 자동 증가 username VARCHAR(50) NOT NULL UNIQUE, -- 문자열 50자, NULL 불허, 중복 불허 email VARCHAR(100) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP -- 기본값으로 현재 시간 설정 ); -
데이터 삽입 (C: Create)
INSERT INTO users (username, email) VALUES ('alice', '[email protected]'); INSERT INTO users (username, email) VALUES ('bob', '[email protected]'); -
데이터 조회 (R: Read)
SELECT * FROM users; -- 모든 사용자 조회 SELECT username, email FROM users WHERE id = 1; -- ID가 1인 사용자의 이름과 이메일 조회 SELECT * FROM users WHERE username LIKE 'a%'; -- 'a'로 시작하는 사용자 조회 SELECT * FROM users ORDER BY created_at DESC; -- 생성일 기준으로 내림차순 정렬 -
데이터 업데이트 (U: Update)
UPDATE users SET email = '[email protected]' WHERE id = 1; -- ID가 1인 사용자의 이메일 변경 -
데이터 삭제 (D: Delete)
DELETE FROM users WHERE id = 2; -- ID가 2인 사용자 삭제
같은 두 행의 변화를 확인하기
각 쿼리는 앞 단계가 성공한 다음 실행합니다. 아래는 결과 행의 값에 대한 예측이며 콘솔의 실행 시간이나 출력 순서를 고정한 기록이 아닙니다.
- 새
users를 만들었을 때는 0행입니다. - 두 INSERT 뒤에는
id=1, username=alice, [email protected]과id=2, username=bob, [email protected]인 2행이 있습니다.SELECT ... WHERE id = 1과LIKE 'a%'는 이때 Alice 한 행을 고릅니다. UPDATE ... WHERE id = 1뒤에는 행 수가 2인 채 Alice의 이메일만[email protected]으로 바뀝니다. Bob은 바뀌지 않습니다.DELETE ... WHERE id = 2뒤에는 Alice 한 행만 남습니다.id=2를 조회하면 결과는 0행입니다.
SELECT * FROM users는 행의 순서를 보장하지 않습니다. ORDER BY created_at DESC에서도 두 시각이 같으면 그 두 행 사이의 순서는 확정할 수 없습니다. 순서까지 비교하려면 별도의 정렬 조건을 정해야 합니다. 자동 증가 ID도 일반적으로 빈틈없는 번호를 보장하는 장치는 아니므로, 여기서 1·2를 기대하는 이유는 앞의 새 테이블·기본 설정·단 한 번 삽입 조건에 있습니다.
행 변화를 먼저 예측한 뒤 조회하기
두 INSERT와 위 UPDATE·DELETE를 순서대로 마친 상태에서 다음 두 조회는 각각 몇 행과 어떤 이메일을 돌려줄까요? 아래 테이블 삭제는 아직 실행하지 않습니다.
SELECT id, username, email FROM users WHERE id = 2;
SELECT id, username, email FROM users WHERE username LIKE 'a%';답: 첫 조회는 Bob을 이미 삭제했으므로 0행입니다. 두 번째는 id=1, username=alice, [email protected]인 한 행입니다. UPDATE는 조건에 맞는 기존 행의 값만 바꾸고 DELETE는 조건에 맞는 행을 제거했으므로 두 작업의 차이를 조회 결과로 확인할 수 있습니다.
-
테이블 삭제
행 변화 실습을 마친 뒤 수행하는 정리 단계입니다.
DELETE와 달리 테이블 구조 자체를 없애므로 이후 같은users조회는 실패합니다.DROP TABLE users;
이러한 SQL 쿼리들을 백엔드 서버(예: Node.js)에서 데이터베이스 드라이버 또는 ORM(Object-Relational Mapping) 라이브러리를 통해 실행하여 데이터를 조작하게 됩니다.
메모리 배열을 데이터베이스로 바꾸면 요청 처리 흐름에 검증, 쿼리, 응답 매핑 단계가 추가됩니다.
DATA-FLOW
API와 영속성 계층의 신뢰 경계
외부 입력과 저장 데이터는 서로 다른 계약입니다. 입력·권한을 검증한 뒤 업무 규칙을 적용하고, 저장 결과 중 공개할 필드만 응답으로 돌려줍니다. 그림은 역할을 나눈 설계 예시입니다.
- 요청 command
- 저장 결과·공개 응답
- rollback
트랜잭션은 여러 변경을 하나로 묶을 때 사용합니다. DB row의 비공개 필드가 응답에 섞이지 않도록 두 방향의 경계 변환을 명시합니다.
데이터베이스를 고를 때는 SQL과 NoSQL이라는 이름보다 데이터 구조, 관계 복잡도, 일관성 요구, 확장 방식을 먼저 비교합니다.
선택 단계에서는 데이터의 구조와 운영 요구를 질문으로 나누어 SQL과 NoSQL의 적합성을 판단합니다.
데이터베이스 입문 요약
이번 장에서는 웹 애플리케이션의 데이터를 영구적으로 저장하고 관리하는 핵심 요소인 데이터베이스의 기초를 학습했습니다.
이번 절에서는 데이터베이스의 영구성, 일관성, 동시성 제어를 기준으로 RDBMS와 NoSQL의 차이를 비교했습니다.
백엔드 서버가 데이터베이스와 연동해 데이터를 저장, 조회, 수정, 삭제하는 흐름과 SQL CRUD 문법도 함께 정리했습니다.
이 절에서는 백엔드 개발에서 데이터베이스가 필요한 이유, 데이터베이스 종류, 기본적인 데이터 처리 흐름을 정리했습니다.
다음 장에서는 앞서 익힌 요청·CRUD·저장소 기초를 바탕으로 웹 보안과 성능 최적화를 살펴봅니다.