풀스택 개발자 과정 27일차

너구·2026년 6월 15일

풀스택 성장과정

목록 보기
27/79

데이터베이스 (Database)

데이터베이스(DB)는 데이터를 전문적이고 체계적으로 관리하기 위해 구출하는 데이터 저장소이다.
데이터 모델링 방식에 따라 크게 두 종류로 구분된다.

  • 관계형 데이터베이스(RDB)
  • 비관계형 데이터베이스(NoSQL)

관계형 데이터베이스 (Relational Database)

데이터를 행과 열을 가진 테이블(Table) 형식으로 저장한다.
가장 널리 사용되는 데이터베이스 방식이다.

주요 제품

  • MySQL/MariaDB: 오픈 소스로 웹 서비스에서 가장 많이 쓰인다.
  • PostgreSQL: 복잡한 쿼리 처리, 대용량 데이터, 확장 기능이 뛰어나 엔터프라이즈급에서 선호한다.
  • Oracle: 강력한 성능과 고비용의 폐쇄형 DB로 대형 금융권에서 주로 사용한다.

비관계형 데이터베이스 (No SQL)

테이블 제약에서 벗어나 유연한 데이터 구조를 가진다.
데이터의 형태가 자주 바뀌거나 엄청난 양의 데이터를 빠르게 처리해야 할 때 적합하다.

주요 제품

  • MongoDB: JSON 형식으로 데이터를 저장한다.
    유연한 구조로 개발 속도가 빠르다.
  • Redis: 메모리 기반 DB. 초고속 응답이 필요할 때 캐시(cache)나 세션 저장소로 활용한다.
  • Cassandra: 엄청난 양의 로그 데이터나 시계열 데이터를 처리할 때 유리하다.

DBMS

데이터베이스 관리 시스템(DataBase Managnent System)을 의미한다.
데이터베이스가 개념적인 용어라면 DBMS는 그 구현체를 의미한다.
많은 문맥에서 데이터베이스 그 자체를 의미하기도 한다.


트랜잭션 (Transaction)

데이터베이스의 상태를 변화시키는 하나의 논리적 작업 단위를 의미한다.
쉽게 말해 더이상 쪼갤 수 없는 최소 작업 단위를 의미한다.

트랜젝션 4대 특징 (ACID)

  1. 원자성 (Atomicity)
  2. 일관성 (Consistency)
  3. 고립성 (Isolation)
  4. 영속성 (Durability)

원자성 (Atomicity)

트랜잭션 내의 모든 연산은 반드시 전체가 다 수행되거나 아니면 전체가 다 수행되지 않아야한다.(All or Nothing)
하나의 연산이 실패하면 트랜잭션 전체가 취소된다.

일관성 (Consistency)

트랜잭션이 성공적으로 완료되어 데이터베이스의 상태를 변화시킬 때 데이터베이스가 사전에 정의된 제약 조건들을 여전히 만족해야 한다.

고립성/격리성 (Isolation)

둘 이상의 트랜잭션이 동시에 실행될 때 각 트랜잭션이 서로의 작업에 끼어들거나 영향을 주지 못하도록 격리되어야 한다.

지속성/영속성 (Durability)

성공적으로 완료(Commit)된 트랜잭션의 결과는 영구적으로 반영되어야 한다.
즉 시스템이 다운되거나 디스크가 고장나더라도 바뀌어서는 안된다.


트랜잭션 제어 명령어 (TCL)

  • Commit(커밋): 트랜잭션이 수행한 연산들을 데이터베이스에 최종적으로 반영한다.
  • Rollback(롤백): 현재 트랜잭션 중 수행된 모든 변경 사항을 취소하고 트랜잭션 시작 전의 상태로 되돌린다.
  • Savepoint(세이브 포인트): 트랜잭션이 길어질 때 중간 저장점을 만들어 롤백할 때 처음이 아닌 특정 위치까지만 부분 롤백할 수 있도록 한다.

SQL

구조적 질의어(Structured Query Language)를 의미하는 것으로 데이터베이스를 조작하는 언어를 의미한다.

  • DDL (Data Definition Language)
  • DML (Data Manipulation Language)
  • DCL (Data Control Language)
  • TCL (Transaction Control Language)

관계 모델 (Relational Model)

