[FastAPI] 14. SQLAlchemy์˜ One-to-Many, Many-to-Many, Self referential relationship

๋ฐ˜์‘ํ˜•

์ง€๋‚œ ํฌ์ŠคํŠธ์—์„œ๋Š” ๋‹จ์ˆœ Column ๋ฐ์ดํ„ฐ์™€ ๊ทธ๋ฆฌ๊ณ , ๋‹จ์ผ ์™ธ๋ž˜ํ‚ค ํ•˜๋‚˜์˜ ๊ด€๊ณ„ ๋ฐ์ดํ„ฐ๋ฅผ Pydantic์œผ๋กœ ๋งคํ•‘ํ•˜์—ฌ Serialize/Deserialize ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” Many-to-Many, One-to-Many ํ˜•ํƒœ์˜ Foreign Key๊ฐ€ ๊ฑธ๋ ค ์žˆ๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฅผ Joinํ•ด์„œ ๊ฐ€์ ธ์˜ฌ ๋–„ ์–ด๋–ป๊ฒŒ Pydantic ๋ชจ๋ธ๊ณผ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

DB์—์„œ ๋‹จ์ˆœํ•˜๊ฒŒ ์ ‘๊ทผ

์ง€๋‚œ ํฌ์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ•œ ERD๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

Category์™€ Post๊ฐ€ ์žˆ๊ณ , Post๋Š” category_id๋ฅผ ์™ธ๋ž˜ํ‚ค๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋ฐ์ดํ„ฐ๋ฅผ category ํ…Œ์ด๋ธ”์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๊ฑด๋ฐ, ์šฐ๋ฆฌ๊ฐ€ ์ด ์ •๋ณด๋ฅผ ๋ชจ๋‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

 

select * from post as p join category as c on p.category_id = c.id where p.id = ?

ํŠน์ • Post ์ปจํ…์ธ ์— ๋Œ€ํ•œ Post, Category ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๊ฐ€์ ธ์˜ค๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ, ๊ฐ„๋‹จํžˆ ์œ„ Query๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ๋Š” ๋‹จ์ˆœ ๊ด€๊ณ„๊ฐ€ ํ•˜๋‚˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ฆฌ ์–ด๋ ต์ง€ ์•Š๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

ORM์—์„œ ์ ‘๊ทผ

ํ…Œ์ด๋ธ” ๊ฐ„ ์—ฐ๊ด€ ๊ด€๊ณ„๊ฐ€ ์žˆ์„ ๋•Œ ๊ฐ์ฒด ์ง€ํ–ฅ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • DB์˜ ์™ธ๋ž˜ํ‚ค ์‚ฌ์šฉ
  • SQLAlchemy์˜ entity ๊ฐ์ฒด ์ฐธ์กฐ

 

๊ทธ๋Ÿฌ๋‚˜ ORM์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ฐ€๊ธ‰์  ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•ด์„œ ๊ด€๊ณ„๋ฅผ ๋งบ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. DB์˜ ์™ธ๋ž˜ํ‚ค๋ฅผ ์‚ฌ์šฉํ•œ ๊ด€๊ณ„๋Š” ํ…Œ์ด๋ธ” ์ค‘์‹ฌ์˜ ๋ชจ๋ธ๋ง ์„ค๊ณ„์‹œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ๋ฐ, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์™ธ๋ž˜ํ‚ค์— ์˜์กดํ•˜๋ฏ€๋กœ ๊ฐ์ฒด์ง€ํ–ฅ์Šค๋Ÿฝ์ง€ ๋ชปํ•œ ํ˜•ํƒœ๋ฅผ ๋ณด์—ฌ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๋”ฐ๋ผ์„œ ๊ฐ์ฒด ์ค‘์‹ฌ์œผ๋กœ ๊ด€๊ณ„๋ฅผ ๋งคํ•‘ํ•˜๊ณ  ๋ชจ๋ธ๋ง ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. 

๋‹จ, ํ•„์š”์— ๋”ฐ๋ผ์„œ ์™ธ๋ž˜ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ทธ ๊ด€๊ณ„๋œ ๋ฐ์ดํ„ฐ์˜ ์‚ญ์ œ๋‚˜ ์‚ฝ์ž…์„ DB์— ์˜์กดํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ, ์„ค๊ณ„๋Š” ๊ฐ์ฒด์ง€ํ–ฅ์ ์œผ๋กœ ์„ค๊ณ„ํ•˜๋˜, ์™ธ๋ž˜ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ๋‚˜์˜์ง€ ์•Š์€ ์„ ํƒ์ž…๋‹ˆ๋‹ค.

 

