데이터베이스가 파일 저장과 어디서 갈라지는지부터 DBMS와 스키마, 관계형 모델의 구조, 키와 무결성까지 4개 단원을 한 편에 정리했습니다. 이어지는 SQL 완전 가이드와 같은 예제 스키마(members·categories·posts·comments)를 씁니다.
이 글의 순서
데이터베이스란 무엇인가
서비스를 하나 만들면 회원 정보, 글, 댓글처럼 지워지면 안 되는 값들이 곧바로 쌓이기 시작합니다. 이 값들을 어디에 어떻게 둘지 정하는 것이 데이터베이스 공부의 출발점입니다. 이 글에서는 데이터와 정보가 어떻게 다른지, 파일에 그냥 저장하는 방식이 왜 금방 한계에 부딪히는지, 그리고 이 강좌가 12편 내내 쓸 예제 테이블이 무엇인지까지 살펴봅니다.
데이터와 정보는 같은 말이 아닙니다
데이터는 아직 해석되지 않은 원재료입니다. 블로그 글 하나하나에 붙은 조회수 숫자는 데이터입니다. 반면 “지난달 가장 많이 읽힌 분류는 개발 후기였다”처럼 사람이 판단에 쓸 수 있게 가공된 결과는 정보입니다. 데이터베이스가 하는 일은 데이터를 잃어버리지 않게 보관하면서, 필요할 때 정보로 바꿔 낼 통로를 열어 두는 것입니다.
그 통로 역할을 하는 언어가 SQL입니다. 자바로 만들든 파이썬으로 만들든, 프로그램이 저장된 값을 꺼내려면 결국 SQL 문장을 통과해야 합니다. 그래서 언어를 무엇으로 고르든 SQL은 따로 배워 둘 가치가 있습니다.
파일에 저장하면 무엇이 문제인가
회원 명단을 표 계산 파일 하나에 적어 두었다고 해 보겠습니다. 처음에는 잘 굴러갑니다. 문제는 그 파일이 여러 벌로 복제되는 순간부터입니다. 마케팅 담당자가 쓰는 사본과 운영 담당자가 쓰는 사본에 각각 다른 연락처가 적히면, 어느 쪽이 맞는지 아무도 확신하지 못합니다.
두 사람이 같은 파일을 동시에 열어 저장할 때도 곤란해집니다. 나중에 저장한 쪽이 앞사람의 수정을 통째로 덮어써 버립니다. 파일 방식에는 “지금 이 값을 누가 고치는 중이니 잠깐 기다리라”고 정리해 줄 심판이 없기 때문입니다. 이 심판 역할을 맡는 프로그램이 다음 편에서 다룰 DBMS입니다.
데이터베이스가 갖는 네 가지 성격
어떤 저장소를 데이터베이스라고 부르려면 다음 네 가지를 모두 갖춰야 합니다.
| 성격 | 의미 |
|---|---|
| 통합 | 같은 값을 여러 곳에 중복해 두지 않아, 값이 서로 어긋날 여지를 줄입니다. |
| 저장 | 사람이 넘겨 보는 서류가 아니라, 컴퓨터가 읽을 수 있는 저장 장치에 담깁니다. |
| 운영 | 보관 자체가 목적이 아니라, 그 조직이 실제 업무를 굴리는 데 쓰입니다. |
| 공용 | 한 사람이 아니라 여러 사용자와 여러 프로그램이 같이 씁니다. |
네 번째 성격이 특히 부담이 큽니다. 여럿이 동시에 쓰기 때문에 요청이 겹칠 때 순서를 정해 주어야 하고, 처리 도중 문제가 생기면 중간까지 반영된 값을 되돌려 놓아야 합니다. 요청이 들어오는 즉시 응답하는 실시간 처리와, 하루치를 모아 새벽에 한 번에 돌리는 일괄 처리를 업무 성격에 따라 섞어 쓰는 것도 이 부담을 나누기 위해서입니다.
무결성 — 데이터베이스가 지키는 약속
무결성은 저장된 값이 규칙을 어기지 않은 상태를 뜻합니다. 회원 번호가 겹치지 않는다든지, 존재하지 않는 회원이 쓴 글이 남아 있지 않다든지 하는 것들입니다. 데이터베이스는 이런 규칙을 미리 등록해 두고, 규칙을 깨는 저장 요청은 아예 거절합니다.
거절해 주는 쪽이 훨씬 안전합니다. 프로그램 쪽 검사에만 의존하면 화면이 늘어날 때마다 같은 검사를 반복해 넣어야 하고, 한 군데만 빠뜨려도 이상한 값이 들어갑니다. 규칙을 데이터가 사는 곳에 직접 걸어 두는 방법은 키와 무결성 편에서 자세히 다룹니다.
참고로 같은 데이터베이스라도 사람마다 닿는 깊이가 다릅니다. 일반 사용자는 화면만 보고, 응용 프로그래머는 그 화면 뒤에서 SQL을 가장 많이 작성하며, 관리자는 계정과 권한, 백업과 성능처럼 서비스 전체가 걸린 문제를 맡습니다. 입문자가 처음 서는 자리는 두 번째이므로 이 강좌도 조회와 조작 쪽에 무게를 둡니다.
이 강좌에서 함께 쓸 예제 테이블
설명만 이어지면 지루하니 12편 내내 같은 예제를 씁니다. 카드뉴스 블로그를 운영한다고 가정하고 회원과 글, 분류, 댓글을 담는 네 개의 표를 쓰겠습니다.
members 회원 member_id, nickname, email, grade, joined_on, invited_by
categories 분류 category_id, category_name, sort_order
posts 글 post_id, title, member_id, category_id, view_count, reward_rate, published_on
comments 댓글 comment_id, post_id, member_id, body, created_on
글은 회원이 쓰고 댓글은 글에 달립니다. posts의 member_id가 members를 가리키는 식으로 표끼리 서로를 참조하는 구조가 관계형 데이터베이스의 핵심이며, 관계형 모델의 구조 편에서 본격적으로 뜯어봅니다.
핵심 정리
- 데이터와 정보 — 데이터는 원재료, 정보는 판단에 쓸 수 있게 가공된 결과입니다.
- 파일 방식의 한계 — 사본이 늘면 값이 어긋나고, 동시 수정 시 앞사람 작업이 사라집니다.
- 네 가지 성격 — 통합·저장·운영·공용을 모두 만족해야 데이터베이스입니다.
- 무결성 — 규칙을 데이터가 사는 곳에 걸어 두면 프로그램이 늘어나도 안전합니다.
- 예제 스키마 — 이 강좌는 members·categories·posts·comments 네 표로 진행합니다.
DBMS와 스키마
앞 편에서 여러 사람이 같은 데이터를 동시에 쓰려면 심판이 필요하다고 했습니다. 그 심판이 DBMS입니다. 이 글에서는 DBMS가 우리를 대신해 처리해 주는 일이 무엇인지, 그리고 데이터의 생김새를 적어 둔 설계도인 스키마가 어떤 층으로 나뉘는지 정리합니다.
DBMS가 대신 해 주는 일
DBMS는 데이터베이스 관리 시스템의 줄임말입니다. 우리가 파일을 직접 열고 닫는 대신, 요청을 받아 처리해 주는 프로그램이라고 보면 됩니다. 흔히 데이터베이스라고 부르는 오라클, MySQL, PostgreSQL은 정확히 말하면 모두 DBMS입니다.
DBMS가 떠맡는 일은 크게 네 가지입니다. 여러 요청이 겹칠 때 순서를 정해 주는 동시성 제어, 처리 도중 문제가 생겼을 때 중간까지 반영된 값을 되돌리는 복구, 규칙을 어기는 저장을 막는 무결성 검사, 그리고 누가 무엇까지 볼 수 있는지 가르는 권한 관리입니다.
이 네 가지를 직접 구현해 본 적이 있다면 DBMS를 쓰는 이유를 금방 납득하게 됩니다. 특히 복구는 혼자 만들기가 대단히 까다롭습니다. 저장하는 도중 전원이 나갔을 때 어디까지 반영됐는지 판단하고 나머지를 되돌리려면, 실제 값과 별도로 변경 이력을 따로 적어 두어야 하기 때문입니다.
그래서 데이터베이스라는 말은 문맥에 따라 두 가지를 가리킵니다. 저장된 데이터 뭉치 자체를 뜻할 때도 있고, 그것을 관리하는 프로그램을 뜻할 때도 있습니다. 데이터와 DBMS, 그리고 이를 쓰는 사용자와 응용 프로그램까지 묶어 부를 때는 데이터베이스 시스템이라고 합니다.
스키마 — 데이터를 설명하는 데이터
스키마는 어떤 표가 있고 각 표에 어떤 칸이 있으며 그 칸에 어떤 값이 들어갈 수 있는지를 적어 둔 설계도입니다. 실제 값이 아니라 값의 생김새를 적은 것이므로 데이터를 설명하는 데이터, 즉 메타데이터에 해당합니다.
중요한 점은 스키마가 자주 바뀌지 않는다는 것입니다. 회원이 하루에 백 명씩 늘어도 members 표의 구조는 그대로입니다. 반대로 스키마를 바꾸는 일은 이미 쌓인 값 전체에 영향을 주므로 신중해야 합니다. 칸 하나를 지우는 명령 한 줄이 수십만 줄의 값을 함께 지웁니다.
설계를 문서로 그릴 때는 개체 관계 모델을 자주 씁니다. 회원과 글처럼 관리 대상이 되는 것을 네모로 그리고, 그 사이의 관계를 선으로 잇는 방식입니다. 이 그림을 그대로 표로 옮기면 스키마가 됩니다. 그림 단계에서 빠뜨린 관계는 표를 다 만든 뒤에 발견되므로, 코드를 쓰기 전에 그려 보는 습관이 시간을 아껴 줍니다.
스키마는 세 층으로 나뉩니다
같은 데이터라도 보는 사람에 따라 필요한 모습이 다릅니다. 그래서 스키마를 세 층으로 나눠 생각합니다.
| 층 | 누가 보는가 | 예 |
|---|---|---|
| 외부 스키마 | 사용자·응용 프로그램 | 글쓴이 화면에는 자기 글 목록만 보입니다 |
| 개념 스키마 | 조직 전체 | 회원·글·분류·댓글 네 표와 그 관계 전부 |
| 내부 스키마 | DBMS·관리자 | 어느 파일에 어떤 순서로 적히고 어떤 색인을 두는가 |
이렇게 나누면 내부 저장 방식을 바꿔도 위층이 흔들리지 않습니다. 색인을 새로 하나 만들었다고 해서 이미 만들어 둔 화면을 고칠 필요가 없다는 뜻입니다. 이 성질을 데이터 독립성이라고 부릅니다.
데이터 딕셔너리 — DBMS가 스스로 적어 두는 장부
스키마 정보는 DBMS가 자기 안에 표 형태로 보관합니다. 이 장부를 데이터 딕셔너리라고 합니다. 사용자가 손으로 고칠 수는 없고, 표를 만들거나 바꿀 때 DBMS가 알아서 갱신합니다.
딕셔너리는 조회 범위에 따라 이름 앞머리가 갈립니다. 다음은 오라클의 표기입니다.
-- 오라클
SELECT table_name FROM user_tables; -- 내가 만든 것만
SELECT table_name FROM all_tables; -- 내가 볼 권한이 있는 것
SELECT table_name FROM dba_tables; -- 데이터베이스 전체 (관리자 전용)
-- MySQL / PostgreSQL 은 표준 뷰를 씁니다
SELECT table_name FROM information_schema.tables;
같은 목적의 조회라도 제품마다 이름이 다릅니다. 이런 차이는 앞으로도 계속 나오므로, 문법이 하나로 통일돼 있다고 기대하지 않는 편이 마음이 편합니다.
어떤 DBMS로 연습할까
이 강좌의 예제는 표준 SQL을 기준으로 씁니다. 표준만 쓰면 오라클, MySQL, PostgreSQL 어디에 붙여 넣어도 대체로 그대로 돌아가기 때문입니다. 제품마다 갈리는 부분이 나오면 그때그때 따로 표시해 두겠습니다.
연습 환경으로는 설치가 가장 가벼운 MySQL이나 PostgreSQL을 권합니다. 국내 업무 환경에서 오라클을 만날 일이 많기는 하지만, 문법의 뼈대는 어느 쪽으로 배워도 같습니다. 이제 관계형 모델의 구조로 넘어가 표 한 장이 어떤 규칙으로 이루어지는지 보겠습니다.
핵심 정리
- DBMS — 동시성 제어·복구·무결성·권한을 대신 처리해 주는 프로그램입니다.
- 스키마 — 값이 아니라 값의 생김새를 적은 설계도, 곧 메타데이터입니다.
- 3층 구조 — 외부·개념·내부로 나눠 두면 저장 방식을 바꿔도 화면이 안 흔들립니다.
- 데이터 딕셔너리 — DBMS가 스스로 관리하는 스키마 장부입니다.
- 제품 차이 — 표준 SQL을 기준으로 배우고 제품 고유 문법은 따로 익힙니다.
관계형 모델의 구조
관계형 데이터베이스에서 데이터가 담기는 그릇은 결국 표 한 장입니다. 그런데 아무 표나 되는 것은 아니고, 지켜야 할 규칙이 몇 가지 있습니다. 이 글에서는 그 표를 부르는 정식 이름인 릴레이션의 구조와 규칙, 그리고 값이 없는 상태를 뜻하는 NULL을 살펴봅니다.
릴레이션이라는 이름의 표
릴레이션은 행과 열로 이루어진 표입니다. 실무에서는 그냥 테이블이라고 부르는 일이 훨씬 많지만, 이론을 설명할 때는 릴레이션이라는 말을 씁니다. 관계형 모델, 관계형 데이터베이스, 관계 대수 같은 용어가 모두 여기서 나왔습니다.
같은 대상을 가리키는 말이 여럿이라 헷갈리기 쉬우니 한 번 정리하고 가겠습니다.
| 이론 용어 | 실무에서 부르는 말 | 뜻 |
|---|---|---|
| 릴레이션 | 테이블 | 표 한 장 |
| 속성 | 컬럼, 필드 | 표의 세로 한 칸 |
| 투플 | 로우, 행, 레코드 | 표의 가로 한 줄 |
| 도메인 | 자료형과 허용 범위 | 그 칸에 들어갈 수 있는 값의 집합 |
스키마와 인스턴스는 다릅니다
릴레이션 스키마는 표의 머리글, 즉 어떤 속성들로 이루어져 있는가입니다. 릴레이션 인스턴스는 그 안에 실제로 들어 있는 값들입니다. 스키마는 좀처럼 변하지 않고 인스턴스는 매 순간 변합니다.
-- 스키마 표기 : 릴레이션이름(속성:도메인, ...)
posts(post_id:INT, title:VARCHAR(200), member_id:INT,
view_count:INT, published_on:DATE)
-- 인스턴스 : 지금 이 순간 담겨 있는 투플들
101 | 카드뉴스 만드는 법 | 3 | 1520 | 2026-03-04
102 | 파이썬 첫걸음 | 7 | 340 | 2026-03-09
속성의 개수를 차수라고 하고, 투플의 개수를 카디널리티라고 합니다. 위 예에서 차수는 5, 카디널리티는 2입니다. 차수는 설계가 바뀌어야 달라지지만 카디널리티는 글이 하나 올라올 때마다 달라집니다.
도메인도 함께 봐 두면 좋습니다. 도메인은 그 칸에 들어올 수 있는 값의 범위입니다. view_count의 도메인은 0 이상의 정수이고, grade의 도메인은 BASIC과 PLUS와 PRO 세 값뿐입니다. 자료형만으로는 이 범위를 다 표현하지 못하기 때문에, 나머지는 제약조건으로 따로 걸어 둡니다.
릴레이션이 지키는 규칙
표처럼 생겼다고 전부 릴레이션인 것은 아닙니다. 다음 규칙을 지켜야 합니다.
- 한 칸에는 값이 하나만 들어갑니다. 취미 세 가지를 한 칸에 몰아 적으면 안 됩니다.
- 한 표 안에서 속성 이름은 서로 달라야 합니다.
- 한 속성의 값은 모두 같은 도메인에 속합니다. 숫자 칸에 문자열이 섞이면 안 됩니다.
- 속성의 좌우 순서는 의미가 없습니다. 순서를 바꿔 적어도 같은 스키마입니다.
- 완전히 똑같은 투플이 두 줄 있으면 안 됩니다.
- 투플의 위아래 순서도 의미가 없습니다. 원하는 순서로 보려면 조회할 때 정렬을 지정해야 합니다.
마지막 두 규칙이 특히 자주 발목을 잡습니다. 저장한 순서대로 나오리라 기대하고 코드를 짜면, 데이터가 늘어난 어느 날 갑자기 순서가 뒤집혀 있습니다. 정렬이 필요하면 정렬과 별칭 편에서 다룰 ORDER BY를 반드시 적어야 합니다.
관계는 두 방향으로 생깁니다
관계형이라는 이름이 붙은 이유는 값들이 서로 관계를 맺기 때문입니다. 관계는 두 방향으로 생깁니다.
관계는 몇 대 몇으로 이어지는지에 따라 성격이 달라집니다. 회원 한 명이 글을 여럿 쓰므로 회원과 글은 일대다입니다. 회원과 프로필 사진처럼 한쪽에 하나씩만 붙으면 일대일이고, 글과 태그처럼 양쪽 모두 여럿일 수 있으면 다대다입니다. 다대다는 표 두 개만으로는 표현할 수 없어서 가운데에 연결용 표를 하나 더 두는 것이 보통입니다.
하나는 표 안에서 생기는 관계입니다. posts의 한 줄에서 제목과 조회수와 작성일은 같은 글에 대한 값이라는 점으로 묶여 있습니다. 다른 하나는 표와 표 사이의 관계입니다. posts.member_id가 members.member_id를 가리키는 것이 그렇습니다. 이 두 번째 관계를 다루는 도구가 외래키와 조인이며, 각각 키와 무결성과 테이블 연결하기 편에서 다룹니다.
NULL — 값이 없다는 상태
칸은 마련해 두었지만 아직 값을 넣지 않은 상태를 NULL이라고 합니다. 숫자 0이나 빈 문자열과는 다릅니다. 0은 “0이라는 값이 있다”는 뜻이지만 NULL은 “값이 무엇인지 모른다”는 뜻입니다.
이 차이 때문에 NULL은 계산과 비교에서 특이하게 굴러갑니다. NULL이 섞인 덧셈 결과는 NULL이 되고, 등호로 비교해도 참이 되지 않습니다. 예제 스키마에서는 posts.reward_rate가 NULL을 허용하는 칸입니다. 제휴 수익이 걸리지 않은 글에는 값이 없기 때문입니다. NULL을 다루는 구체적인 방법은 원하는 행만 남기기 편에서 이어집니다.
핵심 정리
- 릴레이션 — 행과 열로 이루어진 표, 실무에서는 테이블이라고 부릅니다.
- 차수와 카디널리티 — 속성 개수와 투플 개수를 가리킵니다.
- 순서는 무의미 — 속성과 투플 모두 순서에 뜻이 없어, 정렬은 조회할 때 지정합니다.
- 두 방향의 관계 — 표 안에서, 그리고 표와 표 사이에서 관계가 생깁니다.
- NULL — 0이나 빈 문자열이 아니라 값을 모른다는 상태입니다.
키와 무결성
표에 값이 쌓이기 시작하면 곧 한 가지 질문에 부딪힙니다. 이 많은 줄 가운데 특정한 한 줄을 어떻게 콕 집어낼 것인가. 답이 키입니다. 이 글에서는 키의 종류를 정리하고, 키를 이용해 잘못된 값이 들어오지 못하게 막는 제약조건을 살펴봅니다.
왜 키가 필요한가
회원 표에서 닉네임으로 한 사람을 찾는다고 해 보겠습니다. 닉네임은 바뀔 수 있고, 운이 나쁘면 겹칠 수도 있습니다. 이런 값을 기준으로 삼으면 어느 날 엉뚱한 회원의 글이 다른 사람에게 붙습니다.
그래서 각 줄을 구분하는 전용 값을 따로 둡니다. 이 값이 키입니다. 키는 절대 겹치지 않아야 하고, 한 번 정해지면 바뀌지 않아야 하며, 비어 있어서도 안 됩니다.
키의 종류
이름이 비슷비슷해서 헷갈리기 쉬우니 표로 정리하겠습니다. members 표에 회원번호와 이메일이 있고 둘 다 겹치지 않는다고 가정합니다.
| 이름 | 뜻 | 예 |
|---|---|---|
| 슈퍼키 | 줄을 구분할 수만 있으면 되고, 불필요한 칸이 섞여도 상관없음 | (member_id, nickname) |
| 후보키 | 슈퍼키 중에서 군더더기를 모두 뺀 것 | member_id, email |
| 기본키 | 후보키 중 대표로 고른 하나 | member_id |
| 대체키 | 후보키 중 기본키로 뽑히지 않은 나머지 | |
| 외래키 | 다른 표의 기본키를 가리키는 칸 | posts.member_id |
기본키를 고를 때는 짧고 바뀌지 않는 값을 고릅니다. 이메일도 후보키이긴 하지만 회원이 바꿀 수 있고 길이도 길어서 대표로 삼기에는 불리합니다. 잘 설계된 표는 기본키가 하나씩 뚜렷하게 잡혀 있습니다.
외래키와 참조 무결성
외래키는 다른 표를 가리키는 손가락입니다. posts.member_id에는 members에 실제로 있는 회원번호만 들어갈 수 있습니다. 없는 회원번호를 넣으려 하면 데이터베이스가 거절합니다. 이 규칙을 참조 무결성이라고 합니다.
-- members 에 없는 999번 회원으로 글을 넣으려 하면
INSERT INTO posts (post_id, title, member_id)
VALUES (301, '첫 글', 999);
-- 참조 무결성 위반으로 거절됩니다
반대 방향도 막힙니다. 글이 걸려 있는 회원을 지우려 하면 그 삭제도 거절됩니다. 지우고 싶다면 글을 먼저 정리하거나, 표를 만들 때 함께 지우도록 지정해 두어야 합니다.
제약조건 — 규칙을 표에 직접 걸어 두기
키 말고도 걸 수 있는 규칙이 몇 가지 더 있습니다. 이런 규칙을 통틀어 제약조건이라고 부릅니다.
CREATE TABLE members (
member_id INT PRIMARY KEY,
nickname VARCHAR(30) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
grade VARCHAR(10) DEFAULT 'BASIC',
joined_on DATE NOT NULL,
invited_by INT,
CONSTRAINT members_grade_ck
CHECK (grade IN ('BASIC', 'PLUS', 'PRO')),
CONSTRAINT members_invited_fk
FOREIGN KEY (invited_by) REFERENCES members(member_id)
);
NOT NULL은 비워 둘 수 없게 하고, UNIQUE는 겹치지 못하게 하며, CHECK는 허용된 값만 받게 합니다. DEFAULT는 값을 안 주면 대신 채워 넣을 값입니다. 마지막 invited_by는 같은 표의 회원번호를 가리키는 외래키인데, 자기 자신을 참조하는 이런 구조가 나중에 셀프 조인의 재료가 됩니다.
제약조건에 이름을 붙일 때는 표이름_칸이름_종류 형태를 쓰면 편합니다. 오류 메시지에 제약조건 이름이 그대로 찍히기 때문에, 어디서 걸렸는지 바로 알 수 있습니다.
정규화 — 중복을 덜어내는 작업
한 표에 모든 것을 몰아넣으면 이상한 일이 생깁니다. 분류 이름을 posts 안에 문자열로 직접 적어 두면, 분류 이름을 고칠 때 글 수천 개를 전부 고쳐야 합니다. 하나라도 놓치면 같은 분류가 두 이름으로 갈라집니다. 이런 문제를 이상 현상이라고 합니다.
정규화는 표를 쪼개어 이런 중복을 덜어내는 작업입니다. 분류를 categories로 떼어 내고 posts에는 번호만 남기면, 이름을 고칠 자리는 한 곳뿐이 됩니다. 다만 쪼갤수록 조회할 때 표를 다시 이어 붙여야 해서 조회 부담은 늘어납니다. 그래서 조회가 압도적으로 많은 곳에서는 일부러 중복을 남기기도 하는데, 이를 역정규화라고 합니다. 무결성과 속도를 저울질하는 선택입니다.
핵심 정리
- 기본키 — 짧고 바뀌지 않는 값을 골라 각 줄의 대표 식별자로 씁니다.
- 외래키 — 다른 표의 기본키를 가리키며, 없는 값은 애초에 들어가지 못합니다.
- 제약조건 — NOT NULL·UNIQUE·CHECK·DEFAULT로 규칙을 표에 직접 걸어 둡니다.
- 이상 현상 — 중복이 남아 있으면 수정·삽입·삭제에서 값이 어긋납니다.
- 정규화와 역정규화 — 무결성과 조회 속도를 저울질하는 설계 선택입니다.
“데이터베이스 기초 완전 가이드 — 개념부터 관계형 모델과 무결성까지”에 대한 1개의 생각