관계형 데이터베이스는 데이터를 테이블(표)에 담고, 테이블은 이름이 붙은 열과 그 열을 채운 행으로 이뤄집니다. 테이블에 어떤 열이 어떤 타입으로 있는지 적은 설계도를 스키마라고 부르죠. 저도 SQL 을 처음 배우면서 「테이블은 그냥 엑셀 시트 아닌가?」 싶었는데요, 이번 글에서는 테이블·행·열·스키마가 각각 무엇이고 엑셀 시트와 어디가 다른지 회원 표 하나로 함께 알아보겠습니다. 지난 글: 데이터베이스란? 엑셀 시트와 무엇이 다를까
SQL 기초 시리즈 1/12 · 전체 커리큘럼
오늘 배울 개념
PostgreSQL 튜토리얼은 관계형 데이터베이스 관리 시스템을 「릴레이션에 저장된 데이터를 관리하는 시스템」이라고 설명하고, 릴레이션은 테이블을 가리키는 수학 용어라고 덧붙입니다. 같은 문서에 따르면 테이블은 이름이 있는 행의 모음이고, 한 테이블의 행은 모두 같은 이름의 열을 가지며, 열마다 데이터 타입이 정해져 있는데요, 엑셀로 바꿔 보면 이렇게 대응됩니다.
| 관계형 모델 용어 | SQL 에서 흔히 쓰는 말 | 엑셀로 치면 |
|---|---|---|
| 릴레이션(relation) | 테이블(table), 표 | 시트 한 장의 표 |
| 튜플(tuple) | 행(row), 레코드(record) | 줄 하나 |
| 속성(attribute) | 열(column), 컬럼 | 열 하나(머리글 포함) |
| - | 스키마(schema) | 머리글 줄과 「이 열엔 날짜만」 같은 약속 |
PostgreSQL 용어집은 속성을 「이름과 데이터 타입이 있는 요소」로, 튜플을 「정해진 순서로 놓인 속성의 묶음」으로 정의하고, 테이블 안의 튜플을 흔히 행이라고 부른다고 적고 있습니다. 비유를 하나 들면 스키마는 빈 주문서 양식이고, 행은 그 양식을 한 장씩 채운 주문서입니다. 양식에 칸이 정해져 있으니 누가 채워도 같은 칸에 같은 종류의 값이 들어가죠.
예시로 이해하기
작은 온라인 문구점의 회원 테이블 members 를 놓고 보겠습니다(가상 데이터).
| member_id | name | joined_on | city |
|---|---|---|---|
| 1 | 김하늘 | 2026-09-03 | 서울 |
| 2 | 이도윤 | 2026-09-10 | 부산 |
| 3 | 박서연 | 2026-09-21 | 서울 |
| 4 | 최지우 | 2026-10-02 | 대전 |
| 5 | 정민준 | 2026-10-15 | 광주 |
- 테이블: 이름이
members인 표 하나입니다. - 열:
member_id,name,joined_on,city네 개입니다. PostgreSQL 테이블 기초 문서는 열의 개수와 순서가 고정돼 있고 열마다 이름이 있다고 설명합니다. - 행: 회원 한 명이 한 행이고 지금은 다섯 개인데요, 같은 문서는 행의 개수는 그때그때 저장된 데이터 양에 따라 달라진다고 합니다. 회원이 가입하면 행이 늘어나지만 열은 그대로죠.
- 값: 행과 열이 만나는 칸 하나입니다. 「이도윤」은
member_id가 2인 행의name열 값이죠.
개념 그림: 열은 세로로 이름과 타입을, 행은 가로로 회원 한 명을 담습니다
이 테이블의 스키마는 SQL 로 이렇게 적습니다. 문법은 6회부터 배우니 지금은 「표 이름, 열 이름, 열의 타입을 적는 문장」이라는 것만 보시면 됩니다.
CREATE TABLE members (
member_id INTEGER, -- 정수
name VARCHAR(50), -- 최대 50자 문자
joined_on DATE, -- 날짜
city VARCHAR(20)
);PostgreSQL 문서에 따르면 CREATE TABLE 에는 최소한 테이블 이름, 열 이름, 열마다의 데이터 타입을 적고, 숫자 타입으로 정한 열에는 아무 문자열이나 들어가지 않습니다.
그래서 member_id 에 「일번」 같은 글자를 넣으려 하면 PostgreSQL 은 받아들이지 않는데요, 엑셀 시트라면 그 칸에 그냥 적혔을 겁니다.
개념 그림: 스키마는 칸이 정해진 양식, 행은 그 양식을 채운 한 장입니다
엑셀 시트와 테이블은 무엇이 다를까요?
모양은 비슷해도 지키는 약속이 다릅니다.
| 기준 | 엑셀 시트 | 관계형 테이블 |
|---|---|---|
| 위치를 가리키는 법 | 셀 주소(B3)로 칸의 위치를 가리킴 | 테이블 이름과 열 이름으로 가리킴 |
| 열 | 머리글은 선택, 아무 칸에나 값을 적을 수 있음 | 열 개수·순서 고정, 열마다 이름이 있음 |
| 값의 종류 | 한 열에 숫자·글자가 섞일 수 있음, 데이터 유효성 검사로 제한 가능 | 열마다 데이터 타입이 정해짐 |
| 행 순서 | 줄 번호가 곧 순서 | 순서를 보장하지 않음, 보고 싶은 순서는 조회할 때 요청 |
| 똑같은 행 | 얼마든지 적을 수 있음 | 기본으로는 똑같은 행도 들어갈 수 있음 |
마지막 두 줄은 처음에 의외였는데요, PostgreSQL 문서는 SQL 이 테이블 안 행의 순서를 보장하지 않아서 정렬을 따로 요청하지 않으면 행이 정해지지 않은 순서로 나온다고 설명합니다. 또 SQL 은 행마다 고유한 번호를 붙여 주지 않아서 완전히 똑같은 행이 여러 개 있을 수 있고, 보통은 바라지 않는 상태라고 덧붙이죠. 이 문제를 막는 방법이 다음 글의 기본 키입니다.
엑셀에도 「표」 기능이 있어서 헷갈리기 쉬운데요, 엑셀 표 도움말에 따르면 엑셀 표는 기본으로 머리글 행이 있고, 수식을 셀 하나에 넣으면 열 전체에 적용되는 계산된 열, 셀 주소 대신 표 이름으로 가리키는 구조적 참조를 쓸 수 있습니다. 셀 주소 대신 이름으로 가리킨다는 점은 데이터베이스 테이블과 닮았지만, 열의 값 종류를 막는 일은 유효성 검사를 따로 걸어야 한다는 점이 다릅니다.
엑셀 시트를 테이블로 옮긴다면 무엇부터 정할까요?
실무에서 쓰던 주간 광고 성과 시트를 언젠가 데이터베이스로 옮긴다고 상상해 보면, 저는 SQL 을 쓰기 전에 아래 네 가지를 먼저 적어 보려고 합니다.
- 한 행이 무엇 하나인지: 「캠페인 하루치 성과 한 건」처럼 한 문장으로 말할 수 있어야 열을 고를 수 있습니다. 시트 아래에 붙인 합계 줄은 이 문장에 맞지 않으니 테이블에 넣지 않습니다.
- 열 이름: PostgreSQL 문서에 따르면 이름은 글자나 밑줄로 시작하고, 띄어쓰기 같은 문자를 쓰려면 큰따옴표로 감싸야 합니다. 그래서 저는
ad_cost처럼 영문 소문자와 밑줄로 지으려고 합니다. - 열마다 타입: 날짜는 날짜, 비용은 숫자로 정해 둡니다. 「1만2천」 같은 글자가 섞여 있던 칸은 옮기기 전에 숫자로 바꿔야 하죠.
- 표를 나눌 곳: 캠페인 이름과 담당자가 행마다 반복된다면 따로 뺄 후보입니다. 나누는 기준은 3회 정규화에서 다룹니다.
개념 그림: PostgreSQL 에서는 데이터베이스 안에 스키마, 스키마 안에 테이블이 들어갑니다
여기서 한 가지 짚어 둘 것이 있는데요, 「스키마」는 두 가지 뜻으로 쓰입니다. PostgreSQL 용어집은 넓은 뜻의 스키마를 테이블 정의·제약 조건 같은 데이터 설명 전체로 설명하면서, 좁은 뜻으로는 같은 데이터베이스 안에서 테이블 같은 객체를 묶는 이름 공간이라고 적고 있습니다. PostgreSQL 스키마 문서는 이 이름 공간을 운영체제의 폴더에 비유하는데, 폴더와 달리 스키마 안에 스키마를 다시 넣을 수는 없다고 합니다. 같은 스키마 안에서는 테이블 이름이 겹치면 안 되지만, 스키마가 다르면 같은 이름의 테이블을 함께 둘 수 있죠. 이 글에서 말한 스키마는 넓은 뜻, 즉 설계도입니다.
연습 문제
1. (쉬움) 위 members 테이블의 행과 열은 각각 몇 개인가요? 「부산」은 어느 행, 어느 열의 값인가요?
정답 보기
행 5개, 열 4개입니다. 「부산」은 member_id 가 2인 행(이도윤 님)의 city 열 값입니다. 행은 회원 한 명, 열은 회원의 속성 하나라고 보면 쉽죠.
2. (보통) 엑셀에 「주문번호 · 주문일 · 상품명 · 수량 · 금액」 머리글로 주문을 쌓아 왔습니다. 이 시트를 orders 테이블로 옮긴다면 스키마를 어떻게 적을까요? 열 이름과 타입만 정해 보세요.
정답 보기
예시 답안입니다. order_id INTEGER, ordered_on DATE, product_name VARCHAR(100), quantity INTEGER, amount INTEGER. 금액에 소수점이 필요하면 NUMERIC 같은 소수 타입을 고릅니다. 열 이름은 띄어쓰기 없이 영문 소문자와 밑줄로 지었고, 데이터 타입은 4회에서 자세히 다룹니다.
3. (보통) 다음 중 엑셀 시트에서는 되지만 관계형 테이블에서는 할 수 없는 것을 모두 고르세요. (가) 한 열에 날짜와 「확인 필요」 메모를 섞어 적기 (나) 특정 행에만 열을 하나 더 쓰기 (다) 같은 이름의 회원을 두 번 적기
정답 보기
(가)와 (나)입니다. 테이블은 열마다 타입이 정해져 있어 날짜 열에 메모 글자를 넣을 수 없고, 열 개수가 고정돼 있어 한 행만 열을 늘릴 수 없습니다. (다)는 테이블에서도 되는데요, SQL 은 기본으로 똑같은 행도 막지 않기 때문입니다. 이를 막으려면 다음 글의 기본 키가 필요하죠.
헷갈리기 쉬운 것
- 스키마는 제품마다 가리키는 범위가 다릅니다: 이 글의 넓은 뜻(설계도) 말고도 PostgreSQL 에서는 데이터베이스 안의 이름 공간을 뜻하고, MySQL 용어집은 MySQL 에서 물리적으로 스키마가 데이터베이스와 같은 말이라고 설명합니다. 문서를 읽을 때 어느 뜻인지 먼저 보시길 권합니다.
- 열 타입을 지키는 정도도 제품마다 다릅니다: SQLite 문서는 대부분의 SQL 데이터베이스가 열에 따라 값의 타입이 정해지는 엄격한 방식을 쓰지만 SQLite 는 값마다 타입이 붙는 유연한 방식을 쓴다고 밝힙니다. 3.37.0 부터는 엄격하게 검사하는 STRICT 테이블도 고를 수 있다고 하죠.
- 열 순서와 행 순서는 다릅니다: 열은 정해진 순서가 있지만, 행은 순서를 보장받지 못합니다. 원하는 순서로 보는 방법은 8회에서 다룹니다.
마치며
관계형 데이터베이스는 데이터를 테이블에 담고, 테이블은 이름과 타입이 정해진 열, 그 열을 채운 행으로 이뤄지며, 이 구조를 적은 설계도가 스키마입니다. 엑셀 시트와 모양은 닮았지만 열 개수와 타입을 미리 정하고 행 순서를 기대하지 않는다는 점이 다르니, 시트를 볼 때 「한 행은 무엇 하나인가」부터 떠올려 보시면 감이 빨리 잡힐 겁니다. 저도 시리즈를 따라가며 하나씩 공부해 보려고 하니 전체 커리큘럼을 참고해 주세요. 다음 글에서는 표와 표를 잇는 기본 키와 외래 키를 다룹니다.
자주 묻는 질문
- 관계형 데이터베이스의 기본 구조는 무엇인가요?
- 데이터를 테이블에 담고, 테이블은 열과 행으로 이뤄집니다. PostgreSQL 튜토리얼은 테이블을 이름 있는 행의 모음으로, 한 테이블의 행은 모두 같은 이름의 열을 가지며 열마다 데이터 타입이 정해져 있다고 설명합니다. 테이블에 어떤 열이 어떤 타입으로 있는지 적은 것이 스키마입니다.
- 스키마란 무엇인가요?
- 넓게는 테이블 정의와 제약 조건 같은 데이터 구조의 설명 전체를 뜻합니다. PostgreSQL 에서는 데이터베이스 안에서 테이블 같은 객체를 묶는 이름 공간을 가리키기도 하고, MySQL 에서는 데이터베이스와 같은 말로 씁니다.
- 엑셀 테이블(표)과 데이터베이스 테이블은 같은 건가요?
- 닮은 점은 있지만 같지 않습니다. 엑셀 표도 머리글 행과 표 이름으로 가리키는 구조적 참조를 쓸 수 있지만, 열의 값 종류를 막으려면 유효성 검사를 따로 걸어야 합니다. 데이터베이스 테이블은 열마다 데이터 타입을 정해 두고 열 개수와 순서가 고정돼 있습니다.
관련 글 더 보기
- 데이터베이스란? 엑셀 시트와 무엇이 다를까 - SQL 기초 시리즈 0회, 데이터베이스와 DBMS
- 엑셀 피벗테이블이란? 뜻부터 만들기·새로고침까지 실무 활용법 - 머리글이 있는 표를 기준별로 요약하는 방법
- 엑셀 숫자 인식 안됨 | 텍스트로 저장된 숫자를 숫자로 바꾸는 법 - 숫자 칸에 글자가 섞일 때 생기는 문제