SQLAlchemy์—์„œ๋Š” Core์™€ ORM์ด ์กด์žฌํ•˜๋Š”๋ฐ, Core๋Š” SQLAlchemy์—์„œ ์ œ๊ณตํ•˜๋Š” Syntax(such as Linq)์ด๊ณ , ORM์€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ ORM์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ๋ฐ, ORM์—์„œ๋Š” relationship์„ ์ด์šฉํ•ด ์™ธ๋ž˜ํ‚ค๊ฐ€ ๊ฑธ๋ ค ์žˆ๋Š” ํ…Œ์ด๋ธ”์„ Joinํ•˜์—ฌ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

์ง€๋‚œ ํฌ์ŠคํŠธ์˜ ๋‚ด์šฉ์„ ๋ณด๋ฉด Post๊ฐ€ ํ•˜๋‚˜์˜ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” Many-to-One ํ˜•ํƒœ์˜ ๊ด€๊ณ„ ๋ฐ์ดํ„ฐ๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ดค๋Š”๋ฐ์š”. ์ด๋Ÿฐ ๊ฒฝ์šฐ๋Š” ๊ฐ„๋‹จํžˆ relationship์— foreign_key ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋ฉด ์ž๊ธฐ ์ž์‹ ์˜ ํ…Œ์ด๋ธ”์„ ๋ฐ”๋ผ๋ณด๋Š” One-to-Many ํ˜•ํƒœ์˜ relationship์€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

 

 

 

์ž๊ธฐ ์ฐธ์กฐ ๊ด€๊ณ„ (Self referential relationship)

์ž๊ธฐ ์ž์‹ ์˜ ํ…Œ์ด๋ธ”์˜ ID๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ์˜ ๊ด€๊ณ„ ๋ฐ์ดํ„ฐ๋ฅผ SQLAlchemy์—์„œ๋Š” Self referential relationship์ด๋ผ๊ณ  ์ด์•ผ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค. 

 

์šฐ๋ฆฌ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ ํ…Œ์ด๋ธ”์—์„œ ํ•˜๋‚˜์˜ ์นดํ…Œ๊ณ ๋ฆฌ๋Š” ๋ถ€๋ชจ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์ง€๋‹ ์ˆ˜๋„ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ์„ค๊ณ„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ ๋ง์€ ์ž์‹ ์ด ๋ถ€๋ชจ ์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ๋  ์ˆ˜๋„ ์žˆ๊ณ , ์ž์‹ ์นดํ…Œ๊ณ ๋ฆฌ๋„ ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ฐ์ฒด์ง€ํ–ฅ์ ์œผ๋กœ ์„ค๊ณ„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

๋‚˜์˜ ๋ถ€๋ชจ ์นดํ…Œ๊ณ ๋ฆฌ๋Š” ๋‹จ ํ•œ ๊ฐœ๋งŒ ์กด์žฌํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ๊ทธ ๋ถ€๋ชจ์— ๋Œ€ํ•œ ๋ถ€๋ชจ ์นดํ…Œ๊ณ ๋ฆฌ๋„ ํ•˜๋‚˜ ์กด์žฌํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ parents๋ผ๊ณ  ํ‘œ๊ธฐํ•ฉ๋‹ˆ๋‹ค. children์€ ๋‚˜๋ฅผ ๋ถ€๋ชจ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ์„ ํƒํ•œ ์นดํ…Œ๊ณ ๋ฆฌ๋“ค์ด ๋ชจ๋‘ ์„ ํƒ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋‹จ, ์ด๋ ‡๊ฒŒ ์„ค๊ณ„ํ•˜๋Š” ๊ฒฝ์šฐ ๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜ํ•ด์•ผํ•˜๋Š” ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • ์›์น™์ ์œผ๋กœ ๊นŠ์ด ๊ฐฏ์ˆ˜๋ฅผ ์ œํ•œํ•˜์ง€ ์•Š์œผ๋‚˜, ๊นŠ์ด๋ฅผ ๋งŽ์ด ์ค„์ˆ˜๋ก ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋Š๋ ค์ง€๋ฏ€๋กœ ์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค
  • ๋ถ€๋ชจ์™€ ์ž์‹ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ๋™์‹œ์— ๋กœ๋”ฉํ•˜์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.

 