관계 모델 또는 관계 데이터 모델은 데이터를 2차원의 표(Table)로 표현하고 데이터베이스 모델링 기법이다.
1970년 에드거 커드 박사가 제안하였다.

아래와 같이 현재 우리가 사용하는 거의 모든 RDB의 이론적 토대가 되었다.

  • MySQL
  • PostgreSQL
  • Oracle

관계 모델의 주요 용어들

릴레이션

다음은 학번, 학년, 이메일 등의 속성으로 구성된 학생 릴레이션이다.


키 (Key)

데이터 식별 또는 릴레이션 간의 관계를 맺기 위한 도구이다.

키의 상관 관계

기본키

아래 테이블에서 '학번'이 기본키이다.

외래 키

아래 학생 테이블에서 '학과ID'는 학과의 기본키를 참조하는 외래키이다.


무결성 (Integrity)

데이터가 정확하고 일관되게 유지되는 상태를 의미한다.
다음은 주요 무결성의 유형이다.

  • 개체 무결성 (Entity Integrity)
  • 참조 무결성 (Reference Integrity)
  • 도메인 무결성 (Domain Integrity)
  • 사용자 정의 무결성 (User-defined Integrity)

무결성 종류


DDL

DDL은 데이터 정의어(Data Definition Launguage)를 의미하며 데이터 베이스 객체(테이블, 뷰 인덱스 등)를 관리하는 역할을 한다.

다음은 DDL의 종류이다.

  • CREATE: 객체 생성 명령어
  • ALTER: 객체 수정 명령어
  • DROP: 객체 삭제 명령어

CREATE TABLE

테이블을 생성하는 명령어이다. 다음은 사용 방법이다.

CREATE TABLE 테이블 (
컬럼1 자료형 제약조건1 제약조건2, ... ,
컬럼2 자료형 제약조건1 제약조건2, ... ,
...
);


컬럼 자료형 종류


DROP TABLE

테이블을 삭제하는 명령어이다. 다음은 사용 방법이다.

DROP TABLE 테이블;


제약 조건

테이블을 생성 또는 수정할 때 데이터의 무결성을 지키기 위해 다양한 제약 조건을 추가할 수 있다.
다음은 주요 제약 조건이다.


학과 테이블 생성하기 예제

'학과번호(정수)', '학과이름(최대 100자)', '전화번호(최대 100자)'로 구성된 학과 테이블을 생성하라.
단 다음의 제약 조건을 고려하라.

  • 학과 이름, 전화번호는 NULL일 수가 없다.
  • 학과 번호가 기본키이며 데이터 삽입시 1부터 자동할당된다.
-- 테이블 생성문 (CREATE TABLE)
-- 테이블 이름 department(학과)
CREATE TABLE department (
-- dept_id (학과 번호), int (정수형), 1부터 자동 증가하도록 설정(auto increment)
dept_id int AUTO_INCREMENT,
-- dept_name (부서명), varchar (가변길이 문자열, 최대 100자로 설정)
-- NULL일 수 없음 (필수값)
dept_name varchar(100) NOT NULL,
-- 전화번호, 최대 100자, 필수값
phone_number varchar(100) NOT NULL,
-- 학과번호를 기본키로 설정
PRIMARY KEY(dept_id)
)

학과 정보를 저장할 수 있는 department 테이블을 생성하였다.

dept_id: 학과 번호를 저장하는 정수형 컬럼으로 AUTO_INCREMENT를 사용해 값이 자동으로 증가하도록 설정하였다.
dept_name: 학과명을 저장하는 문자열 컬럼이며 반드시 입력해야하므로 NOT NULL 제약 조건을 추가하였다.
phone_number: 학과 전화번호를 저장하는 문자열 컬럼이며 필수값으로 설정하였다.
PRIMARY KEY(dept_id): 학과 번호를 기본키로 지정해 각 학과를 고유하게 식별할 수 있도록 하였다.

이를 통해 학과 번호, 학과명, 전화번호를 체계적으로 관리할 수 있는 테이블을 생성할 수 있다.

학생 테이블 생성하기

