
ORM์ ๊ฐ์ฒด์งํฅ ์ธ๊ณ(ํด๋์ค/๊ฐ์ฒด)์ ๊ด๊ณํ DB ์ธ๊ณ(ํ
์ด๋ธ/ํ)๋ฅผ ์ด์ด์ฃผ๋ ํต์ญ ์์คํ
์ด๋ค. ๐
๊ฐ๋ฐ์๋ Python ๊ฐ์ฒด๋ฅผ ๋ค๋ฃจ๋ฏ์ด ์ฝ๋๋ฅผ ์์ฑํ๊ณ , ORM์ ๊ทธ๊ฑธ SQL๋ก ๋ฒ์ญํด์ DB์ ์์ฒญํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ๊ฐ์ฒด๋ก ๋ณต์ํ๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ ๋ณดํต ๊ฐ์ฒด๋ก ์ฌ๊ณ ํ๋ค.
User, Post, Comment ๊ฐ์ ๊ฒ๋ค์ ํด๋์ค/๊ฐ์ฒด๋ก ํํํ๋ค. ๐งฑ
๊ทธ๋ฐ๋ฐ DB๋ ํ
์ด๋ธ/์ปฌ๋ผ/ํ์ผ๋ก ์ ์ฅํ๋ค.
์ฆ, ๋์ ๊ธฐ๋ณธ ์ฒ ํ์ด ๋ค๋ฅด๋ค.
์ด ์ฐจ์ด๋ฅผ ํํ ๊ฐ์ฒด์งํฅ vs ๊ด๊ณํ DB์ ํจ๋ฌ๋ค์ ๋ถ์ผ์น๋ผ๊ณ ๋ถ๋ฅธ๋ค. (Object-Relational Impedance Mismatch) โก
๊ฐ์ฒด์งํฅ ์ธ๊ณ ๊ด๊ณํ DB ์ธ๊ณ
------------------ ------------------
User ๊ฐ์ฒด (์์ฑ+ํ๋) users ํ
์ด๋ธ (๋ฐ์ดํฐ)
user.email = "a@b.com" UPDATE users SET email='a@b.com' ...
user.team.name SELECT ... JOIN teams ...
"์ (.)์ผ๋ก ํ์" "JOIN์ผ๋ก ์กฐ๋ฆฝ"
ORM์ ์ด ๋ถ์ผ์น๋ฅผ ์ค์ด๊ธฐ ์ํด ๋ฑ์ฅํ๋ค. ์ฆ, ๊ฐ์ฒด๋ฅผ ์ค์ฌ์ผ๋ก ๊ฐ๋ฐํ๋ DB์์ ์ฐ๊ฒฐ์ ์๋ํํ๋ ๋๊ตฌ๋ค. ๐ ๏ธ
ORM ์์ด DB๋ฅผ ์ฐ๋ฉด ๋ณดํต ์ด๋ฐ ํ๋ฆ์ด ๋๋ค.
[ํ๋ฆ]
1) SQL ๋ฌธ์์ด ์์ฑ
2) cursor.execute(...)
3) fetchone()/fetchall()
4) row๋ฅผ ๊ฐ์ฒด๋ก ์ง์ ๋ณํ (์๋ ๋งคํ)
5) ํ๋ ์ถ๊ฐ/๋ณ๊ฒฝ ์ SQL + ๋งคํ ์ฝ๋ ํจ๊ป ์์
# (์์) ์ง์ SQL + ์๋ ๋งคํ
import pymysql
conn = pymysql.connect(host="localhost", user="root", password="1234", db="mydb")
cursor = conn.cursor()
cursor.execute("""
SELECT member_id, name, team_id
FROM members
WHERE member_id = %s
""", (1,))
row = cursor.fetchone() # (1, "jay", 10) ๊ฐ์ ํํ
class Member:
def __init__(self, member_id, name, team_id):
self.member_id = member_id
self.name = name
self.team_id = team_id
member = Member(row[0], row[1], row[2])
print(member.name)
cursor.close()
conn.close()
๋ฌธ์ ๋ ์ฌ๊ธฐ์๋ถํฐ๋ค. ๐ตโ๐ซ
ํ
์ด๋ธ์ด ๋๊ณ , ๊ด๊ณ๊ฐ ๋ณต์กํด์ง๋ฉด ๋งคํ ์ฝ๋๊ฐ ํญ๋ฐํ๋ค. ์ปฌ๋ผ ํ๋ ์ถ๊ฐํด๋ SQL/๋งคํ/ํ
์คํธ๊ฐ ๊ฐ์ด ํ๋ค๋ฆฐ๋ค.
| ์ํฉ | ORM ์์ด ์๊ธฐ๋ ์ผ |
|---|---|
| ์ปฌ๋ผ ์ถ๊ฐ/๋ณ๊ฒฝ | SQL ์์ + ๋งคํ ์ฝ๋ ์์ + ๊ด๋ จ ๋ก์ง ์ํฅ ๋ฒ์ ํ๋ |
| JOIN ์ฆ๊ฐ | SQL์ด ๊ธธ์ด์ง๊ณ ์ฌ์ฌ์ฉ ์ด๋ ค์, ์กฐํ ๋ชฉ์ ๋ง๋ค ์ฟผ๋ฆฌ ํํธํ |
| ๋๋ฉ์ธ ๋ก์ง ํ์ฅ | ๋น์ฆ๋์ค๋ณด๋ค DB ์ฐ๋ ์ฝ๋๊ฐ ๋ ๋ง์์ง๋ ํ์ |
ORM์ ์ฐ๋ฉด ๊ฐ๋ฐ์๋ "ํ
์ด๋ธ" ๋์ "ํด๋์ค"๋ฅผ ์ค์ฌ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ค. ๐งโ๐ป
ORM์ ๋ด๋ถ์์ SQL์ ๋ง๋ค๊ณ ์คํํ ๋ค ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด๋ก ๋๋ ค์ค๋ค.
[ํ๋ฆ]
1) ํด๋์ค(๋ชจ๋ธ) ์ ์ = ํ
์ด๋ธ ๋งคํ ์ ๋ณด
2) session.get/query = ์กฐํ ์๋๋ง ํํ
3) ORM์ด SQL ์์ฑ/์คํ
4) ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด๋ก ๊ตฌ์ฑํด์ ๋ฐํ
5) ์์ ์ ๊ฐ์ฒด ๋ณ๊ฒฝ โ ORM์ด UPDATE๋ก ๋ณํ
# (์์) SQLAlchemy ์คํ์ผ ์์ฌ ์ฝ๋ (๊ฐ๋
๋ณด์ฌ์ฃผ๊ธฐ์ฉ)
# ์ค์ ์ค์ /์์ง/์ธ์
์์ฑ์ ํ๋ก์ ํธ ๊ตฌ์กฐ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ค
class Team:
id: int
name: str
class Member:
id: int
name: str
team: Team # FK ์ซ์๊ฐ ์๋๋ผ "๊ฐ์ฒด ์ฐธ์กฐ"์ฒ๋ผ ๋ค๋ฃฌ๋ค
member = session.get(Member, 1) # PK๋ก ์กฐํ (ORM์ด SELECT๋ฅผ ๋ง๋ ๋ค)
print(member.name)
print(member.team.name) # ๊ด๊ณ ํ์ (ํ์ํ๋ฉด JOIN/์ถ๊ฐ ์ฟผ๋ฆฌ)
ํต์ฌ์ ์ด๊ฑฐ๋ค. ๐ฏ
SQL์ "์ง์ ์์ฑ"ํ๋ ์๊ฐ์ด ์ค๊ณ , ๋์ ๊ฐ์ฒด ๋ชจ๋ธ๋ง๊ณผ ๋ก์ง์ ์ง์คํ๊ฒ ๋๋ค.
| ๊ธฐ๋ฅ | ๋ฌด์จ ์๋ฏธ์ธ๊ฐ | ๊ฐ๋ฐ์๊ฐ ์ฒด๊ฐํ๋ ๋ณํ |
|---|---|---|
| โ ๋งคํ ์๋ํ | ํ ์ด๋ธ โ ํด๋์ค, ํ โ ๊ฐ์ฒด ๋ณํ | row[0], row[1] ๊ฐ์ ์๋ ๋งคํ ์ ๊ฑฐ |
| โ SQL ์์ฑ | ์กฐํ/์ ์ฅ ์๋๋ฅผ SQL๋ก ๋ณํ | ๋ฐ๋ณต SQL ์์ฑ ๊ฐ์, ์ค์ ๊ฐ์ |
| โ ๊ด๊ณ ๊ด๋ฆฌ | FK๋ฅผ ๊ฐ์ฒด ์ฐธ์กฐ์ฒ๋ผ ์ฌ์ฉ | member.team.name ๊ฐ์ ํ์ ๊ฐ๋ฅ |
| โ ๋ณ๊ฒฝ ๊ฐ์ง | ๊ฐ์ฒด ๋ณ๊ฒฝ ์ฌํญ์ ์ถ์ | ๊ฐ ๋ฐ๊พธ๋ฉด UPDATE ์๋ ๋ฐ์ ๊ฐ๋ฅ |
| โ ์บ์/์ผ๊ด์ฑ(Identity Map) | ๊ฐ์ PK๋ ๊ฐ์ ๊ฐ์ฒด๋ก ๊ด๋ฆฌ(์ธ์ ๋จ์) | ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ๊ฐ์ฒด๋ก ๋ค๋ฃจ๋ฉฐ ๊ผฌ์ด๋ ๋ฌธ์ ๊ฐ์ |
[์ง์ SQL]
Python ์ฝ๋
|
| 1) SQL ๋ฌธ์์ด ์์ฑ
v
DB Driver (pymysql ๋ฑ)
|
| 2) SQL ์ ์ก
v
Database
|
| 3) row(ํํ/๋์
๋๋ฆฌ) ๋ฐํ
v
Python ์ฝ๋
|
| 4) row โ ๊ฐ์ฒด ์๋ ๋ณํ
v
๋๋ฉ์ธ ๊ฐ์ฒด ์ฌ์ฉ
[ORM]
Python ์ฝ๋ (๊ฐ์ฒด ์ค์ฌ)
|
| 1) "์๋"๋ง ํํ(session.get / query)
v
ORM (SQL ์์ฑ + ๋งคํ + ๋ณ๊ฒฝ ๊ฐ์ง)
|
| 2) SQL ์์ฑ/์คํ
v
Database
|
| 3) ๊ฒฐ๊ณผ ์์
v
ORM
|
| 4) row โ ๊ฐ์ฒด ์๋ ๋ณํ
v
๋๋ฉ์ธ ๊ฐ์ฒด ์ฌ์ฉ
์๋๋ค. ORM์ ๋ง๋ฅ์ด ์๋๋ค. ๋์ ํธ๋ ์ด๋์คํ๊ฐ ์๋ค. ๐
๊ด๊ณ๋ฅผ ์ (.)์ผ๋ก ํธํ๊ฒ ํ์ํ๋ค๊ฐ, ๋ฐ๋ณต๋ฌธ ์์์ ๋งค๋ฒ ์ถ๊ฐ ์กฐํ๊ฐ ๋ฐ์ํ๋ฉด ์ฟผ๋ฆฌ๊ฐ ํญ๋ฐํ๋ค. ๐ฅ
[์์ ์ํฉ]
members 100๋ช
์กฐํ (1๋ฒ)
for member in members:
member.team.name ์ ๊ทผ (ํ์ 100๋ฒ ์ถ๊ฐ ์กฐํ)
์ด 101๋ฒ ์ฟผ๋ฆฌ = 1 + 100 โ ์ด๊ฒ์ด N+1์ ์ ํ์ ํํ
ํด๊ฒฐ์ ๋ณดํต "ํ ๋ฒ์ ๊ฐ์ ธ์ค๊ฒ" ๋ง๋๋ ์ ๋ต(์กฐ์ธ ๋ก๋ฉ/ํ๋ฆฌํจ์น ๋ฑ)์ ์ ํํ๋ ๋ฐฉ์์ผ๋ก ํ๋ค. ORM์ ์ฐ๋ฉด ์ด๋ฐ ์ฑ๋ฅ ์ด์๋ฅผ ๋ ์ฝ๊ฒ ๋ง๋ค ์๋ ์๊ณ , ๋ฐ๋๋ก ๋ ์ฝ๊ฒ ํด๊ฒฐํ ์๋ ์๋ค.
๋ณต์กํ GROUP BY, ์๋์ฐ ํจ์, ๋์ฉ๋ ํต๊ณ ์ฟผ๋ฆฌ๋ ORM๋ณด๋ค SQL์ด ๋ ์ง๊ด์ ์ธ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. ๐
์ด๋ด ๋ ORM์ ์ฐ๋๋ผ๋ "Raw SQL"์ ์๋ ์ ํ์ ํ๊ธฐ๋ ํ๋ค.
| ํค์๋ | ํต์ฌ ๋ฌธ์ฅ |
|---|---|
| ORM | ๊ฐ์ฒด์งํฅ ์ฝ๋์ ๊ด๊ณํ DB ์ฌ์ด๋ฅผ ์ฐ๊ฒฐํ๋ ํต์ญ ์์คํ ์ด๋ค |
| ORM ์์ด | SQL ์์ฑ + ๊ฒฐ๊ณผ ์๋ ๋งคํ์ด ๋ฐ๋ณต๋์ด ์ฝ๋๊ฐ ๋น๋ํด์ง๊ธฐ ์ฝ๋ค |
| ORM ์ฌ์ฉ | ํด๋์ค ์ค์ฌ์ผ๋ก ๊ฐ๋ฐํ๊ณ SQL ์์ฑ/๋งคํ/๋ณ๊ฒฝ ๊ฐ์ง๋ฅผ ์๋ํํ๋ค |
| ์ฃผ์์ | N+1 ๊ฐ์ ์กฐํ ์ ๋ต ๋ฌธ์ ๋ฅผ ์ดํดํด์ผ ํ๋ค |
๊ฒฐ๋ก โจ
ORM์ ๊ฐ๋ฐ์๊ฐ SQL์ ๋ ์ฐ๊ฒ ํด์ฃผ๋ ๋๊ตฌ๊ฐ ์๋๋ผ, ๊ฐ์ฒด ์ค์ฌ์ผ๋ก ์์ ํ๊ฒ DB๋ฅผ ๋ค๋ฃจ๊ฒ ํด์ฃผ๋ ๊ตฌ์กฐ๋ค.