๋ณด๋‹ค์‹œํ”ผ ํŠธ๋ฆฌ ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ๋˜์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋กœ์˜ ๊ด€๊ณ„ ๋กœ๋”ฉ์„ ๋‘ ๊ฐœ ๋™์‹œ์— ์ด๋ฃฐ ๊ฒฝ์šฐ ์„œ๋กœ๊ฐ€ ์„œ๋กœ์˜ ๋ถ€๋ชจ, ์ž์‹ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ๊ณ„์† ๋กœ๋”ฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์žฌ๊ท€ ์ง€์˜ฅ(๋ฌดํ•œ ์ฐธ์กฐ)์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‘˜ ์ค‘ ํ•œ ๊ฐ€์ง€์˜ ๊ด€๊ณ„๋งŒ์„ ๋กœ๋”ฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

 

 

SQLAlchemy์—์„œ๋Š” lazy ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์€ relationship๊ณผ ๊ฐ™์€ ๊ด€๊ณ„ ๊ฐ์ฒด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋‹ค์–‘ํ•œ ์˜ต์…˜์„ ์„ ํƒํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ด๋ฅผ noload๋กœ ์„ค์ •ํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ORM ๊ฐ์ฒด๋ฅผ ๋กœ๋”ฉํ•  ๋•Œ ํ•ด๋‹น ๊ด€๊ณ„ ๊ฐ์ฒด๋Š” ๋กœ๋”ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ API๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋Š” parents๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋„ ์žˆ๊ณ , children์„ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ, Entity ํด๋ž˜์Šค๋ฅผ API ๊ฐฏ์ˆ˜๋งŒํผ ๋งŒ๋“ค์–ด ์ ์šฉํ•ด์•ผ ํ•˜๋‚˜์š”?

 

SQLAlchemy์—์„œ๋Š” ํ•˜๋‚˜์˜ ํ…Œ์ด๋ธ”์— ๋ณต์ˆ˜์˜ Entity ๊ฐ์ฒด๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ํ…Œ์ด๋ธ” ์ด๋ฆ„์ด category ์ผ ๋•Œ, ๋™์ผํ•œ ํ…Œ์ด๋ธ” ์ด๋ฆ„์ด ๊ฐ–๋Š” Entity ๊ฐ์ฒด๋ฅผ ๋งŒ๋‚˜๋ฉด ๋ฐ”๋กœ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋Ÿด ๋•Œ๋Š” ORM ๋ชจ๋ธ์„ ๋ฐ”๋กœ ๋กœ๋”ฉํ•˜๊ธฐ ๋ณด๋‹จ, SQLAlchemy Core๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

์œ„์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ์›ํ•˜๋Š” relationship์„ ํ•จ์ˆ˜๋ณ„๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒฝ์šฐ ORM ๋ชจ๋ธ์— ์žˆ๋Š” lazy ์˜ต์…˜์„ ๋ชจ๋‘ noload๋กœ ํ•ด์•ผํ•˜๋ฉฐ, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ•ด๋‹น ๋ชจ๋ธ์„ ๋”ฐ๋ผ๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

 

 

Self referential in Pydantic

๊ทธ๋ ‡๋‹ค๋ฉด Pydantic ๋ชจ๋ธ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? ํŒŒ์ด์ฌ์—์„œ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  ์ž๊ธฐ ์ž์‹ ์˜ ๋ชจ๋ธ์„ property ํƒ€์ž…์œผ๋กœ ๋„ฃ์„ ๋•Œ๋Š” '' ๋”ฐ์˜ดํ‘œ๋ฅผ ๋„ฃ์–ด ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

ํ•˜์ง€๋งŒ Pydantic์—์„œ ์ด๋Ÿฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ForwardRef error๋ฅผ ๋‚ด๋ฟœ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€์—์„œ๋Š” update_forward_refs ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ์ง€์‹œํ•˜๋Š”๋ฐ, ์ด ๋ฉ”์„œ๋“œ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”?

 

