Browse Source

๐ŸŒ Add Korean translation for `docs/ko/docs/tutorial/sql-databases.md` (#13093)

pull/13107/head
Geumbin 3 months ago
committed by GitHub
parent
commit
eece6344f5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 360
      docs/ko/docs/tutorial/sql-databases.md

360
docs/ko/docs/tutorial/sql-databases.md

@ -0,0 +1,360 @@
# SQL (๊ด€๊ณ„ํ˜•) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
**FastAPI**์—์„œ SQL(๊ด€๊ณ„ํ˜•) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉ์€ ํ•„์ˆ˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์ด ์›ํ•˜๋Š” **์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋“ ** ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์„œ๋Š” <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel</a>์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
**SQLModel**์€ <a href="https://www.sqlalchemy.org/" class="external-link" target="_blank">SQLAlchemy</a>์™€ Pydantic์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋˜์—ˆ์Šต๋‹ˆ๋‹ค.SQLModel์€ **SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค**๋ฅผ ์‚ฌ์šฉํ•˜๋Š” FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์™„๋ฒฝํžˆ ์–ด์šธ๋ฆฌ๋„๋ก **FastAPI**์˜ ์ œ์ž‘์ž๊ฐ€ ์„ค๊ณ„ํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.
/// tip | ํŒ
๋‹ค๋ฅธ SQL ๋˜๋Š” NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค (์ผ๋ถ€๋Š” <abbr title="๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํผ(Object Relational Mapper), SQL ํ…Œ์ด๋ธ”์„ ๋‚˜ํƒ€๋‚ด๋Š” ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ  ํ…Œ์ด๋ธ”์˜ ํ–‰์„ ์ธ์Šคํ„ด์Šค๋กœ ํ‘œํ˜„ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ง€์นญํ•˜๋Š” ์šฉ์–ด">"ORM"</abbr>์ด๋ผ๊ณ ๋„ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค), FastAPI๋Š” ํŠน์ • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์‚ฌ์šฉ์„ ๊ฐ•์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž
///
SQLModel์€ SQLAlchemy๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฏ€๋กœ, SQLAlchemy์—์„œ **์ง€์›ํ•˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค**๋ฅผ ์†์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(SQLModel์—์„œ๋„ ๋™์ผํ•˜๊ฒŒ ์ง€์›๋ฉ๋‹ˆ๋‹ค). ์˜ˆ๋ฅผ ๋“ค๋ฉด:
* PostgreSQL
* MySQL
* SQLite
* Oracle
* Microsoft SQL Server ๋“ฑ.
์ด ์˜ˆ์ œ์—์„œ๋Š” **SQLite**๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. SQLite๋Š” ๋‹จ์ผ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๊ณ  ํŒŒ์ด์ฌ์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ์˜ˆ์ œ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•˜์—ฌ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‚˜์ค‘์— ์‹ค์ œ ํ”„๋กœ๋•์…˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” **PostgreSQL**๊ณผ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
/// tip | ํŒ
**FastAPI**์™€ **PostgreSQL**๋ฅผ ํฌํ•จํ•˜์—ฌ ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋‹ค์–‘ํ•œ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ณต์‹ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ๊ธฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: <a href="https://github.com/fastapi/full-stack-fastapi-template" class="external-link" target="_blank">https://github.com/fastapi/full-stack-fastapi-template</a>
///
์ด ํŠœํ† ๋ฆฌ์–ผ์€ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ณ  ์งง์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ธฐ๋ณธ ๊ฐœ๋…, SQL, ๋˜๋Š” ๋” ๋ณต์žกํ•œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด, <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel ๋ฌธ์„œ</a>๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.
## `SQLModel` ์„ค์น˜ํ•˜๊ธฐ
๋จผ์ €, [๊ฐ€์ƒ ํ™˜๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์„ ์ƒ์„ฑํ•˜๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ, `sqlmodel`์„ ์„ค์น˜ํ•˜์„ธ์š”:
<div class="termy">
```console
$ pip install sqlmodel
---> 100%
```
</div>
## ๋‹จ์ผ ๋ชจ๋ธ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑํ•˜๊ธฐ
์šฐ์„  ๋‹จ์ผ **SQLModel** ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์ฒซ ๋ฒˆ์งธ ๋ฒ„์ „์„ ์ƒ์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์ดํ›„ **๋‹ค์ค‘ ๋ชจ๋ธ**์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ณด์•ˆ๊ณผ ์œ ์—ฐ์„ฑ์„ ๊ฐ•ํ™”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿค“
### ๋ชจ๋ธ ์ƒ์„ฑํ•˜๊ธฐ
`SQLModel`์„ ๊ฐ€์ ธ์˜ค๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *}
`Hero` ํด๋ž˜์Šค๋Š” Pydantic ๋ชจ๋ธ๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค (์‹ค์ œ๋กœ ๋‚ด๋ถ€์ ์œผ๋กœ *Pydantic ๋ชจ๋ธ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค*).
๋ช‡ ๊ฐ€์ง€ ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:
* `table=True`๋Š” SQLModel์— ์ด ๋ชจ๋ธ์ด *ํ…Œ์ด๋ธ” ๋ชจ๋ธ*์ด๋ฉฐ, ๋‹จ์ˆœํ•œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์ด ์•„๋‹ˆ๋ผ SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ **ํ…Œ์ด๋ธ”**์„ ๋‚˜ํƒ€๋‚ธ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. (๋‹ค๋ฅธ ์ผ๋ฐ˜์ ์ธ Pydantic ํด๋ž˜์Šค์ฒ˜๋Ÿผ) ๋‹จ์ˆœํ•œ *๋ฐ์ดํ„ฐ ๋ชจ๋ธ*์ด ์•„๋‹™๋‹ˆ๋‹ค.
* `Field(primary_key=True)`๋Š” SQLModel์— `id`๊ฐ€ SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ **๊ธฐ๋ณธ ํ‚ค**์ž„์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค (SQL ๊ธฐ๋ณธ ํ‚ค์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ SQLModel ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”).
`int | None` ์œ ํ˜•์œผ๋กœ ์„ค์ •ํ•˜๋ฉด, SQLModel์€ ํ•ด๋‹น ์—ด์ด SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ `INTEGER` ์œ ํ˜•์ด๋ฉฐ `NULLABLE` ๊ฐ’์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
* `Field(index=True)`๋Š” SQLModel์— ํ•ด๋‹น ์—ด์— ๋Œ€ํ•ด **SQL ์ธ๋ฑ์Šค**๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ด ์—ด์œผ๋กœ ํ•„ํ„ฐ๋ง๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ๋•Œ ๋” ๋น ๋ฅด๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
SQLModel์€ `str`์œผ๋กœ ์„ ์–ธ๋œ ํ•ญ๋ชฉ์ด SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ `TEXT` (๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋”ฐ๋ผ `VARCHAR`) ์œ ํ˜•์˜ ์—ด๋กœ ์ €์žฅ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค.
### ์—”์ง„ ์ƒ์„ฑํ•˜๊ธฐ
SQLModel์˜ `engine` (๋‚ด๋ถ€์ ์œผ๋กœ๋Š” SQLAlchemy `engine`)์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ **์—ฐ๊ฒฐ์„ ์œ ์ง€**ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
**ํ•˜๋‚˜์˜ ๋‹จ์ผ engine ๊ฐ์ฒด**๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ ์ „์ฒด์—์„œ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *}
`check_same_thread=False`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด FastAPI์—์„œ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์—์„œ ๋™์ผํ•œ SQLite ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” **ํ•˜๋‚˜์˜ ๋‹จ์ผ ์š”์ฒญ**์ด **์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ**๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: ์˜์กด์„ฑ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ).
๊ฑฑ์ •ํ•˜์ง€ ๋งˆ์„ธ์š”. ์ฝ”๋“œ๊ฐ€ ๊ตฌ์กฐํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด, ์ดํ›„์— **๊ฐ ์š”์ฒญ๋งˆ๋‹ค ๋‹จ์ผ SQLModel *์„ธ์…˜*์„ ์‚ฌ์šฉ**ํ•˜๋„๋ก ๋ณด์žฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๊ทธ๊ฒƒ์ด `check_same_thread`๊ฐ€ ํ•˜๋ ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
### ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•˜๊ธฐ
๊ทธ ๋‹ค์Œ `SQLModel.metadata.create_all(engine)`์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  *ํ…Œ์ด๋ธ” ๋ชจ๋ธ*์˜ **ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑ**ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *}
### ์„ธ์…˜ ์˜์กด์„ฑ ์ƒ์„ฑํ•˜๊ธฐ
**`Session`**์€ **๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ์ฒด**๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ฐ์ดํ„ฐ์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถ”์ ํ•œ ํ›„, **`engine`์„ ํ†ตํ•ด** ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค.
`yield`๋ฅผ ์‚ฌ์šฉํ•ด FastAPI์˜ **์˜์กด์„ฑ**์„ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ ์š”์ฒญ๋งˆ๋‹ค ์ƒˆ๋กœ์šด `Session`์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์š”์ฒญ๋‹น ํ•˜๋‚˜์˜ ์„ธ์…˜๋งŒ ์‚ฌ์šฉ๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๐Ÿค“
๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ์˜์กด์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐ„์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด `Annotated` ์˜์กด์„ฑ `SessionDep`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *}
### ์‹œ์ž‘ ์‹œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•˜๊ธฐ
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *}
์—ฌ๊ธฐ์„œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์ด๋ฒคํŠธ ์‹œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์‹คํ–‰๋˜๋Š” ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ๐Ÿค“
/// tip | ํŒ
SQLModel์€ Alembic์„ ๊ฐ์‹ธ๋Š” ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์ œ๊ณตํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ˜„์žฌ <a href="https://alembic.sqlalchemy.org/en/latest/" class="external-link" target="_blank">Alembic</a>์„ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
///
### Hero ์ƒ์„ฑํ•˜๊ธฐ
๊ฐ SQLModel ๋ชจ๋ธ์€ Pydantic ๋ชจ๋ธ์ด๊ธฐ๋„ ํ•˜๋ฏ€๋กœ, Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” **ํƒ€์ž… ์–ด๋…ธํ…Œ์ด**์…˜์—์„œ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ `Hero` ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•˜๋ฉด **JSON ๋ณธ๋ฌธ**์—์„œ ๊ฐ’์„ ์ฝ์–ด์˜ต๋‹ˆ๋‹ค.
๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ํ•จ์ˆ˜์˜ **๋ฐ˜ํ™˜ ํƒ€์ž…**์œผ๋กœ ์„ ์–ธํ•˜๋ฉด ํ•ด๋‹น ๋ฐ์ดํ„ฐ์˜ ๊ตฌ์กฐ๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” API ๋ฌธ์„œ์˜ UI์— ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *}
</details>
์—ฌ๊ธฐ์„œ `SessionDep` ์˜์กด์„ฑ (์ฆ‰, `Session`)์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด `Hero`๋ฅผ `Session` ์ธ์Šคํ„ด์Šค์— ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ปค๋ฐ‹ํ•˜๊ณ , `hero` ๋ฐ์ดํ„ฐ์˜ ์ตœ์‹  ์ƒํƒœ๋ฅผ ๊ฐฑ์‹ ํ•œ ๋‹ค์Œ ์ด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
### Heroes ์กฐํšŒํ•˜๊ธฐ
`select()`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ `Hero`๋ฅผ **์กฐํšŒ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์— ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด `limit`์™€ `offset`์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *}
### ๋‹จ์ผ Hero ์กฐํšŒํ•˜๊ธฐ
๋‹จ์ผ `Hero`๋ฅผ **์กฐํšŒ**ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *}
### Hero ์‚ญ์ œํ•˜๊ธฐ
`Hero`๋ฅผ **์‚ญ์ œ**ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *}
### ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ํ•˜๊ธฐ
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
<div class="termy">
```console
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
๊ทธ๋Ÿฐ ๋‹ค์Œ `/docs` UI๋กœ ์ด๋™ํ•˜๋ฉด, **FastAPI**๊ฐ€ ํ•ด๋‹น **model๋“ค**์„ ์‚ฌ์šฉํ•˜์—ฌ API **๋ฌธ์„œ๋ฅผ ์ƒ์„ฑ**ํ•˜๋Š” ๊ฒƒ์œผ๋ฅด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด ๋ชจ๋ธ๋“ค์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ง๋ ฌํ™”ํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋Š” ๋ฐ์—๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
<div class="screenshot">
<img src="/img/tutorial/sql-databases/image01.png">
</div>
## ์—ฌ๋Ÿฌ ๋ชจ๋ธ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์—…๋ฐ์ดํŠธ
์ด์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์•ฝ๊ฐ„ **๋ฆฌํŒฉํ† ๋ง**ํ•˜์—ฌ **๋ณด์•ˆ**๊ณผ **์œ ์—ฐ์„ฑ**์„ ๊ฐœ์„ ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์ด์ „ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ UI๋ฅผ ๋ณด๋ฉด, ์ง€๊ธˆ๊นŒ์ง€๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ƒ์„ฑํ•  `Hero`์˜ `id`๋ฅผ ์ง์ ‘ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ฑ
์ด๋Š” ํ—ˆ์šฉ๋˜์–ด์„  ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด๋ฏธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ `id`๋ฅผ ๋ฎ์–ด์“ธ ์œ„ํ—˜์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. `id`๋Š” **๋ฐฑ์—”๋“œ** ๋˜๋Š” **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค**๊ฐ€ ๊ฒฐ์ •ํ•ด์•ผ ํ•˜๋ฉฐ, **ํด๋ผ์ด์–ธํŠธ**๊ฐ€ ๊ฒฐ์ •ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ hero์˜ `secret_name`์„ ์ƒ์„ฑํ•˜๊ธด ํ–ˆ์ง€๋งŒ, ์ง€๊ธˆ๊นŒ์ง€๋Š” ์ด ๊ฐ’์„ ์–ด๋””์—์„œ๋‚˜ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ทธ๋‹ค์ง€ **๋น„๋ฐ€์Šค๋Ÿฝ์ง€** ์•Š์Šต๋‹ˆ๋‹ค... ๐Ÿ˜…
์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ **์ถ”๊ฐ€ ๋ชจ๋ธ**์„ ์ถ”๊ฐ€ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์—ฌ๊ธฐ์„œ SQLModel์ด ๋น›์„ ๋ฐœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. โœจ
### ์—ฌ๋Ÿฌ ๋ชจ๋ธ ์ƒ์„ฑํ•˜๊ธฐ
**SQLModel**์—์„œ `table=True`๊ฐ€ ์„ค์ •๋œ ๋ชจ๋ธ ํด๋ž˜์Šค๋Š” **ํ…Œ์ด๋ธ” ๋ชจ๋ธ**์ž…๋‹ˆ๋‹ค.
`table=True`๊ฐ€ ์—†๋Š” ๋ชจ๋ธ ํด๋ž˜์Šค๋Š” **๋ฐ์ดํ„ฐ ๋ชจ๋ธ**๋กœ, ์ด๋Š” ์‹ค์ œ๋กœ ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋œ Pydantic ๋ชจ๋ธ์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. ๐Ÿค“
SQLModel์„ ์‚ฌ์šฉํ•˜๋ฉด **์ƒ์†**์„ ํ†ตํ•ด ๋ชจ๋“  ๊ฒฝ์šฐ์— ํ•„๋“œ๋ฅผ **์ค‘๋ณต ์„ ์–ธํ•˜์ง€ ์•Š์•„๋„** ๋ฉ๋‹ˆ๋‹ค.
#### `HeroBase` - ๊ธฐ๋ณธ ํด๋ž˜์Šค
๋ชจ๋“  ๋ชจ๋ธ์—์„œ **๊ณต์œ ๋˜๋Š” ํ•„๋“œ**๋ฅผ ๊ฐ€์ง„ `HeroBase` ๋ชจ๋ธ์„ ์‹œ์ž‘ํ•ด ๋ด…์‹œ๋‹ค:
* `name`
* `age`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *}
#### `Hero` - *ํ…Œ์ด๋ธ” ๋ชจ๋ธ*
๋‹ค์Œ์œผ๋กœ ์‹ค์ œ *ํ…Œ์ด๋ธ” ๋ชจ๋ธ*์ธ `Hero`๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์€ ๋‹ค๋ฅธ ๋ชจ๋ธ์—๋Š” ํ•ญ์ƒ ํฌํ•จ๋˜๋Š” ๊ฑด ์•„๋‹Œ **์ถ”๊ฐ€ ํ•„๋“œ**๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค:
* `id`
* `secret_name`
`Hero`๋Š” `HeroBase`๋ฅผ ์ƒ์†ํ•˜๋ฏ€๋กœ `HeroBase`์— ์„ ์–ธ๋œ ํ•„๋“œ๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ `Hero`๋Š” ๋‹ค์Œ **ํ•„๋“œ๋“ค๋„** ๊ฐ€์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:
* `id`
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *}
#### `HeroPublic` - ๊ณต๊ฐœ *๋ฐ์ดํ„ฐ ๋ชจ๋ธ*
๋‹ค์Œ์œผ๋กœ `HeroPublic` ๋ชจ๋ธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์€ API ํด๋ผ์ด์–ธํŠธ์— **๋ฐ˜ํ™˜**๋˜๋Š” ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.
`HeroPublic`์€ `HeroBase`์™€ ๋™์ผํ•œ ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, `secret_name`์€ ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๋งˆ์นจ๋‚ด ์šฐ๋ฆฌ์˜ heroes์˜ ์ •์ฒด๊ฐ€ ๋ณดํ˜ธ๋ฉ๋‹ˆ๋‹ค! ๐Ÿฅท
๋˜ํ•œ `id: int`๋ฅผ ๋‹ค์‹œ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด, API ํด๋ผ์ด์–ธํŠธ์™€ **๊ณ„์•ฝ**์„ ๋งบ์–ด `id`๊ฐ€ ํ•ญ์ƒ ์กด์žฌํ•˜๋ฉฐ ํ•ญ์ƒ `int` ํƒ€์ž…์ด๋ผ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค(`None`์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค).
/// tip | ํŒ
๋ฐ˜ํ™˜ ๋ชจ๋ธ์ด ๊ฐ’์ด ํ•ญ์ƒ ์กด์žฌํ•˜๊ณ  ํ•ญ์ƒ `int`(`None`์ด ์•„๋‹˜)๋ฅผ ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์€ API ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด API์™€ ํ†ต์‹ ํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ **์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ**๋Š” ๋” ๋‹จ์ˆœํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ, API์™€ ์†Œํ†ตํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋“ค์ด ํ›จ์”ฌ ์ˆ˜์›”ํ•˜๊ฒŒ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž
///
`HeroPublic`์˜ ๋ชจ๋“  ํ•„๋“œ๋Š” `HeroBase`์™€ ๋™์ผํ•˜๋ฉฐ, `id`๋Š” `int`๋กœ ์„ ์–ธ๋ฉ๋‹ˆ๋‹ค(`None`์ด ์•„๋‹˜):
* `id`
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *}
#### `HeroCreate` - hero ์ƒ์„ฑ์šฉ *๋ฐ์ดํ„ฐ ๋ชจ๋ธ*
์ด์ œ `HeroCreate` ๋ชจ๋ธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์€ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ **๊ฒ€์ฆ**ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
`HeroCreate`๋Š” `HeroBase์™€` ๋™์ผํ•œ ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์ถ”๊ฐ€๋กœ `secret_name์„` ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
ํด๋ผ์ด์–ธํŠธ๊ฐ€ **์ƒˆ hero์„ ์ƒ์„ฑ**ํ•  ๋•Œ `secret_name`์„ ๋ณด๋‚ด๊ณ , ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜์ง€๋งŒ, ํ•ด๋‹น ๋น„๋ฐ€ ์ด๋ฆ„์€ API๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ˜ํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
/// tip | ํŒ
์ด ๋ฐฉ์‹์€ **๋น„๋ฐ€๋ฒˆํ˜ธ**๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ฐ›์ง€๋งŒ, ์ด๋ฅผ API์—์„œ ๋ฐ˜ํ™˜ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฐ’์„ ์ €์žฅํ•˜๊ธฐ ์ „์— **ํ•ด์‹ฑ**ํ•˜์—ฌ ์ €์žฅํ•˜๊ณ , **ํ‰๋ฌธ์œผ๋กœ ์ €์žฅํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค**.
///
`HeroCreate`์˜ ํ•„๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *}
#### `HeroUpdate` - hero ์ˆ˜์ •์šฉ *๋ฐ์ดํ„ฐ ๋ชจ๋ธ*
์ด์ „ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” **hero๋ฅผ ์ˆ˜์ •**ํ•  ๋ฐฉ๋ฒ•์ด ์—†์—ˆ์ง€๋งŒ, ์ด์ œ **๋‹ค์ค‘ ๋ชจ๋ธ**์„ ํ†ตํ•ด ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽ‰
`HeroUpdate` *๋ฐ์ดํ„ฐ ๋ชจ๋ธ*์€ ์•ฝ๊ฐ„ ํŠน๋ณ„ํ•œ๋ฐ, ์ƒˆ hero์„ ์ƒ์„ฑํ•  ๋•Œ ํ•„์š”ํ•œ **๋ชจ๋“  ๋™์ผํ•œ ํ•„๋“œ**๋ฅผ ๊ฐ€์ง€์ง€๋งŒ, ๋ชจ๋“  ํ•„๋“œ๊ฐ€ **์„ ํƒ์ **(๊ธฐ๋ณธ๊ฐ’์ด ์žˆ์Œ)์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด hero์„ ์ˆ˜์ •ํ•  ๋•Œ ์ˆ˜์ •ํ•˜๋ ค๋Š” ํ•„๋“œ๋งŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ชจ๋“  **ํ•„๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ธฐ** ๋•Œ๋ฌธ์—(ํƒ€์ž…์ด `None`์„ ํฌํ•จํ•˜๊ณ , ๊ธฐ๋ณธ๊ฐ’์ด `None`์œผ๋กœ ์„ค์ •๋จ), ๋ชจ๋“  ํ•„๋“œ๋ฅผ **๋‹ค์‹œ ์„ ์–ธ**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด `HeroBase`๋ฅผ ์ƒ์†ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋‹ค์‹œ ์„ ์–ธํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ผ๊ด€์„ฑ์„ ์œ„ํ•ด ์ƒ์†์„ ์œ ์ง€ํ•˜๊ธด ํ–ˆ์ง€๋งŒ, ํ•„์ˆ˜๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐœ์ธ์ ์ธ ์ทจํ–ฅ์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ๐Ÿคท
`HeroUpdate`์˜ ํ•„๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *}
### `HeroCreate`๋กœ ์ƒ์„ฑํ•˜๊ณ  `HeroPublic` ๋ฐ˜ํ™˜ํ•˜๊ธฐ
์ด์ œ **๋‹ค์ค‘ ๋ชจ๋ธ**์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ด€๋ จ ๋ถ€๋ถ„์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์š”์ฒญ์—์„œ `HeroCreate` *๋ฐ์ดํ„ฐ ๋ชจ๋ธ*์„ ๋ฐ›์•„ ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ `Hero` *ํ…Œ์ด๋ธ” ๋ชจ๋ธ*์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
์ด ์ƒˆ *ํ…Œ์ด๋ธ” ๋ชจ๋ธ* `Hero`๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ณด๋‚ธ ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ƒ์„ฑ๋œ `id`๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ ๋‹ค์Œ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋™์ผํ•œ *ํ…Œ์ด๋ธ” ๋ชจ๋ธ* `Hero`๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ `response_model`๋กœ `HeroPublic` *๋ฐ์ดํ„ฐ ๋ชจ๋ธ*์„ ์„ ์–ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, **FastAPI**๋Š” `HeroPublic`์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๊ณ  ์ง๋ ฌํ™”ํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *}
/// tip | ํŒ
์ด์ œ **๋ฐ˜ํ™˜ ํƒ€์ž… ์ฃผ์„** `-> HeroPublic` ๋Œ€์‹  `response_model=HeroPublic`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์ด ์‹ค์ œ๋กœ `HeroPublic`์ด *์•„๋‹ˆ๊ธฐ* ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๋งŒ์•ฝ `-> HeroPublic`์œผ๋กœ ์„ ์–ธํ–ˆ๋‹ค๋ฉด, ์—๋””ํ„ฐ์™€ ๋ฆฐํ„ฐ์—์„œ ๋ฐ˜ํ™˜๊ฐ’์ด `HeroPublic`์ด ์•„๋‹ˆ๋ผ `Hero`๋ผ๊ณ  ๊ฒฝ๊ณ ํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ ์ ˆํ•œ ๊ฒฝ๊ณ ์ž…๋‹ˆ๋‹ค.
`response_model`์— ์„ ์–ธํ•จ์œผ๋กœ์จ **FastAPI**๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•˜๊ณ , ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜๊ณผ ์—๋””ํ„ฐ ๋ฐ ๋‹ค๋ฅธ ๋„๊ตฌ์˜ ๋„์›€์—๋Š” ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
///
### `HeroPublic`์œผ๋กœ Heroes ์กฐํšŒํ•˜๊ธฐ
์ด์ „๊ณผ ๋™์ผํ•˜๊ฒŒ `Hero`๋ฅผ **์กฐํšŒ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋„ `response_model=list[HeroPublic]`์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ฒ€์ฆ๋˜๊ณ  ์ง๋ ฌํ™”๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *}
### `HeroPublic`์œผ๋กœ ๋‹จ์ผ Hero ์กฐํšŒํ•˜๊ธฐ
๋‹จ์ผ hero์„ **์กฐํšŒ**ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *}
### `HeroUpdate`๋กœ Hero ์ˆ˜์ •ํ•˜๊ธฐ
**hero๋ฅผ ์ˆ˜์ •**ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด HTTP `PATCH` ์ž‘์—…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์ฝ”๋“œ์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ(`dict`)๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ด๋Š” **ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฐ์ดํ„ฐ๋งŒ ํฌํ•จ**ํ•˜๋ฉฐ, ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋“ค์–ด๊ฐ€๋Š” ๊ฐ’์€ ์ œ์™ธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด `exclude_unset=True`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ฃผ์š” ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ๐Ÿช„
๊ทธ๋Ÿฐ ๋‹ค์Œ, `hero_db.sqlmodel_update(hero_data)`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ `hero_data`์˜ ๋ฐ์ดํ„ฐ๋ฅผ `hero_db`์— ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *}
### Hero ๋‹ค์‹œ ์‚ญ์ œํ•˜๊ธฐ
hero **์‚ญ์ œ**๋Š” ์ด์ „๊ณผ ๊ฑฐ์˜ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฒˆ์—๋Š” ๋ชจ๋“  ๊ฒƒ์„ ๋ฆฌํŒฉํ† ๋งํ•˜๊ณ  ์‹ถ์€ ์š•๊ตฌ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๐Ÿ˜…
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *}
### ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ธฐ
๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋‹ค์‹œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
<div class="termy">
```console
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
`/docs` API UI๋กœ ์ด๋™ํ•˜๋ฉด ์—…๋ฐ์ดํŠธ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์˜์›…์„ ์ƒ์„ฑํ•  ๋•Œ `id`๋ฅผ ์ œ๊ณตํ•  ํ•„์š”๊ฐ€ ์—†๊ฒŒ ๋˜๋Š” ๋“ฑ์˜ ๋ณ€ํ™”๋„ ๋ณด์ž…๋‹ˆ๋‹ค.
<div class="screenshot">
<img src="/img/tutorial/sql-databases/image02.png">
</div>
## ์š”์•ฝ
<a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">**SQLModel**</a>์„ ์‚ฌ์šฉํ•˜์—ฌ SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ณ , *๋ฐ์ดํ„ฐ ๋ชจ๋ธ* ๋ฐ *ํ…Œ์ด๋ธ” ๋ชจ๋ธ*๋กœ ์ฝ”๋“œ๋ฅผ ๊ฐ„์†Œํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋” ๋งŽ์€ ๋‚ด์šฉ์„ ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด, **SQLModel** ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">SQLModel์„ **FastAPI**์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๋” ๊ธด ๋ฏธ๋‹ˆ ํŠœํ† ๋ฆฌ์–ผ</a>๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๐Ÿš€
Loadingโ€ฆ
Cancel
Save