1. ORM์ด๋? ๐ค
ORM (Object-Relational Mapping) ์ ํต์ฌ ๊ฐ๋
ORM์ ๊ฐ์ฒด-๊ด๊ณ ๋งคํ ์ ์ฝ์๋ก, ํ์ด์ฌ์ ๊ฐ์ฒด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ์ ์๋์ผ๋ก ์ฐ๊ฒฐํด์ฃผ๋ ๊ธฐ์ ์ ๋๋ค!
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ Python ์ธ๊ณ (๊ฐ์ฒด ์งํฅ) โ
โ โ
โ class User: โ
โ id = 1 โ
โ name = "ํ๊ธธ๋" โ
โ email = "hong@example.com" โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ๏ธ ORM์ด ์๋ ๋ณํ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐พ Database ์ธ๊ณ (๊ด๊ณํ ๋ฐ์ดํฐ) โ
โ โ
โ users ํ
์ด๋ธ: โ
โ โโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโ โ
โ โ id โ name โ email โ โ
โ โโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโโโโค โ
โ โ 1 โ ํ๊ธธ๋ โ hong@example.com โ โ
โ โโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ๋งคํ ๊ด๊ณ ์ดํดํ๊ธฐ!
| Python (๊ฐ์ฒด์งํฅ) | โ๏ธ | Database (๊ด๊ณํ) |
|---|---|---|
| Class (ํด๋์ค) | = | Table (ํ ์ด๋ธ) |
| Object (๊ฐ์ฒด) | = | Row (ํ) |
| Attribute (์์ฑ) | = | Column (์ปฌ๋ผ) |
๐ก ์ฝ๊ฒ ์ดํดํ๊ธฐ
Python์์
user = User(name="ํ๊ธธ๋")์ด๋ผ๊ณ ์ฐ๋ฉด,ORM์ด ์๋์ผ๋ก
INSERT INTO users (name) VALUES ('ํ๊ธธ๋')SQL์ ์์ฑํด์ ์คํํด์ฃผ๋๊ฑฐ์ฃ !
2. ORM์ ์ฐ๋ ์ด์ ?
Rawl SQL์ ๋ฌธ์ ์
Raw SQL์ ๋ฌธ์ ์ ์ด ๋ญ์ง๋ถํฐ ์์์ผ ํฉ๋๋ค.
1. SQL ๋ฌธ์์ด์ ์ง์ ์์ฑํด์ผ ํจ
cursor.execute("INSERT INTO users (name, email) VALUES ('ํ๊ธธ๋', 'hong@example.com')")2. ๐ฑ ํ์ ์ค์๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์
cursor.execute("INSERT INTO users (age) VALUES ('์ค๋ฌผ๋ค์ฏ')") # ์๋ฌ!3. ๐ฑ SQL ์ธ์ ์ ์ํ
user_input = "'; DROP TABLE users; --"
cursor.execute(f"SELECT * FROM users WHERE name = '{user_input}'") # ์ํ!4. ๐ฑ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ณ๊ฒฝ ์ ๋ชจ๋ SQL ์์ ํ์
- SQLite โ PostgreSQL ์ด๋ ์ ๋ฌธ๋ฒ ์ฐจ์ด๋ก ๋๊ท๋ชจ ์์
ORM์ ์ฅ์
1. ํ์ด์ฌ ๊ฐ์ฒด๋ก ์ง๊ด์ ์ผ๋ก ์์ ๊ฐ๋ฅ
user = User(name='ํ๊ธธ๋', email='hong@example.com')
db.session.add(user)
db.session.commit()2. ํ์ ์ฒดํฌ ์๋!
user.age = "์ค๋ฌผ๋ค์ฏ" # IDE๊ฐ ๋ฏธ๋ฆฌ ๊ฒฝ๊ณ !3. SQL ์ธ์ ์ ์๋ ๋ฐฉ์ง
User.query.filter_by(name=user_input).first() # ์์ !4. ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ณ๊ฒฝ์ ๊ฐํจ
- SQLite -> PostgreSQL๋ก ๋ฐ๊ฟ๋ ์ฝ๋ ์์ ์ต์ํ ๊ฐ๋ฅ
3. ์ค์ต ํ๊ฒฝ ์ค๋น
์ด๋ก ๋ง ๋ฐฑ๋ ๋ค์ด๋ ํ ๋ฒ์ ์ค์ต๋ง ๋ชปํฉ๋๋ค!
ํ๋ก์ ํธ ๊ตฌ์กฐ
orm_tutorial/
โโโ requirements.txt # ํ์ํ ํจํค์ง
โโโ 1_raw_sql_crud.py # Raw SQL ๋ฐฉ์
โโโ 2_orm_crud.py # ORM ๋ฐฉ์
โโโ 3_comparison.py # ๋น๊ต ์ค์ต
โโโ raw_sql_database.db # Raw SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค
โโโ orm_database.db # ORM ๋ฐ์ดํฐ๋ฒ ์ด์คํจํค์ง ์ค์น
1) requirements.txt ์์ฑ
Flask-SQLAlchemy==3.1.14. Raw SQL๋ก CRUD ๊ตฌํํ๊ธฐ
4-1. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ๊ด๋ฆฌ
Rawl SQL ๋ฐฉ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ์ง์ ๊ด๋ฆฌํด์ค์ผ ํฉ๋๋ค ..!
import sqlite3
from datetime import datetime
class DatabaseManager:
def __init__(self, db_name: str = "test.db"):
self.db_name = db_name
self.connection: None | sqlite3.Connection = None
self.cursor: None | sqlite3.Cursor = None
def connect(self) -> None:
"""๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ"""
# SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐ
self.connection = sqlite3.connect(self.db_name)
# Row ํ์
์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ๋์
๋๋ฆฌ๋ก ์ฒ๋ฆฌ
self.connection.row_factory = sqlite3.Row
# cursor: SQL ๋ช
๋ น ์คํํ๋ ๊ฐ์ฒด
self.cursor = self.connection.cursor()
print(f"โ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ: {self.db_name}")
def disconnect(self) -> None:
"""๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ข
๋ฃ"""
if self.connection:
self.connection.close()
print(f"โ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ข
๋ฃ")connection: ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฐ๊ฒฐcursor: SQL ๋ช ๋ น์ ์คํํ๋ ๋๊ตฌrow_factory: ๊ฒฐ๊ณผ๋ฅผ ์ด๋ค ํํ๋ก ๋ฐ์์ง ์ค์
ํ ๋ฒ ์คํํด๋ณผ๊น์?
if __name__ == "__main__":
dbm = DatabaseManager()
dbm.connect()
dbm.disconnect()โ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ: test.db
โ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ข
๋ฃ4-2. ํ ์ด๋ธ ์์ฑ
def create_table(self) -> None:
"""users ํ
์ด๋ธ ์์ฑ"""
# users ํ
์ด๋ธ ์์ฑ ์ฟผ๋ฆฌ ์ง์ ์์ฑ
create_table_sql = """
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
age INTEGER,
created_at TEXT NOT NULL
)
"""
print(f"\nํ
์ด๋ธ ์์ฑ SQL:\n{create_table_sql}")
# SQL ์คํ
self.cursor.execute(create_table_sql)
# ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ
self.connection.commit()
print("โ
users ํ
์ด๋ธ ์์ฑ ์๋ฃ!")โ ๏ธ ์ฃผ์์ฌํญ
commit()์ ํ์ง ์์ผ๋ฉด ๋ณ๊ฒฝ์ฌํญ์ด ์ ์ฅ๋์ง ์์ต๋๋ค!
4-3. CREATE - ์ฌ์ฉ์ ์์ฑ
def create_user(self, name: str, email: str, age: int | None = None) -> str | None:
"""์๋ก์ด ์ฌ์ฉ์ ์์ฑ (Create)"""
print(f"\n์ฌ์ฉ์ ์์ฑ: {name}, {email}")
created_at = datetime.now().isoformat()
# SQL Insert ๋ฌธ ์์ฑ
# ?๋ ํ๋ ์ด์คํ๋ (๊ฐ์ด ๋ค์ด๊ฐ ์๋ฆฌ)
insert_sql = """
INSERT INTO users (name, email, age, created_at)
VALUES (?, ?, ?, ?)
"""
print(f"๐ ์คํ SQL:\n{insert_sql}")
print(f"๐ ๊ฐ: {(name, email, age, created_at)}")
try:
# SQL ์คํ - ํ๋ ์ด์คํ๋์ ๊ฐ์ ์ ๋ฌ
self.cursor.execute(insert_sql, (name, email, age, created_at))
# ๋ณ๊ฒฝ์ฌํญ ์ ์ฅ
self.connection.commit()
# ๋ฐฉ๊ธ ์ธ์ํธ๋ ํ์ ID ๊ฐ์ ธ์ค๊ธฐ
user_id = self.cursor.lastrowid
print(f"โ
์ฌ์ฉ์ ์์ฑ ์๋ฃ! ID: {user_id}")
return user_id
except sqlite3.IntegrityError as e:
print(f"โ ์๋ฌ: {str(e)}")
return None๐ก ํ๋ ์ด์คํ๋ (?) ์ฌ์ฉ ์ด์
?๋ฅผ ์ฌ์ฉํ๋ฉด SQL ์ธ์ ์ ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.๋์ ์:
f"INSERT INTO users VALUES ('{name}')"์ข์ ์:
cursor.execute("INSERT INTO users VALUES (?)", (name,))
์ฌ์ฉ์๋ฅผ ํ ๋ฒ ์์ฑํด๋ด ์๋ค.
if __name__ == "__main__":
dbm = DatabaseManager()
# DB ์ฐ๊ฒฐ
dbm.connect()
# ํ
์ด๋ธ ์์ฑ
dbm.create_table()
# ์ ์ ์์ฑ (Create)
user_id: str = dbm.create_user(
name="jh", email="jh@jh.com", age=29
)์ฌ์ฉ์ ์์ฑ: jh, jh@jh.com
๐ ์คํ SQL:
INSERT INTO users (name, email, age, created_at)
VALUES (?, ?, ?, ?)
๐ ๊ฐ: ('jh', 'jh@jh.com', 29, '2025-11-09T08:33:44.539447')4-4. READ - ์ฌ์ฉ์ ์กฐํ
def get_user_by_id(self, user_id: int) -> dict|None:
"""ID๋ก ์ฌ์ฉ์ ์กฐํ"""
print(f"๐ ID๋ก ์ฌ์ฉ์ ์กฐํ: {user_id}")
select_sql = """
SELECT id, name, email, age, created_at FROM users WHERE id = ?
"""
# SQL ์คํ
self.cursor.execute(select_sql, (user_id,))
# ๊ฒฐ๊ณผ ๊ฐ์ ธ์ค๊ธฐ
row = self.cursor.fetchone()
if row:
user = dict(row) # Row๋ฅผ ๋์
๋๋ฆฌ๋ก ๋ณํ
print(f"์ฌ์ฉ์ ์ฐพ์!: {user}")
return user
else:
print(f"์ฌ์ฉ์ ๋ชป์ฐพ์!")
return None๐ก fetch ๋ฉ์๋ ์ข ๋ฅ
fetchone(): ์ฒซ ๋ฒ์งธ ๊ฒฐ๊ณผ๋ง ๋ฐํfetchall(): ๋ชจ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌ์คํธ๋ก ๋ฐํfetchmany(n): n๊ฐ์ ๊ฒฐ๊ณผ๋ง ๋ฐํ
์ ์ฝ๋์์ ์ถ๊ฐ๋ก ํ์ธํด๋ณผ๊ฒ ๋ญ๊ฐ ์์๊น์?
์ด์ ์ DatabaseManager ํด๋์ค์์ SQLite3์ connection ๊ฐ์ฒด์ ๋ค์๊ณผ ๊ฐ์ ์์ฑ์ ๋ฃ์๋ ๊ฒ์ด ๊ธฐ์ต๋์ญ๋๊น?
# Row ํ์
์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ๋์
๋๋ฆฌ๋ก ์ฒ๋ฆฌ
self.connection.row_factory = sqlite3.Row์ฌ๊ธฐ์ ์ ์์ฑ์ ์ฃผ์ ์ฒ๋ฆฌํ๊ณ get_user_by_id ๋ฉ์๋์์ row ๋ฐ์ดํฐ๋ฅผ ์กฐํํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฐ์ดํฐ๊ฐ ๋์ด์ต๋๋ค.
(1, 'jhlee37', 'jhlee37@cafe24corp.com', 29, '2025-11-09T08:00:46.327799')๋ฐ์ดํฐ๋ฅผ ์กฐํํด๋ดค์ ๋ ๋์ด์จ ๋ฐ์ดํฐ๊ฐ ์ด๋ค ์ปฌ๋ผ์ ๋ฐ์ดํฐ์ธ์ง ์์๋ณด๊ธฐ๊ฐ ์ฝ์ง ์์ฃ ?
๊ทธ๋ผ ๋ค์ ์ฃผ์ ์ฒ๋ฆฌ ํ๋ self.connection.row_factory = sqlite3.Row๋ฅผ ์ฃผ์ ํด์ ํ๊ณ ๋ค์ ์คํํด๋ณด๋ฉด?
{'id': 1, 'name': 'jhlee37', 'email': 'jhlee37@cafe24corp.com', 'age': 29, 'created_at': '2025-11-09T08:00:46.327799'}์ด๋ฐ ์์ผ๋ก row ๋ฐ์ดํฐ๊ฐ ๋ณด๊ธฐ ์ข๊ฒ dict ํํ๋ก ์ฒ๋ฆฌ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค!
๋ชจ๋ ์ฌ์ฉ์ ์กฐํํ๊ธฐ
์ ์์๋ ๋จ์ผ ์ฌ์ฉ์๋ง ์กฐํํ ์ ์์์ฃ ?
์ ์ฒด ์ฌ์ฉ์๋ฅผ ์กฐํํ๊ณ ์ถ๋ค๋ฉด, fetchall()๋ก ์ฟผ๋ฆฌ์ ๋ํ ๋ชจ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌ์คํธ๋ก ๋ฐํํ์ฌ ๊ฐ์ ธ์ค๋ฉด ๋ฉ๋๋ค.
def get_all_users(self) -> list[dict]:
"""๋ชจ๋ ์ฌ์ฉ์ ์กฐํ"""
print("\n๐๋ชจ๋ ์ฌ์ฉ์ ์กฐํ")
select_sql = """
SELECT id, name, email, age, created_at FROM users ORDER BY id desc
"""
self.cursor.execute(select_sql)
# ๋ชจ๋ ๊ฒฐ๊ณผ ํ ๊ฐ์ ธ์ค๊ธฐ
rows = self.cursor.fetchall()
# ๊ฐ ํ์ ๋์
๋๋ฆฌ๋ก ์ ํ
users = [dict(row) for row in rows]
print(f"โ
{len(users)} ๋ช
์ ์ ์ ๋ฅผ ์ฐพ์.")
return users4-5. UPDATE - ์ฌ์ฉ์ ์์
def update_user(
self, user_id: int, name: str = None, email: str = None, age: int = None
) -> bool:
"""์ฌ์ฉ์ ์ ๋ณด ์์ """
print(f"โ๏ธ ์ฌ์ฉ์ ์์ : ID {user_id}")
# ์์ ํ ํ๋ ๋ชฉ๋ก
update_fields = []
update_values = []
# ์ ๋ฌ๋ ๊ฐ๋ง ์
๋ฐ์ดํธ ๋ชฉ๋ก์ ์ถ๊ฐ
if name is not None:
update_fields.append("name = ?")
update_values.append(name)
if email is not None:
update_fields.append("email = ?")
update_values.append(email)
if age is not None:
update_fields.append("age = ?")
update_values.append(age)
# ์์ ํ ๋ด์ฉ์ด ์๋ ๊ฒฝ์ฐ
if not update_fields:
print("โ ๏ธ ์์ ํ ๋ด์ฉ์ด ์์ต๋๋ค.")
return False
# WHERE ์ ์ user_id๋ ์ถ๊ฐ
update_values.append(user_id)
# SQL Update ๋ฌธ ๋์ ์์ฑ
update_sql = f"""
UPDATE users
SET {", ".join(update_fields)}
WHERE id = ?
"""
print(f"์คํํ SQL๋ฌธ!\n{update_sql}")
print(f"๊ฐ: {tuple(update_values)}")
try:
self.cursor.execute(update_sql, tuple(update_values))
self.connection.commit()
# ์ค์ ๋ก ์์ ๋ ํ์ ๊ฐ์
if self.cursor.rowcount > 0:
print(f"โ
์ฌ์ฉ์ ์์ ์๋ฃ! (์
๋ฐ์ดํธ๋ ํ: {self.cursor.rowcount})")
return True
else:
print(f"โ ํด๋น ID์ ์ฌ์ฉ์๊ฐ ์์!")
return False
except sqlite3.IntegrityError as e:
print(f"์๋ฌ: {str(e)}")
return Falseid๊ฐ 4๋ฒ์ธ ์ฌ์ฉ์๋ฅผ ์์ ํด๋ณด๊ฒ ์ต๋๋ค.
if __name__ == "__main__":
# ...
# ์ ์ ์ ๋ณด ์
๋ฐ์ดํธ
dbm.update_user(user_id=4, name="up_jhlee37", email="up_jhlee37@com", age=30)
dbm.get_user_by_id(user_id=4) # ์์ ๋๋์ง ํ์ธ์ถ๋ ฅ ๊ฐ์ ํ์ธํด๋ณผ๊น์?
โ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ: test.db
โ
users ํ
์ด๋ธ ์์ฑ ์๋ฃ!
โ๏ธ ์ฌ์ฉ์ ์์ : ID 4
์คํํ SQL๋ฌธ!
UPDATE users
SET name = ?, email = ?, age = ?
WHERE id = ?
๊ฐ: ('up_jhlee37', 'up_jhlee37@com', 30, 4)
โ
์ฌ์ฉ์ ์์ ์๋ฃ! (์
๋ฐ์ดํธ๋ ํ: 1)
๐ ID๋ก ์ฌ์ฉ์ ์กฐํ: 4
์ ์ ์ฐพ์!: {'id': 4, 'name': 'up_jhlee37', 'email': 'up_jhlee37@com', 'age': 30, 'created_at': '2025-11-15T07:25:41.487555'}
โ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ข
๋ฃ์ ์์ ์ผ๋ก id๊ฐ 4๋ฒ์ธ ์ ์ ์ ๋ฐ์ดํฐ๊ฐ ์์ ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค!
4-6. DELETE - ์ฌ์ฉ์ ์ญ์
๋ง์ง๋ง์ผ๋ก ์ฌ์ฉ์๋ฅผ ์ญ์ ํ๋ ํจ์๋ฅผ ์์ฑํด๋ณด๋ฉฐ, Raw SQL๋ก CRUD๋ฅผ ๊ตฌํํ๋ ์ฑํฐ๋ฅผ ๋ง๋ฌด๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
def delete_user(self, user_id: int) -> bool:
"""์ฌ์ฉ์ ์ญ์ """
print(f"\n๐๏ธ ์ฌ์ฉ์ ์ญ์ : ID {user_id}")
delete_sql = """
DELETE FROM users
WHERE id = ?
"""
self.cursor.execute(delete_sql, (user_id,))
self.connection.commit()
if self.cursor.rowcount > 0:
print(f"โ
์ฌ์ฉ์ ์ญ์ ์๋ฃ! (์ญ์ ๋ ํ: {self.cursor.rowcount})")
return True
else:
print(f"โ ํด๋น ID์ ์ฌ์ฉ์๊ฐ ์์!")
return Falseid๊ฐ 3๋ฒ์ธ ์ฌ์ฉ์๋ฅผ ์ญ์ ํด๋ณด๊ฒ ์ต๋๋ค.
if __name__ == "__main__":
# ...
dbm.delete_user(user_id=3)
# ์ ์ ๊ฐ ์ญ์ ๋๋์ง ํ์ธํ๊ธฐ.
users = dbm.get_all_users()
print(users)์ถ๋ ฅ ๊ฐ์ ํ์ธํด๋ด ์๋ค.
โ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ: test.db
โ
users ํ
์ด๋ธ ์์ฑ ์๋ฃ!
๐๏ธ ์ฌ์ฉ์ ์ญ์ : ID 3
โ
์ฌ์ฉ์ ์ญ์ ์๋ฃ! (์ญ์ ๋ ํ: 1)
๐๋ชจ๋ ์ฌ์ฉ์ ์กฐํ
โ
1 ๋ช
์ ์ ์ ๋ฅผ ์ฐพ์.
[{'id': 2, 'name': 'jhlee38', 'email': 'jhlee38@cafe24corp.com', 'age': 29, 'created_at': '2025-11-09T08:02:06.148338'}]
โ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ข
๋ฃid๊ฐ 3๋ฒ์ธ ์ฌ์ฉ์๊ฐ ์ญ์ ๋์ด, ๋์ด์ ์กฐํ๋์ง ์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
5. ORM์ผ๋ก CRUD ๊ตฌํํ๊ธฐ
์ด์ Raw SQL๋ก ๊ตฌํํ ๋ชจ๋ ๊ธฐ๋ฅ์ ORM์ผ๋ก ๊ตฌํํด๋ณผ ๊ฒ๋๋ค.
์ฝ๋๊ฐ ์ผ๋ง๋ ๊ฐ๊ฒฐํด์ง๋์ง ํ ๋ฒ ๋น๊ตํด๋ด ์๋ค.
5-0. ๋ชจ๋ ๋ถ๋ฌ์ค๊ธฐ
from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import sessionmakerํ์ฌ ๋ถ๋ฌ์จ ํจ์์ ํด๋์ค์ ๋ํ ์ค๋ช ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
| ๋ชจ๋๋ช | ์ค๋ช |
|---|---|
create_engine ํจ์ |
- SQLAlchemy์์ DB์์ ์ฐ๊ฒฐ์ ์ค์ ํ๋ ์ญํ ์ ํฉ๋๋ค. - ์ฐ๊ฒฐ ๋ฌธ์์ด์ ๋ฐ์์ ํด๋น ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๋ ์์ง(Engine) ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. - ์์) create_engine("mysql+pymysql://...") |
declarative_base ํจ์ |
- ํด๋์ค๋ฅผ ์ ์ํ ๋ ์ฌ์ฉ๋๋ ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ์ ์ํฉ๋๋ค. - ์ด ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ์์๋ฐ์ ํด๋์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ์ ๋ํ๋ด๊ฒ ๋ฉ๋๋ค. - Base = declarative_base()์ ๊ฐ์ด ์ฌ์ฉํฉ๋๋ค |
Column ํด๋์ค |
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ
์ด๋ธ์์ ๊ฐ ์ด(Column)์ ๋ํ๋
๋๋ค. ์์) id = Column(Integer, primary_key=True) |
sessionmaker ํด๋์ค |
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ธ์
์ ์์ฑํ๋ ์ญํ ์ ํฉ๋๋ค. - ์ธ์ ์ ํธ๋์ญ์ ๊ณผ ๊ด๋ จ๋ ์์ ์ ์ฒ๋ฆฌํ๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ํธ ์์ฉ๋ ๋ด๋นํฉ๋๋ค. ์์) SessionLocal = sessionmaker(bind=engine) (engine์ ๋ฐ์ธ๋ฉ๋ ์ธ์
์ฐ๊ฒฐ) |
5-1. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐํ๊ธฐ
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฒฝ์ฐ ์ด์ ์๋ sqlite3๋ฅผ ์ฌ์ฉํ์์ผ๋,
์ด๋ฒ ์ค์ต์์๋ MySQL๋ก ์ ํํ์ฌ ์ค์ต์ ์งํํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime
# ํ์
ํํธ ์ฒ๋ฆฌ์ฉ ๋ชจ๋
import sqlalchemy.orm as orm
import sqlalchemy.exc as exc
import sqlalchemy.engine as eng
# Base ํด๋์ค ์์ฑ
# ๋ชจ๋ ORM์ ์ด Base๋ฅผ ์์๋ฐ์.
Base: orm.decl_api.DeclarativeMeta = declarative_base()
# MySQL ์ฐ๊ฒฐ ์ ๋ณด
DB_USER: str = "root"
DB_PASS: str = "custom"
DB_HOST: str = "192.168.219.110"
DB_PORT: int = 3333
DB_NAME: str = "orm"
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ง ์์ฑ
try:
engine: eng.base.Engine = create_engine(
f"mysql+pymysql://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}",
echo=True, # SQL ์ฟผ๋ฆฌ๋ฌธ์ ์๋์ผ๋ก ์ถ๋ ฅํด์ค (ํ์ต์ฉ)
)
except exc.ArgumentError as e:
print(f"[๐ด] Argument Error!\nReason: {str(e)}")
# Session ํด๋์ค ์์ฑ
# Session: ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ํ (conversation)
SessionLocal: orm.session.sessionmaker = sessionmaker(bind=engine)5-2. ํด๋์ค(ํ ์ด๋ธ) ์์ฑํ๊ธฐ
ORM ๋ชจ๋ธ ์ ์ํ๊ธฐ (ํ ์ด๋ธ ์คํค๋ง ์ ์)
# ------------------ ORM ๋ชจ๋ธ ์ ์ ------------------
class User(Base):
"""
User ํ
์ด๋ธ์ ๋ํ๋ด๋ ORM ๋ชจ๋ธ
User ํด๋์ค:
- ํ
์ด๋ธ ๊ตฌ์กฐ๋ฅผ ์ ์
- ๊ฐ ์ธ์คํด์ค๊ฐ ํ
์ด๋ธ์ ํ ํ(row)์ ๋ํ๋
- Python ๊ฐ์ฒด์ฒ๋ผ ๋ค๋ฃฐ ์ ์์.
"""
# ํ
์ด๋ธ ์ด๋ฆ ์ง์
__tablename__ = "users"
# ์ปฌ๋ผ ์ ์
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(100), nullable=False)
email = Column(String(100), nullable=False, unique=True)
age = Column(Integer)
created_at = Column(DateTime, default=datetime.utcnow)
def __repr__(self) -> str:
"""๊ฐ์ฒด๋ฅผ ๋ฌธ์์ด๋ก ํํํจ"""
return f"<User(id={self.id}, name='{self.name}', email='{self.email}')>"
def to_dict(self) -> dict:
"""๊ฐ์ฒด๋ฅผ ๋์
๋๋ฆฌ๋ก ๋ณํ"""
return {
"id": self.id,
"name": self.name,
"email": self.email,
"age": self.age,
"created_at": self.created_at,
}๐ก ORM ๋ชจ๋ธ์ ๊ตฌ์กฐ
__tablename__: ํ ์ด๋ธ ์ด๋ฆColumn(): ๊ฐ ์ปฌ๋ผ ์ ์primary_key=True: ๊ธฐ๋ณธ ํค ์ค์ nullable=False: NOT NULL ์ ์ฝunique=True: UNIQUE ์ ์ฝdefault: ๊ธฐ๋ณธ๊ฐ ์ค์
ํ ์ด๋ธ ์์ฑ
# ------------------ ํ
์ด๋ธ ์์ฑ------------------
def create_tables() -> None:
"""์ ์๋ ๋ชจ๋ ๋ชจ๋ธ์ ํ
์ด๋ธ ์์ฑ"""
print("\n๐ ํ
์ด๋ธ ์์ฑ ์ค ...")
# Base.metadata.create_all():
# - Base๋ฅผ ์์๋ฐ์ ๋ชจ๋ ํด๋์ค๋ฅผ ์ฐพ์
# - ๊ฐ ํด๋์ค์ ๋์ํ๋ ํ
์ด๋ธ์ ์์ฑ
# - ์ด๋ฏธ ์กด์ฌํ๋ ํ
์ด๋ธ์ ๊ฑด๋๋ฆฌ์ง ์์
Base.metadata.create_all(bind=engine)
print("โ
ํ
์ด๋ธ ์์ฑ ์๋ฃ!")5-3. CREATE - ์ฌ์ฉ์ ์์ฑ
# ------------------ CRUD ------------------
class UserCRUD:
"""ORM์ ์ฌ์ฉํ User CRUD ์์
"""
def __init__(self):
self.session: orm.session.sessionmaker = SessionLocal()
def create_user(self, name: str, email: str, age: int = None) -> None | User:
"""
์๋ก์ด ์ฌ์ฉ์ ์์ฑ
ORM ๋ฐฉ์:
1. User ๊ฐ์ฒด ์์ฑ (๋ฉ๋ชจ๋ฆฌ์๋ง ์กด์ฌ)
2. session.add()๋ก ์ธ์
์ ์ถ๊ฐ
3. session.commit()์ผ๋ก DB์ ์ค์ ์ ์ฅ
"""
print(f"\nโ ์ฌ์ฉ์ ์์ฑ: {name}, {email}")
# 1. User ๊ฐ์ฒด ์์ฑ
# ์ด ์์ ์์๋ ๋ฉ๋ชจ๋ฆฌ์๋ง ์กด์ฌ
new_user = User(name=name, email=email, age=age)
print(f"์์ฑ๋ ๊ฐ์ฒด: {new_user}")
print(f"ID: {new_user.id}") # None (์์ง DB์ ์์!)
try:
# 2. Session์ ์ถ๊ฐ
self.session.add(new_user)
# 3. DB์ ์ค์ ์ ์ฅ
# INSERT SQL์ด ์๋ ์์ฑ๋์ด ์คํ๋จ
self.session.commit()
# commit ํ์๋ ID๊ฐ ์์ฑ๋จ!
print(f"์ฌ์ฉ์ ์์ฑ ์๋ฃ! ID: {new_user.id}")
return new_user
except Exception as e:
print(f"[๐ด] {str(e)}")
return None๐ก ORM ์์ฑ ํ๋ก์ธ์ค
- ๊ฐ์ฒด ์์ฑ:
user = User(name="ํ๊ธธ๋")โ ๋ฉ๋ชจ๋ฆฌ์๋ง ์กด์ฌ- ์ธ์ ์ถ๊ฐ:
session.add(user)โ "์ ์ฅํ ์์ " ํ์- ์ปค๋ฐ:
session.commit()โ ์ค์ DB์ ์ ์ฅ
ํ ๋ฒ User ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉ์๋ฅผ ์์ฑํด๋ณด๋๋ก ํฉ์๋ค.
if __name__ == "__main__":
"""ORM CRUD ์ค์ต"""
print("=" * 80)
print("SQLAlchemy ORM์ ์ฌ์ฉํ CRUD ์ค์ต")
print("=" * 80)
# 1. ํ
์ด๋ธ ์์ฑ
create_tables()
# 2. CRUD ๊ฐ์ฒด ์์ฑ
user_crud = UserCRUD()
# 3. ์๋ก์ด ์ ์ ์์ฑ
new_user: User | None = user_crud.create_user(
name="jhlee04", email="jhlee04@jhlee04", age=29
)
print(
f"์๋ก์ด ์ ์ ์ ๋ณด: ID: {new_user.id}, NAME: {new_user.name}, EMAIL: {new_user.email}"
)์ถ๋ ฅ ๊ฐ์ ํ ๋ฒ ๋ณด๋๋ก ํ ๊ฒ์.
================================================================================
SQLAlchemy ORM์ ์ฌ์ฉํ CRUD ์ค์ต
================================================================================
๐ ํ
์ด๋ธ ์์ฑ ์ค ...
2025-11-15 10:09:51,140 INFO sqlalchemy.engine.Engine SELECT DATABASE()
2025-11-15 10:09:51,140 INFO sqlalchemy.engine.Engine [raw sql] {}
2025-11-15 10:09:51,141 INFO sqlalchemy.engine.Engine SELECT @@sql_mode
2025-11-15 10:09:51,141 INFO sqlalchemy.engine.Engine [raw sql] {}
2025-11-15 10:09:51,141 INFO sqlalchemy.engine.Engine SELECT @@lower_case_table_names
2025-11-15 10:09:51,142 INFO sqlalchemy.engine.Engine [raw sql] {}
2025-11-15 10:09:51,142 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2025-11-15 10:09:51,142 INFO sqlalchemy.engine.Engine DESCRIBE `orm`.`users`
2025-11-15 10:09:51,142 INFO sqlalchemy.engine.Engine [raw sql] {}
2025-11-15 10:09:51,144 INFO sqlalchemy.engine.Engine COMMIT
โ
ํ
์ด๋ธ ์์ฑ ์๋ฃ!
โ ์ฌ์ฉ์ ์์ฑ: jhlee04, jhlee04@jhlee04
์์ฑ๋ ๊ฐ์ฒด: <User(id=None, name='jhlee04', email='jhlee04@jhlee04')>
ID: None
2025-11-15 10:09:51,145 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2025-11-15 10:09:51,146 INFO sqlalchemy.engine.Engine INSERT INTO users (name, email, age, created_at) VALUES (%(name)s, %(email)s, %(age)s, %(created_at)s)
2025-11-15 10:09:51,146 INFO sqlalchemy.engine.Engine [generated in 0.00013s] {'name': 'jhlee04', 'email': 'jhlee04@jhlee04', 'age': 29, 'created_at': datetime.datetime(2025, 11, 15, 10, 9, 51, 146782)}
2025-11-15 10:09:51,147 INFO sqlalchemy.engine.Engine COMMIT
2025-11-15 10:09:51,150 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2025-11-15 10:09:51,152 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.age AS users_age, users.created_at AS users_created_at
FROM users
WHERE users.id = %(pk_1)s
2025-11-15 10:09:51,152 INFO sqlalchemy.engine.Engine [generated in 0.00010s] {'pk_1': 12}
์ฌ์ฉ์ ์์ฑ ์๋ฃ! ID: 12
์๋ก์ด ์ ์ ์ ๋ณด: ID: 12, NAME: jhlee04, EMAIL: jhlee04@jhlee04์ฌ๋ฌ ์ถ๋ ฅ๋ฌธ์ด ๋จ๊ณ ์์ฃ ?
SQL ๊ด๋ จ ๋ก๊ทธ๊ฐ ๋จ๋ ๊ฒ์ ์์์ ์ค์ ํ ์๋ ์ฝ๋ ๋๋ฌธ์ ๋๋ค.
engine: eng.base.Engine = create_engine(
f"mysql+pymysql://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}",
echo=True, # SQL ์ฟผ๋ฆฌ๋ฌธ์ ์๋์ผ๋ก ์ถ๋ ฅํด์ค (ํ์ต์ฉ)
)echo ์์ฑ์ True๋ก ์คฌ๊ธฐ ๋๋ฌธ์ SQL ์ฟผ๋ฆฌ๋ฌธ์ ๋ํ ๋ก๊ทธ๊ฐ ๋จ๊ณ ์๋ ๊ฒ์ ๋ณผ ์ ์์ด์.
Raw SQL๊ณผ ๋น๊ต
Raw SQL์ ์ฌ์ฉํ์ ๋์๋ ์ด๋ค ์ ์ด ๋ค๋ฅธ์ง ์ฝ๋๋ก ๋น๊ตํด๋ณผ๊น์?
# Raw SQL: 19์ค
insert_sql = """
INSERT INTO users (name, email, age, created_at)
VALUES (?, ?, ?, ?)
"""
created_at = datetime.now().isoformat()
try:
cursor.execute(insert_sql, (name, email, age, created_at))
connection.commit()
user_id = cursor.lastrowid
return user_id
except sqlite3.IntegrityError as e:
print(f"์๋ฌ: {e}")
return None
# ORM: 7์ค
try:
user = User(name=name, email=email, age=age)
session.add(user)
session.commit()
return user
except Exception as e:
session.rollback()
return None5-4. READ - ์ฌ์ฉ์ ์กฐํ
id ์ปฌ๋ผ ๊ฐ ๊ธฐ๋ฐ ๋จ์ผ ์ฌ์ฉ์ ์กฐํ
def get_user_by_id(self, user_id: int) -> User | None:
"""ID๋ก ์ฌ์ฉ์ ์กฐํ"""
print(f"\n๐ ID๋ก ์ฌ์ฉ์ ์กฐํ: {user_id}")
# get(): ๊ธฐ๋ณธ ํค๋ก ์กฐํ
# SELECT * FROM users WHERE id = ?์ ๋์ผ
user: User = self.session.get(User, user_id)
if user:
print(f"์ฌ์ฉ์ ์ฐพ์: {user.to_dict()}")
else:
print("์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์์!")
return userid๊ฐ 1์ธ ์ฌ์ฉ์๋ฅผ ์กฐํํด๋ณด๊ฒ ์ต๋๋ค.
if __name__ == "__main__":
"""ORM CRUD ์ค์ต"""
# ...
# 4. ๋จ์ผ ์ ์ ์กฐํ (user_id, READ)
user: User = user_crud.get_user_by_id(user_id=1)
print(user.to_dict())์ถ๋ ฅ ๊ฐ์ ์กฐํํด๋ณผ๊ฒ์.
์ฌ์ฉ์ ์ฐพ์: {'id': 1, 'name': 'jhlee01', 'email': 'jhlee01@jhlee01', 'age': 29, 'created_at': datetime.datetime(2025, 11, 15, 9, 28, 18)}
{'id': 1, 'name': 'jhlee01', 'email': 'jhlee01@jhlee01', 'age': 29, 'created_at': datetime.datetime(2025, 11, 15, 9, 28, 18)}id๊ฐ 1๋ฒ์ธ ์ฌ์ฉ์ ๋ฐ์ดํฐ๊ฐ ์กฐํ๋ฉ๋๋ค.
to_dict() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด์ ์ ๋ณด๊ฐ ๋์
๋๋ฆฌ๋ก๋ ์ ์์ ์ผ๋ก ์กฐํ๋๋ ๊ฒ์ ๋ณผ ์ ์์ด์.
๋ชจ๋ ์ฌ์ฉ์ ์กฐํ
def get_all_users(self) -> list[User]:
"""๋ชจ๋ ์ฌ์ฉ์ ์กฐํ"""
print("\n๐ ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ")
# query(User): User ํ
์ด๋ธ์ ๋ํ ์ฟผ๋ฆฌ
# order_by(User.id): ORDER BY id
# all(): ๋ชจ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌ์คํธ๋ก ๋ฐํ
users = self.session.query(User).order_by(User.id).all()
print(f"{len(users)} ๋ช
์ ์ฌ์ฉ์ ์ฐพ์.")
return users๋ชจ๋ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ list๋ก ๋ฆฌํดํ๋๋ก ์์ฑํ์์ต๋๋ค.
๋ชจ๋ ์ฌ์ฉ์๋ฅผ ์กฐํํด๋ด ์๋ค.
if __name__ == "__main__":
"""ORM CRUD ์ค์ต"""
# ...
# 5. ๋ชจ๋ ์ ์ ์กฐํ
users: list = user_crud.get_all_users()
print(users)4 ๋ช
์ ์ฌ์ฉ์ ์ฐพ์.
[<User(id=1, name='jhlee01', email='jhlee01@jhlee01')>, <User(id=9, name='jhlee02', email='jhlee02@jhlee02')>, <User(id=10, name='jhlee03', email='jhlee03@jhlee03')>, <User(id=12, name='jhlee04', email='jhlee04@jhlee04')>]์ด๋ฆ์ผ๋ก ๊ฒ์
def get_users_by_name(self, name_keyword: str) -> list[User]:
"""์ ์ ์ด๋ฆ์ผ๋ก ์กฐํ"""
print("\n๐ ์ด๋ฆ์ผ๋ก ๊ฒ์")
# filter(): WHERE ์
# like(): SQL์ LIKE ์ฐ์ฐ์
users = (
self.session.query(User)
.filter(User.name.like(f"%{name_keyword}%"))
.order_by(User.name)
).all()
print(f"ํค์๋: '{name_keyword}' - {len(users)}๋ช
์ ์ฌ์ฉ์ ์ฐพ์.")
return userssessionmaker ๊ฐ์ฒด๊ฐ ๊ฐ์ง๊ณ ์๋ filter ๋ฉ์๋๋ฅผ ํตํด์ SQL์ LIKE ์ฐ์ฐ์๋ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
jh ๋ผ๋ ๋ฌธ์์ด์ ํฌํจํ๋ ์ ์ ๋ค์ ์กฐํํด๋ณด๊ฒ ์ต๋๋ค.
if __name__ == "__main__":
"""ORM CRUD ์ค์ต"""
# ...
# 6. ์ด๋ฆ์ผ๋ก ๊ฒ์ (LIKE ์ฐ์ฐ์)
users = user_crud.get_users_by_name(name_keyword="jh")ํค์๋: jh - 4๋ช
์ ์ฌ์ฉ์ ์ฐพ์.
[<User(id=1, name='jhlee01', email='jhlee01@jhlee01')>, <User(id=9, name='jhlee02', email='jhlee02@jhlee02')>, <User(id=10, name='jhlee03', email='jhlee03@jhlee03')>, <User(id=12, name='jhlee04', email='jhlee04@jhlee04')>]Raw SQL๊ณผ ๋น๊ต
# ---- Raw SQL: ๋ณต์กํ ๋ฌธ์์ด ์กฐ์
select_sql = """
SELECT id, name, email, age, created_at
FROM users
WHERE name LIKE ?
ORDER BY name ASC
"""
cursor.execute(select_sql, (f"%{name_keyword}%",))
rows = cursor.fetchall()
users = [dict(row) for row in rows]
# ---- ORM: ๋ฉ์๋ ์ฒด์ด๋์ผ๋ก ์ง๊ด์
users = session.query(User)\
.filter(User.name.like(f"%{name_keyword}%"))\
.order_by(User.name)\
.all()5-5. UPDATE - ์ฌ์ฉ์ ์์
id ๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์์ ํ ๋!
def update_user(
self, user_id: int, name: str = None, email: str = None, age: int = None
) -> None | User:
"""
์ฌ์ฉ์ ์ ๋ณด ์์
ORM ๋ฐฉ์:
1. ๊ฐ์ฒด ์กฐํ
2. ๊ฐ์ฒด์ ์์ฑ ์์
3. commit()์ผ๋ก ๋ณ๊ฒฝ์ฌํญ ์ ์ฅ
"""
print(f"\n โ๏ธ ์ฌ์ฉ์ ์์ : ID: {user_id}")
# 1. ์ฌ์ฉ์ ์กฐํ
user: User = self.session.get(User, user_id)
if not user:
print(f"ํด๋น ID({user_id})์ ์ฌ์ฉ์๊ฐ ์์ต๋๋ค")
return None
# ์์ ์ ์ ์ฌ์ฉ์ ์ ๋ณด ์ถ๋ ฅ
print(f" ์์ ์ : {user.to_dict()}")
# 2. ์์ฑ ์์
# ๊ฐ์ฒด์ ์์ฑ์ ์ง์ ์์
# ORM์ด ๋ณ๊ฒฝ์ฌํญ์ ์๋์ผ๋ก ์ถ์ ํจ.
if name is not None:
user.name = name
print(f" ์ด๋ฆ ๋ณ๊ฒฝ: {user.name}")
if email is not None:
user.email = email
print(f" ์ด๋ฉ์ผ ๋ณ๊ฒฝ: {user.email}")
if age is not None:
user.age = age
print(f" ๋์ด ๋ณ๊ฒฝ: {user.age}")
try:
# 3. ๋ณ๊ฒฝ์ฌํญ ์ ์ฉ
# UPDATE SQL์ด ์๋ ์์ฑ๋จ.
self.session.commit()
print(f"โ
์ฌ์ฉ์ ์์ ์๋ฃ!")
print(f" ์์ ํ: {user.to_dict()}")
return user
except Exception as e:
self.session.rollback() # ์ด์ ์ค์ ์ผ๋ก ๋๋๋ฆฌ๊ธฐ
print(f"์๋ฌ: {str(e)}")
return Noneid ๊ฐ์ด 1๋ฒ์ธ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ์์ ํด๋ณผ๊น์?
if __name__ == "__main__":
"""ORM CRUD ์ค์ต"""
# ...
# 7. ์ฌ์ฉ์ ์
๋ฐ์ดํธ
update_user: User = user_crud.update_user(user_id=1, name="jhlee_updated_01")
read_user: User = user_crud.get_user_by_id(user_id=1)์ ์ฝ๋๋ฅผ ์คํํ๊ณ id๊ฐ 1๋ฒ์ธ ์ ์ ์ name ํ๋ ๊ฐ์ด jhlee_updated_01๋ก ๋ณ๊ฒฝ๋์ด ์์ผ๋ฉด ์ฑ๊ณต์ด๋ค์?
๐ ID๋ก ์ฌ์ฉ์ ์กฐํ: 1
์ฌ์ฉ์ ์ฐพ์: {'id': 1, 'name': 'jhlee_updated_01', 'email': 'jhlee01@jhlee01', 'age': 29, 'created_at': datetime.datetime(2025, 11, 15, 9, 28, 18)}์ ์์ ์ผ๋ก id๊ฐ 1๋ฒ์ธ ์ฌ์ฉ์์ name ๊ฐ์ด ๋ณ๊ฒฝ๋์์ต๋๋ค!
Raw SQL๊ณผ ๋น๊ต
# Raw SQL: ๋ณต์กํ ๋์ SQL ์์ฑ
update_fields = []
update_values = []
if name is not None:
update_fields.append("name = ?")
update_values.append(name)
if email is not None:
update_fields.append("email = ?")
update_values.append(email)
update_values.append(user_id)
update_sql = f"UPDATE users SET {', '.join(update_fields)} WHERE id = ?"
cursor.execute(update_sql, tuple(update_values))
connection.commit()
# ORM: ์ง๊ด์ ์ธ ์์ฑ ์์
user = session.get(User, user_id)
if name is not None:
user.name = name
if email is not None:
user.email = email
session.commit()Raw SQL์ ๊ฒฝ์ฐ ์ง์ ์ฟผ๋ฆฌ๋ฌธ์ ์์ฑํ์ฌ ์คํํ๋ค๋ณด๋ ์ฝ๋๊ฐ ๊ธธ์ด์ง๊ณ ๊ฐ๋ ์ฑ์ด ์๋นํ ๋จ์ด์ง๋๋ค ...
5-6. DELETE - ์ฌ์ฉ์ ์ญ์
def delete_user(self, user_id: int) -> bool:
"""
์ฌ์ฉ์ ์ญ์
ORM ๋ฐฉ์:
1. ๊ฐ์ฒด ์กฐํ
2. session.delete()๋ก ์ญ์ ํ์
3. commit()์ผ๋ก ์ค์ ์ญ์
"""
print(f"\n๐๏ธ ์ฌ์ฉ์ ์ญ์ : {user_id}")
# 1. ์ฌ์ฉ์ ์กฐํ
user: User = self.session.get(User, user_id)
if not user:
print(f"ํด๋น ID({user_id})์ ์ฌ์ฉ์๊ฐ ์์ต๋๋ค!")
return False
# 2. ์ญ์ ํ์
self.session.delete(user)
# 3. ์ค์ ์ญ์
# DELETE SQL์ด ์๋ ์์ฑ๋์ด ์คํ๋จ.
self.session.commit()
return Trueid๊ฐ 1๋ฒ์ธ ์ฌ์ฉ์๋ฅผ ์ญ์ ํด๋ณธ ํ, ์ค์ ๋ก ์ญ์ ๋๋์ง ์กฐํํด๋ด
์๋ค.
if __name__ == "__main__":
"""ORM CRUD ์ค์ต"""
# ...
# 9. ์ฌ์ฉ์ ์ญ์
user_delete: bool = user_crud.delete_user(user_id=1)
user_crud.get_user_by_id(user_id=1) # ์ค์ ์ญ์ ๋์๋์ง id ๊ธฐ๋ฐ ์กฐํ์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์์!id๊ฐ 1๋ฒ์ธ ์ฌ์ฉ์๊ฐ ์ญ์ ๋์ด ์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์์! ์ด๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ์ถ๋ ฅ๋๋ค์!
๋ง๋ฌด๋ฆฌํ๋ฉฐ
์ง๊ธ๊น์ง Raw SQL๊ณผ ORM์ ๊ฐ๊ฐ ๋น๊ตํ๋ฉฐ ์ค์ต์ ์งํํด๋ดค์ต๋๋ค.
ํ์คํ ์ผ๋ฐ์ ์ธ CRUD์ ์์ด์๋ ORM์ ์ฌ์ฉํ๋ ๊ฒ์ด ์์
ํจ์จ์ฑ์ ๊ฝค ๋์ผ ์ ์์ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์์ต๋๋ค.
๋ค๋ง ๋ณต์กํ ์ฟผ๋ฆฌ๋ ์ฑ๋ฅ์ ์์ด์ ์ค์ํ ๋ก์ง ๋ฑ์ Raw SQL๊ณผ ๋ณํํ๋ฉฐ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ข์๋ณด์ ๋๋ค!
์ค๋ ๋ฐฐ์ด ORM ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก
์ถํ์ ๊ฐ๋จํ ๋์ ๊ด๋ฆฌ API ๋ฅผ Flask ํ๋ ์์ํฌ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌํํด๋ณด๋ ค๊ณ ํฉ๋๋ค!
๋ค์์ ๋ง๋์!