update_forward_refs๋Š” ๋ฌธ์ž์—ด๋กœ ์„ ์ฐธ์กฐ๋œ ๋ชจ๋ธ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋‹ค์‹œ class ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๋…€์„์ž…๋‹ˆ๋‹ค.

 

์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋ชจ๋“  ํ•„๋“œ์˜ ๊ฐ’์„ ๊ฐ€์ ธ์™€ ํด๋ž˜์Šค ์ฐธ์กฐํ•˜๊ณ , json_encoders์˜ ์˜ต์…˜๋„ ๊ฐ™์ด ์ ์šฉ์‹œ์ผœ์ฃผ๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ์ž๊ธฐ ์ฐธ์กฐ๊ฐ€ ์ ์šฉ๋œ SQLAlchemy ๋ชจ๋ธ์„ Pydantic ๋ชจ๋ธ๋กœ ์‰ฝ๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

Many-to-Many

many-to-many ์—ฐ๊ด€ ๊ด€๊ณ„๋Š” ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๋ผ๊ณ ๋„ ํ•˜๋ฉฐ ์‹ค์ œ ํ…Œ์ด๋ธ” ์ค‘์‹ฌ์˜ ๋ชจ๋ธ๋ง์—์„œ๋Š” ์ž˜ ๋‚˜์˜ค์ง€ ์•Š๋Š” ์—ฐ๊ด€ ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ์—ˆ์„ ๋•Œ ์–‘์ชฝ ์„œ๋กœ ๋ชจ๋‘๊ฐ€ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ด€๊ณ„๋ฅผ ๋งํ•˜๋Š”๋ฐ, ์ด ๋•Œ๋Š” ๊ฐ ํ…Œ์ด๋ธ”์— ์„œ๋กœ์˜ ์™ธ๋ž˜ํ‚ค๋ฅผ ์ง€์ •ํ•˜๊ธฐ ๋ณด๋‹จ, ์™ธ๋ž˜ํ‚ค๊ฐ€ ์žˆ๋Š” ํ…Œ์ด๋ธ”์„ ๋Œ€๋ณ€ํ•˜๋Š” Entity ๊ฐ์ฒด๋ฅผ ๋ณ„๋„๋กœ ์ง€์ •ํ•ด์•ผ ์ฐจํ›„ ์„ฑ๋Šฅ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

SQLAlchemy์—์„œ๋Š” ์ด๋ฅผ SQLAlchemy ORM๊ณผ SQLAlchemy Core ๋‘ ๊ฐ€์ง€๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

post_tags๋Š” Post Entity์™€ Tag Entity์˜ ๊ด€๊ณ„๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ด€๋ฆฌ ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์ปจํ…์ธ ๋Š” ๋™์ผํ•œ ํƒœ๊ทธ๋ฅผ ํ•˜๋‚˜๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ PK๋กœ ์ง€์ •ํ•˜๋ฉด ์ค‘๋ณต๋œ ํƒœ๊ทธ๊ฐ€ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์—†๊ณ , ํŠน์ • ํƒœ๊ทธ์— ์–ด๋–ค ๊ธ€์ด ์žˆ๋Š”์ง€ ๋น ๋ฅด๊ฒŒ ์ƒ‰์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ ๋‘ ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” post_tags๋Š” ORM์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  Table์„ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ๊ทธ ์ด์œ ๋Š” API์—์„œ๋Š” ์ด๋“ค์˜ ํ…Œ์ด๋ธ”์„ ์กฐํšŒํ•  ์ผ์ด ์—†์œผ๋ฏ€๋กœ ORM ๋ชจ๋ธ์ด ์•„๋‹Œ ๋‹จ์ˆœ ํ…Œ์ด๋ธ”๋กœ ์ •์˜ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” SQLAlchemy์˜ Core ๋ชจ๋“ˆ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

 

