[DB-001][입문] 표·행·열·키로 관계형 데이터베이스 이해하기
페이지 정보

본문
[이번 수업]
관계형 데이터베이스는 데이터를 표 형태의 관계로 나누고 키를 이용해 서로 연결합니다. 스프레드시트와 비슷해 보이지만 자료형·제약조건·관계를 데이터베이스가 검사한다는 점이 중요합니다. 이번에는 표·행·열·기본키·외래키를 직접 만들어 봅니다.
[선수지식]
CS-001의 값과 자료형, PY-001의 Python 파일 실행법을 알고 있으면 됩니다. SQL 경험이나 별도 데이터베이스 설치는 필요하지 않습니다.
[학습목표]
1. 데이터베이스·테이블·행·열의 관계를 설명할 수 있습니다.
2. 기본키와 외래키의 역할을 구분할 수 있습니다.
3. 두 테이블을 만들고 연결된 데이터를 조회할 수 있습니다.
[핵심개념]
데이터베이스는 일정한 규칙으로 관리되는 데이터 모음이고, DBMS는 이를 저장·조회·변경하는 관리 시스템입니다. PostgreSQL과 SQLite가 DBMS의 예입니다. 관계형 DBMS에서 테이블(table)은 같은 종류의 데이터를 담는 이름 있는 표입니다.
열(column)은 각 데이터가 가진 속성을 정의합니다. users 테이블의 user_id와 name처럼 열마다 이름과 자료형, 허용 규칙이 있습니다. 행(row)은 한 개체의 실제 기록입니다. ‘1, 민수’ 한 줄이 사용자 한 명을 나타냅니다.
기본키(primary key)는 각 행을 유일하게 식별하는 열 또는 열의 조합입니다. 중복되거나 비어서는 안 됩니다. 이름과 이메일은 바뀌거나 중복될 수 있으므로 안정적인 ID를 기본키로 사용하는 경우가 많습니다.
외래키(foreign key)는 다른 테이블의 행을 가리키는 값입니다. notes.user_id가 users.user_id를 참조하면 ‘이 메모의 작성자는 어느 사용자인가’를 표현합니다. 외래키 제약조건은 존재하지 않는 사용자의 메모가 저장되는 일을 막아 참조 무결성, 즉 테이블 사이 관계의 일관성을 지킵니다.
[따라하기]
database_demo.py 파일에 아래 코드를 저장합니다. :memory:는 실행 중에만 존재하는 연습용 데이터베이스입니다.
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("PRAGMA foreign_keys = ON")
db.executescript("""
CREATE TABLE users (
user_id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE notes (
note_id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(user_id),
title TEXT NOT NULL
);
""")
db.execute(
"INSERT INTO users(user_id, name) VALUES (?, ?)",
(1, "민수"),
)
db.execute(
"INSERT INTO notes(note_id, user_id, title) VALUES (?, ?, ?)",
(101, 1, "첫 데이터베이스 학습"),
)
query = """
SELECT users.name, notes.title
FROM notes
JOIN users ON users.user_id = notes.user_id
"""
for name, title in db.execute(query):
print(name, "-", title)
db.close()
Windows에서는 ‘py database_demo.py’, macOS·Linux에서는 ‘python3 database_demo.py’를 실행합니다. ‘민수 - 첫 데이터베이스 학습’이 나오면 notes의 외래키를 따라 users의 이름을 연결한 것입니다.
[흔한 실수]
화면에 보이는 행 번호를 기본키로 착각하지 마세요. 기본키는 테이블 정의에 명시된 데이터입니다. 같은 기본키를 두 번 넣으면 중복 오류가 납니다. 부모인 users 행보다 자식인 notes 행을 먼저 넣으면 외래키 오류가 납니다. SQLite는 호환성 때문에 연결마다 외래키 검사가 기본적으로 꺼질 수 있으므로 예제처럼 PRAGMA foreign_keys = ON을 명시합니다. 또한 SELECT 결과는 ORDER BY 없이는 항상 같은 순서라고 가정하면 안 됩니다.
[보안 주의]
사용자 입력을 문자열 연결로 SQL에 붙이면 SQL 인젝션 위험이 생깁니다. 예제처럼 ? 자리표시자와 별도 값 튜플을 사용하세요. 실습에는 실제 개인정보를 넣지 말고, 운영 데이터베이스는 최소 권한·암호화·정기 백업을 적용합니다.
[직접 해볼 과제]
users에 두 번째 사용자, notes에 그 사용자의 메모를 각각 자리표시자로 추가하세요. 존재하지 않는 user_id 999를 가진 메모를 넣었을 때 어떤 오류가 발생하는지 본인 소유의 메모리 DB에서 확인하고, 외래키가 막아 준 문제를 한 문장으로 설명하세요.
[확인문제]
1. 테이블의 열과 행은 각각 무엇을 나타내나요?
2. 기본키와 외래키는 어떤 차이가 있나요?
3. SQL에 사용자 입력을 문자열로 직접 붙이면 왜 위험한가요?
[다음 학습]
다음 게시 과정은 OS-001 ‘커널·사용자 공간·시스템 호출’입니다. DB 트랙의 다음 단계는 DB-002 ‘SQL 조회·추가·수정·삭제’입니다.
[공식 참고 자료]
PostgreSQL 공식 튜토리얼 — 관계형 데이터 개념
https://www.postgresql.org/docs/current/tutorial-concepts.html
PostgreSQL 공식 문서 — 기본키와 외래키 제약조건
https://www.postgresql.org/docs/current/ddl-constraints.html
Python 공식 sqlite3 문서
https://docs.python.org/3/library/sqlite3.html
SQLite 공식 외래키 문서
https://www.sqlite.org/foreignkeys.html
관계형 데이터베이스는 데이터를 표 형태의 관계로 나누고 키를 이용해 서로 연결합니다. 스프레드시트와 비슷해 보이지만 자료형·제약조건·관계를 데이터베이스가 검사한다는 점이 중요합니다. 이번에는 표·행·열·기본키·외래키를 직접 만들어 봅니다.
[선수지식]
CS-001의 값과 자료형, PY-001의 Python 파일 실행법을 알고 있으면 됩니다. SQL 경험이나 별도 데이터베이스 설치는 필요하지 않습니다.
[학습목표]
1. 데이터베이스·테이블·행·열의 관계를 설명할 수 있습니다.
2. 기본키와 외래키의 역할을 구분할 수 있습니다.
3. 두 테이블을 만들고 연결된 데이터를 조회할 수 있습니다.
[핵심개념]
데이터베이스는 일정한 규칙으로 관리되는 데이터 모음이고, DBMS는 이를 저장·조회·변경하는 관리 시스템입니다. PostgreSQL과 SQLite가 DBMS의 예입니다. 관계형 DBMS에서 테이블(table)은 같은 종류의 데이터를 담는 이름 있는 표입니다.
열(column)은 각 데이터가 가진 속성을 정의합니다. users 테이블의 user_id와 name처럼 열마다 이름과 자료형, 허용 규칙이 있습니다. 행(row)은 한 개체의 실제 기록입니다. ‘1, 민수’ 한 줄이 사용자 한 명을 나타냅니다.
기본키(primary key)는 각 행을 유일하게 식별하는 열 또는 열의 조합입니다. 중복되거나 비어서는 안 됩니다. 이름과 이메일은 바뀌거나 중복될 수 있으므로 안정적인 ID를 기본키로 사용하는 경우가 많습니다.
외래키(foreign key)는 다른 테이블의 행을 가리키는 값입니다. notes.user_id가 users.user_id를 참조하면 ‘이 메모의 작성자는 어느 사용자인가’를 표현합니다. 외래키 제약조건은 존재하지 않는 사용자의 메모가 저장되는 일을 막아 참조 무결성, 즉 테이블 사이 관계의 일관성을 지킵니다.
[따라하기]
database_demo.py 파일에 아래 코드를 저장합니다. :memory:는 실행 중에만 존재하는 연습용 데이터베이스입니다.
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("PRAGMA foreign_keys = ON")
db.executescript("""
CREATE TABLE users (
user_id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE notes (
note_id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(user_id),
title TEXT NOT NULL
);
""")
db.execute(
"INSERT INTO users(user_id, name) VALUES (?, ?)",
(1, "민수"),
)
db.execute(
"INSERT INTO notes(note_id, user_id, title) VALUES (?, ?, ?)",
(101, 1, "첫 데이터베이스 학습"),
)
query = """
SELECT users.name, notes.title
FROM notes
JOIN users ON users.user_id = notes.user_id
"""
for name, title in db.execute(query):
print(name, "-", title)
db.close()
Windows에서는 ‘py database_demo.py’, macOS·Linux에서는 ‘python3 database_demo.py’를 실행합니다. ‘민수 - 첫 데이터베이스 학습’이 나오면 notes의 외래키를 따라 users의 이름을 연결한 것입니다.
[흔한 실수]
화면에 보이는 행 번호를 기본키로 착각하지 마세요. 기본키는 테이블 정의에 명시된 데이터입니다. 같은 기본키를 두 번 넣으면 중복 오류가 납니다. 부모인 users 행보다 자식인 notes 행을 먼저 넣으면 외래키 오류가 납니다. SQLite는 호환성 때문에 연결마다 외래키 검사가 기본적으로 꺼질 수 있으므로 예제처럼 PRAGMA foreign_keys = ON을 명시합니다. 또한 SELECT 결과는 ORDER BY 없이는 항상 같은 순서라고 가정하면 안 됩니다.
[보안 주의]
사용자 입력을 문자열 연결로 SQL에 붙이면 SQL 인젝션 위험이 생깁니다. 예제처럼 ? 자리표시자와 별도 값 튜플을 사용하세요. 실습에는 실제 개인정보를 넣지 말고, 운영 데이터베이스는 최소 권한·암호화·정기 백업을 적용합니다.
[직접 해볼 과제]
users에 두 번째 사용자, notes에 그 사용자의 메모를 각각 자리표시자로 추가하세요. 존재하지 않는 user_id 999를 가진 메모를 넣었을 때 어떤 오류가 발생하는지 본인 소유의 메모리 DB에서 확인하고, 외래키가 막아 준 문제를 한 문장으로 설명하세요.
[확인문제]
1. 테이블의 열과 행은 각각 무엇을 나타내나요?
2. 기본키와 외래키는 어떤 차이가 있나요?
3. SQL에 사용자 입력을 문자열로 직접 붙이면 왜 위험한가요?
[다음 학습]
다음 게시 과정은 OS-001 ‘커널·사용자 공간·시스템 호출’입니다. DB 트랙의 다음 단계는 DB-002 ‘SQL 조회·추가·수정·삭제’입니다.
[공식 참고 자료]
PostgreSQL 공식 튜토리얼 — 관계형 데이터 개념
https://www.postgresql.org/docs/current/tutorial-concepts.html
PostgreSQL 공식 문서 — 기본키와 외래키 제약조건
https://www.postgresql.org/docs/current/ddl-constraints.html
Python 공식 sqlite3 문서
https://docs.python.org/3/library/sqlite3.html
SQLite 공식 외래키 문서
https://www.sqlite.org/foreignkeys.html
- 이전글[OS-001][입문] 커널·사용자 공간·시스템 호출 이해하기 26.08.29
- 다음글[BACK-001][입문] 서버와 HTTP 요청·응답의 구조 26.08.29
댓글목록
등록된 댓글이 없습니다.