'학번(정수)', '이름(최대 100자)', '학년(정수)', '학과ID(정수)', 취미(최대 100자)'로 구성된 학생 테이블을 생성하라.
단 다음의 제약 조건을 고려하라.

  • 이름, 학년, 학과ID는 NULL일 수 없습니다.
  • 학년은 1부터 4 사이의 값만 가능합니다. 기본값은 1로 정합니다.
  • '학번'이 기본키이며 데이터 삽입시 1부터 자동으로 할당됩니다.
  • 학과ID는 <학과>테이블의 기본키를 참조합니다
-- 테이블 이름은 student(학생)
CREATE TABLE student(
-- 학번(student_id), 정수형 + 자동증가(auto increment) 조합
student_id int AUTO_INCREMENT,
-- 이름(student_name), 최대 100자(varchar(100), 필수값
student_name varchar(100) NOT NULL,
-- 학년(grade), 학년이 1과 4 사이의 값이어야 한다.(check), 기본값(default) 1, 필수값
grade int CHECK(grade BETWEEN 1 AND 4) DEFAULT 1 NOT NULL,
-- 학과번호(dept_id), 필수값
dept_id int NOT NULL,
-- 취미(hobby), 최대 100자, 옵션
hobby varchar(100),
-- 학번(student_id)를 기본키로 설정
PRIMARY KEY(STUDENT_ID),
-- 학과번호(dept_id)를 외래키로 설정
-- 이 외래키는 학과(department)의 기본키(dept_id)를 참조(reference) 한다.
FOREIGN KEY(dept_id) REFERENCES department(dept_id)
)

학생 정보를 저장하기위한 student 테이블을 생성하였다.

student_id: 학번을 저장하는 정수형 컬럼으로 AUTO_INCREMENT를 사용해 자동으로 증가하게 설정하였다.
student_name: 학생 이름을 저장하는 문자열 컬럼이며 필수값으로 지정하였다.
grade: 학년을 저장하는 정수형 컬럼이다.
CHECK 제약 조건을 사용해 1~4학년만 입력할 수 있도록 하였고 기본값은 1학년으로 설정하였다.
dept_id: 학생이 소속된 학과 번호를 저장하는 컬럼이며 필수값으로 설정하였다.
hobby: 학생의 취미를 저장하는 컬럼으로 선택적으로 입력할 수 있다.
PRIMARY KEY(student_id): 학번을 기본키로 지정해 학생을 고유하게 식별할 수 있게 하였다.
FOREIGN KEY(dept_id): 학과 테이블의 dept_id를 참조하는 외래키로 설정하여 학생과 학과의 관계를 연결하였다.

상품 테이블 생성하기

'상품번호(정수)', '상품명(최대 100자)', '가격(정수)', '카테고리(최대 100자)', '판매량(정수)'로 구성된 상품 테이블을 생성하라.
단 다음의 제약 조건을 고려하라.

'상품번호(정수)', '상품명(최대 100자)', ‘가격(정수)', ‘카테고리(최대 100자)’, '판매량(정수)' 로 구성된 <상품>테이블을 생성하세요. 단 다음의 제약 조건을 고려하세요.

  • 상품명, 가격, 카테고리, 판매량은 NULL일 수 없습니다.
  • 가격, 판매량은 음수일 수 없습니다.
  • 제품을 삽입하면 판매량은 기본값 0으로 설정됩니다.
  • '상품 번호'는 기본키이며 데이터 삽입시 1부터 자동으로 할당됩니다.
-- 제품(product) 테이블
CREATE TABLE product (
-- 제품 ID(product_id), 정수형 + 자동증가
product_id int AUTO_INCREMENT,
-- 제품명(product_name), 최대 100자, 필수값
product_name varchar(100) NOT NULL,
-- 가격(price), unsigned(부호 없음) 즉 양수만 가능, 필수값
price int unsigned NOT NULL,
-- 카테고리(category), 최대 100자, 필수값
category varchar(100) NOT NULL,
-- 판매량(sales), unsigned(부호없음), 필수값, 기본값은 0
sales int unsigned NOT NULL DEFAULT 0,
-- 제품ID를 기본키로 설정
PRIMARY KEY(product_id)
)

제품 정보를 저장하기위한 product 테이블을 생성하였다.

product_id: 제품 번호를 저장하는 정수형 컬럼으로 AUTO_INCREMENT를 사용해 자동으로 증가하도록 설정하였다.
product_name: 제품명을 저장하는 문자열 컬럼이며 필수값으로 지정하였다.
price: 제품 가격을 저장하는 컬럼이다.
unsigned를 사용해 음수가 입력되지 않도록 설정하였다.
category: 제품 카테고리를 저장하는 문자열 컬럼이며 필수값이다.
sales: 제품 판매량을 저장하는 컬럼이다.
unsigned를 사용해 음수를 방지하고 기본값을 0으로 설정하였다.
PRIMARY KEY(product_id): 제품ID를 기본키로 지정해 각 제품을 고유하게 식별할 수 있도록 하였다.

이를 통해 제품명, 가격, 카테고리, 판매량 등의 정보를 체계적으로 관리할 수 있다.


CRUD

  • C (Create) = INSERT문
  • R (Read) = SELECT문
  • U (Update) = UPDATE문
  • D (Delete) = DELETE문

DML

DML은 데이터 조작어(Data Manipulation Language)를 의미한다.
아래 4가지로 구성된다.

  • INSERT : 데이터를 삽입하는 명령어
  • SELECT : 데이터를 추출/조회하는 명령어
  • UPDATE : 데이터를 갱신하는 명령어
  • DELETE : 데이터를 삭제하는 명령어

INSERT

데이터를 삽입하는 SQL문이다. 다음의 INSERT문의 사용방법이다.
(만약 모든 컬럼에 해당하는 값을 삽입하는 경우 앞에서 컬럼을 지정하지 않아도 된다)

INSERT INTO 테이블(컬럼 1, 컬럼 2,...) VALUES(컬럼1 값, 컬럼2 값,...)

INSERT 예제 (1)

학과 테이블에 다음의 데이터를 삽입하라.

INSERT INTO department (dept_name, phone_number) VALUES ('수학과', '1234-5678');
INSERT INTO department (dept_name, phone_number) VALUES ('물리학과', '2345-6789');
INSERT INTO department (dept_name, phone_number) VALUES ('체육학과', '3456-7890');

조회시 이런 식으로 값이 들어간 것을 확인할 수 있다.
(여러번 눌러서 값이 여러번 들어갔는데 수정 방법을 찾아야겠다...)

답을 찾았다
student 테이블과 department 테이블에 있는 값들을 모두 삭제한 뒤 AUTO_INCREMENT를 1로 초기화시킨 후 다시 재작성하였다!

INSERT 예제 (2)

학생 테이블에 다음의 데이터를 삽입하라.

INSERT INTO student (student_name, grade, dept_id, hobby) VALUES ('김모군', 1, 3, '축구');
INSERT INTO student (student_name, grade, dept_id, hobby) VALUES ('이모군', 1, 2, '독서');
INSERT INTO student (student_name, grade, dept_id, hobby) VALUES ('박모군', 2, 1, '영화감상');
INSERT INTO student (student_name, grade, dept_id, hobby) VALUES ('최모군', 2, 2, '게임');
INSERT INTO student (student_name, grade, dept_id, hobby) VALUES ('정모군', 3, 3, '축구');

INSERT 예제 (3)

상품 테이블에 다음의 데이터를 삽입하라.

INSERT INTO product (product_name, price, category, sales) VALUES ('아메리카노', 2000, '커피', 10);
INSERT INTO product (product_name, price, category, sales) VALUES ('카페라떼', 3000, '커피', 5);
INSERT INTO product (product_name, price, category, sales) VALUES ('바닐라라떼', 3500, '커피', 3);
INSERT INTO product (product_name, price, category, sales) VALUES ('마카롱', 2000, '디저트', 2);
INSERT INTO product (product_name, price, category, sales) VALUES ('치즈케이크', 4000, '디저트', 1);


SELECT

데이터를 조회하는 SQL문이다. 다음은 SELECT문의 사용 방법이다.
만약 모든 컬럼을 조회하는 경우 컬럼을 지정하는 대신 와일드카드(*)를 쓰면 된다.

SELECT 컬럼1, 컬럼2,... FROM 테이블

SELECT 예제

학생 테이블에서 '이름', '학년' 컬럼과 함께 모든 학생을 조회하라.

SELECT student_name, grade FROM student;

-- 쿼리(query), SQL문 등등 => 지시문, 명령문
-- Query = 질의(요청)
SELECT student_name, grade FROM student;
-- 이름(student_name), 학년(grade)를 조회하라
-- from student: 학생테이블로부터

SELECT는 데이터베이스에서 원하는 데이터를 조회할 때 사용하는 SQL명령어이다.
student_name은 학생 이름 컬럼, grade는 학년 컬럼, FROM student는 student 테이블에서 데이터를 가져온다는 의미이다.
즉 위 쿼리는 student 테이블에 저장된 학생들의 이름과 학년을 조회하라는 것이다.

SELECT 와일드 카드 사용하기

학생 테이블로부터 학생들을 모든 컬럼과 함께 조회하라

SELECT * FROM student

SELECT * FROM student;
-- 와일드카드(*)는 모든 컬럼을 가져온다

UPDATE

데이터를 갱신하는 SQL문이다. 다음은 UPDATE문의 사용 방법이다.
일반적으로 조건절(WHERE)과 함께 사용된다.
만약 조건이 없으면 모든 튜플이 갱신되니 주의해야 한다.

UPDATE 테이블 SET 컬럼1 = 컬럼1 새값, 컬럼2 = 컬럼 2 새값,...

UPDATE 예제

학생 테이블에서 학번이 2인 학생의 취미를 '그림'으로 변경하라.

UPDATE student SET hobby = '그림' WHERE student_id=2;

-- 학번이 2번인 학생의 취미를 '그림'으로 갱신하는 쿼리
-- WHERE은 조건절이다
UPDATE student SET hobby= '그림' WHERE student_id = 2;
-- UPDATE 테이블 SET 컬럼 = 새값 WHERE...

이번 예제에서는 UPDATE문을 사용해 기존 데이터의 값을 수정하는 방법을 학습하였다.
UPDATE student: student 테이블의 데이터를 수정한다.
SET hobby= '그림': hobby 칼럼의 값을 '그림'으로 변경한다.
WHERE student_id = 2;: 학번이 2번인 학생만 수정한다.
즉 위 쿼리는 학번이 2번인 학생의 취미를 '그림'으로 변경하라는 의미이다.
⚠️ WHERE 절을 작성하지 않으면 테이블의 모든 행이 수정될 수 있으므로 주의해야 한다.


DELETE

데이터를 삭제하는 SQL문이다. 다음은 DELETE문의 사용 방법이다.
일반적으로 조건절(WHERE)과 함께 사용된다.
만약 조건이 없으면 모든 튜플이 삭제되니 주의해야 한다.

DELETE FROM 테이블


조건 지정하기

WHERE은 데이터를 조작할 때 조건을 지정하는 명령어이다.
다음의 연산자들과 함께 사용된다.

  • 비교 연산자 (Comparison Operator)
  • 논리 연산자 (Logical Operator)
  • 산술 연산자 (Arithmetic Operator)

비교 연산자

비교 연산자 예제 (1)

학생 테이블로부터 이름이 '이모군'인 학생을 조회하라.

-- 학생 테이블에서 이름이 '이모군'인 학생을 조회하는 쿼리
-- *(와일드카드)를 써서 모든 속성과 함께 조회한다
SELECT*FROM student WHERE student_name='이모군';

비교 연산자 예제 (2)

학생 테이블로부터 1학년 학생을 조회하라.

-- 학생 테이블에서 1학년 학생들만 조회한다.
select*FROM student WHERE grade = 1;

논리 연산자

논리 연산자 예제 (AND)

학생 테이블로부터 1학년이고 취미가 '축구'인 학생들을 조회하라.

-- 1학년 학생들 중 축구 좋아하는 애들을 조회한다
SELECT*FROM student WHERE grade = 1 AND hobby = '축구';

논리 연산자 예제 (IN)

학생 테이블로부터 취미가 '축구', '게임'인 학생들을 조회하라

-- 학생들 중에서 취미가 축구거나 게임인 학생들을 조회
SELECT*FROM student WHERE hobby IN ('축구', '게임')

논리 연산자 예제 (LIKE)

학생 테이블로부터 성이 '김'인 학생을 조회하라

-- 학생들 중에서 이름이 '김'으로 시작하는 애들
SELECT*FROM student WHERE student_name LIKE '김%';

정렬하기

ORDER BY는 추출할 레코드의 순서를 정하는 명령어이다.

FROM 테이블 ORDER BY 칼럼 ASC/DESC

  • ASC 오름차순(ascending)을 의미합니다. 문자는 알파벳순, 숫자는 오름차순으로 정렬합니다. 기본값입니다.
  • DESC 내림차순(descending)을 의미합니다. 문자는 역알파벳순, 숫자는 내림차순으로 정렬합니다.

정렬하기 예제

학생 테이블에서 '이름'을 기준으로 알파벳순으로 정렬하고 조회하라.

-- 학생 이름을 기준으로 정렬
-- 이름(가나다순)
-- 정렬 방식(ASC/DESC)를 생략하면 ASC(오름차순)이 적용된다
SELECT*FROM student ORDER BY student_name;

통계내기

집계 함수(Aggregate Funcion)를 통해 테이블을 대상으로 다양한 집계를 내릴 수 있다.

MAX/MIN 예제

상품 테이블로부터 가장 비싼 제품과 가장 싼 제품의 가격을 추출하라.

-- 상품테이블에서 최저가, 최고가의 가격을 조회
SELECT MAX(price), MIN(price) FROM product;

COUNT 예제

상품 테이블에 존재하는 모든 상품의 개수를 세보아라.

-- 제품 테이블에 존재하는 상품의 개수를 센다.
-- COUNT에 *(와일드카드)를 입력할 경우 행의 개수를 센다.
SELECT COUNT(*)FROM product;

SUM 예제

상품 테이블로부터 모든 제품에 대한 총 판매량을 구하라.

-- 제품의 총 판매량을 조회한다.
SELECT SUM(SALES)FROM product;

AVG 예제

상품 테이블로부터 모든 제품의 평균 가격을 구하라.

-- 제품의 평균가를 구한다
SELECT AVG(price)FROM product;

그룹 집계

GROUP BY 명령어로 테이블 전체가 아닌 그룹을 대상으로 집계를 내릴 수도 있다.

...테이블 GROUP BY 기준 속성

GROUP BY 예제 (1)

제품 테이블에서 카테고리별로 제품의 개수를 세어보라.

-- 카테고리별로 제품의 개수를 구한다.
SELECT category, COUNT(*)FROM product GROUP BY category;

GROUP BY 예제 (2)

제품 테이블에서 카테고리별로 판매량을 구하라.

-- 카테고리별 제품 판매량
SELECT category, SUM(sales)FROM product GROUP BY category;

마무리

오늘 학습을 마치며

오늘은 SQL을 활용하여 데이터베이스의 기본적인 기능을 학습하였다.

먼저 CREATE TABLE 문을 사용하여 department, student, product 테이블을 직접 생성해보았다. 이 과정에서 기본키(Primary Key), 외래키(Foreign Key), NOT NULL, DEFAULT, CHECK 조건 등의 개념을 익힐 수 있었다.

또한 INSERT 문을 이용해 데이터를 추가하고, SELECT 문으로 원하는 데이터를 조회하는 방법을 연습하였다. WHERE 절을 사용하여 특정 조건의 데이터만 조회할 수 있다는 점도 확인할 수 있었다.

UPDATE 문을 사용해 기존 데이터를 수정하는 방법도 배웠다. 특히 WHERE 절의 중요성을 알게 되었는데, 조건을 작성하지 않으면 모든 데이터가 수정될 수 있다는 점을 이해할 수 있었다.

실습 과정에서 AUTO_INCREMENT, 외래키 제약 조건, Safe Update Mode 등 다양한 오류를 경험했다. 처음에는 오류 메시지가 어렵게 느껴졌지만 원인을 하나씩 찾아 해결하면서 데이터베이스가 데이터를 안전하게 관리하는 이유를 이해할 수 있었다.

이번 학습을 통해 SQL 문법뿐만 아니라 데이터베이스의 구조와 관계를 조금 더 깊게 이해할 수 있었다. 앞으로는 JOIN, 서브쿼리, 정렬 및 집계 함수 등 더 다양한 기능도 학습하며 데이터베이스 활용 능력을 키워나가고 싶다.

0개의 댓글