๋˜ TagEntity์˜ posts๋Š” viewonly๋ฅผ True๋กœ ์ง€์ •ํ–ˆ๋Š”๋ฐ, ์ด๋Š” Tag๋ฅผ ๋งŒ๋“ค ๋•Œ ํŠน์ • ์ปจํ…์ธ ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š๊ฒ ๋‹ค๋Š” ๊ฒƒ์ด๋ฉฐ ๋‹จ์ˆœํžˆ ์กฐํšŒ๋งŒ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. SQLAlchemy์—์„œ Many-to-Many๋ฅผ ์ง€์ •ํ•  ๋•Œ๋Š” ์„œ๋กœ์˜ Entity๊ฐ€ relationship์„ ๊ฐ€์ง๊ณ  ์กฐํšŒ/์‚ฝ์ž…ํ•˜๋Š” ํ˜•ํƒœ๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‘˜ ์ค‘ ํ•˜๋‚˜์˜ relationship์€ viewonly๋กœ ๋‘์–ด์•ผ ์„ฑ๋Šฅ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋‘ ๊ฐ์ฒด ๋ฐ์ดํ„ฐ ๋ชจ๋‘๊ฐ€ ์˜ํ–ฅ์„ ๋ฐ›๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

 

๊ฑฐ๊ธฐ์— loading์— ๋Œ€ํ•ด์„œ๋„ ์žฌ๊ท€ ์ง€์˜ฅ(๋ฌดํ•œ ์ฐธ์กฐ)๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ์„œ๋กœ์˜ relationship์ด ๋™์‹œ์— ๋กœ๋”ฉํ•˜์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (์ž๊ธฐ ์ฐธ์กฐ ๊ด€๊ณ„์—์„œ ํ–ˆ๋˜๋Œ€๋กœ ์ง„ํ–‰ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.)

 

 

 

๋งˆ์น˜๋ฉฐ...

ORM์˜ ๋งคํ•‘ ๊ด€๊ณ„์—๋Š” One-to-One, One-to-Many, Many-to-One, Many-to-Many๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ Many-to-Many๋Š” ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ๋ฐฉ๋ฒ•์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ๋ฐ, SQLAlchemy์—์„œ๋Š” ์ด๋ฅผ ๊ฐ€๊ธ‰์  ORM์œผ๋กœ ๋ชจ๋‘ ํ‘œํ˜„ํ•˜์ง€ ์•Š๊ณ , ๊ทธ๋“ค์ด ์–ด๋–ป๊ฒŒ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด์„œ ๋ณ„๋„์˜ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

ํŠนํžˆ ORM์œผ๋กœ ๊ด€๊ณ„ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋”ฉํ•  ๋•Œ ๊ฐ€์žฅ ์ฃผ์˜ํ•ด์•ผ ํ•  ๊ฒƒ์€ ๋ฌดํ•œ ์ฐธ์กฐ์ž…๋‹ˆ๋‹ค. ๊ฐ€๊ธ‰์  ๋ฌดํ•œ ์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๊ฒ ์ง€๋งŒ ๋ฌดํ•œ ์ฐธ์กฐํ•  ์ˆ˜ ๋ฐ–์— ์—†๋Š” ์„ค๊ณ„๊ฐ€ ๋‚˜์™”๋‹ค๋ฉด ์ด๋ฅผ ์ ์ ˆํžˆ ๋กœ๋”ฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ๋„ ํ•˜๋‚˜์˜ ๋ฐฉ๋ฒ•์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Pydantic์„ ์ด์šฉํ•ด์„œ DTO๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ orm_mode๋ฅผ True ๊ฐ’์œผ๋กœ ์ฃผ์–ด SQLAlchemy Entity ๋ชจ๋ธ์„ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ relationship์„ DTO ๋ชจ๋ธ์— ๋ช…์‹œํ•˜์ง€ ์•Š์œผ๋ฉด relationship์˜ ๋กœ๋”ฉ ๋ฐฉ๋ฒ•๊ณผ ๊ด€๊ณ„ ์—†์ด ์ง€๋‚˜๊ฐ€๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Š” DTO ๋ชจ๋ธ์— ๋ณ€ํ™˜ ๋ฐ์ดํ„ฐ๋กœ ๋„ฃ์ง€ ์•Š์„ ๋ฟ ์‹ค์ œ๋กœ DB์—์„œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด์„œ Pydantic์— ๋‹จ์ˆœํžˆ relationship ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฃผ์ง€ ์•Š๋Š” ๊ฒƒ์ด ๋๋‚˜์ง€ ์•Š๊ณ  ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด์„œ๋Š” loading ํ•˜์ง€ ์•Š๋„๋ก ๊ตฌํ˜„ํ•ด์ฃผ์„ธ์š”.

 

๋ฐ˜์‘ํ˜•
TAGS.

Tistory Comments