๊ฐ์ธ์ ์ผ๋ก ํ์ด์ฌ์ ์ข์ํ์ง ์๋๋ค. ๊ทธ๋ฌ๋, AI ์๋์ ์์ด ํ์ด์ฌ์ ์ธ์ ๊น์ง๋ ๊ธฐํผํ ์ ์๋ค. ๋น๋ก ํ์ด์ฌ์ผ๋ก ๊ฐ๋ฐํ์ง ์๋๋ผ๋ ํ์ด์ฌ ์ฝ๋๋ฅผ ๋ณด๊ณ ์ดํดํ ์ ์๋ ์ญ๋์ ํค์๋ณด์. ํ์ด์ฌ์ ๊ฐ๋ฐ์ ๋ณด๋ค๋ DevOps ์์ง๋์ด ๋๋ QA ์์ง๋์ด ๊ทธ๋ฆฌ๊ณ ๋ฐ์ดํฐ ๋ถ์ ์์ง๋์ด๊ฐ ๋ง์ด ํ์ฉํ๋ค.
ํ์ด์ฌ ์ธํฐํ๋ฆฌํฐ โ
ํ์ด์ฌ์ ์ปดํ์ผ ๋จ๊ณ๋ฅผ ๊ฑฐ์น์ง ์๊ณ ์ฝ๋๋ฅผ ํ์ค์ฉ ๊ทธ๋๋ก ํ์ด์ฌ ์ธํฐํ๋ฆฌํฐ์ ์ํด ์ฝ๋๊ฐ ์คํ๋๋ค. ๊ธฐ๋ณธ์ ์ธ ํ์ด์ฌ ์ธํฐํ๋ฆฌํฐ๋ CPython ์ด๋ฉฐ, pip ๋๋ uv ๋ ํ์ด์ฌ์์ ์ฌ์ฉํ ์ ์๋ ํจํค์ง ๋งค๋์ ์ด๋ค. ํ์ด์ฌ ๊ฐ๋ฐ์๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ํ์ด์ฌ ์ธํฐํ๋ฆฌํฐ๊ฐ ์ ํํ ์ด๋ค ๊ณผ์ ์ผ๋ก ์ฝ๋๋ฅผ ์คํํ๋์ง๋ ์์ธํ ์ ํ์๋ ์์ด๋ณด์ธ๋ค.
๋ชจ๋ ๋๋ ํ ๋ฆฌ โ
ํ์ด์ฌ์ ๋ณ์ ๋๋ ํจ์ ๊ทธ๋ฆฌ๊ณ ํด๋์ค ๋ฑ์ ํ๋์ .py ํ์ผ์ ์ ์ํ์ฌ ๋ค๋ฅธ ํ์ผ์์ ๋ถ๋ฌ์ฌ ์ ์๋๋ก ๋ชจ๋ํํ๋ค. ์น ์ ํ๋ฆฌ์ผ์ด์
์์ฑ์ ์ํด FastAPI ํจํค์ง๋ฅผ ์ค์นํ๋ฉด ๋ชจ๋์ ๊ฐ์ ธ์์ ์คํํ๊ฒ ๋๋ค. ๋ชจ๋ ํ์ผ์ด ์กด์ฌํ๋ ๋๋ ํ ๋ฆฌ์ __init__.py
ํ์ผ์ด ์กด์ฌํ๋ฉด ํด๋น ํด๋๋ ํจํค์ง๋ก ์ทจ๊ธ๋๋ค. Best Practices ํ๋ก์ ํธ ์ฝ๋๋ฅผ ์ฐพ์๋ณด๋ฉด ํ์ผ ๊ตฌ์กฐ ์์ ์ด ํ์ผ์ด ์์ ์ ์๋ ๊ฑธ ๋ณผ ์ ์๋๋ฐ ์๋ต์ด ๊ฐ๋ฅํ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def index():
return {"Hello": "World"}
๋ฐ์ฝ๋ ์ดํฐ โ
ํ์ด์ฌ์์ ๋ฐ์ฝ๋ ์ดํฐ๋ ๋ค๋ฅธ ํจ์๋ฅผ ๋ํํ๋ ํจํด์ด๋ค. FastAPI์์ ๋ผ์ฐํฐ๋ฅผ ๋ฑ๋กํ ๋ ์ฌ์ฉํ๊ฑฐ๋ Cache๋ฅผ ํตํด ํ์ด์ฌ ์ฑ๋ฅ์ ํฅ์์ํค๋๋ฐ ์ฌ์ฉํ ์ ์๋ค. ๋ค์๊ณผ ๊ฐ์ ํ์ด๋ฐ ๋ฐ์ฝ๋ ์ดํฐ๋ ํจ์์ ์คํ ์๊ฐ์ ์ธก์ ํ์ฌ ์ฑ๋ฅ ์ด์๊ฐ ๋ด์ฌ๋ ๊ตฌ๊ฐ์ ์ฐพ๋๋ฐ ๋์์ด ๋๋ค.
import functools
import time
def timing_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"ํจ์ '{func.__name__}' ์คํ ์๊ฐ: {end_time - start_time:.4f} ์ด")
return result
return wrapper
@timing_decorator
def example_function(n):
total = 0
for i in range(n):
total += i
return total
if __name__ == '__main__':
example_function(10000000)
SQLAlchemy vs SQLModel โ
SQLAlchemy ORM์ ํ์ด์ฌ์์ ์ฌ์ฉํ ์ ์๋ ORM ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก SQLite ์ ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํต์ ํ ์ ์๋ค . FastAPI ์์ ์ ๊ณตํ๋ SQLModel ์ SQLAlchemy ๊ธฐ๋ฐ์์ Pydantic ์ด ๊ฒฐํฉ๋ ๊ธฐ๋ฅ์ ์ง์ํ๋ค. SQLModel ์ ์ ๋๋ก ์ฌ์ฉํ๊ธฐ ์ํด์๋ SQLAlchemy ๋ฅผ ๋จผ์ ํ์ตํ๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ๋ค. ๋ค์์ AWS IoT Core ์์ ๋ฐ๊ธ๋ฐ์ IoT ํด๋ผ์ด์ธํธ ์ธ์ฆ์๋ฅผ ์ ์ฅํ ์ ์๋ ํ ์ด๋ธ์ ์ ์ํด๋ณธ ๊ฒ์ด๋ค.
from datetime import datetime
from sqlmodel import Field, Session, SQLModel, create_engine, Column, LargeBinary
from sqlalchemy.dialects.sqlite import insert
class IoT(SQLModel, table=True):
__tablename__ = "iot"
__table_args__ = {"sqlite_autoincrement": True, "comment": "AWS IoT Thing"}
id: int = Field(default=None, primary_key=True)
client_id: str = Field(nullable=False, unique=True)
private_key: bytes = Field(sa_column=Column(LargeBinary, nullable=False))
cert_pem: bytes = Field(sa_column=Column(LargeBinary, nullable=False))
ca_cert_pem: bytes | None = Field(sa_column=Column(LargeBinary, nullable=True))
created_at: datetime = Field(default_factory=lambda: datetime.now(), nullable=False)
engine = create_engine(
"sqlite:///./db/app.db", echo=True, pool_size=5, pool_recycle=3600
)
SQLModel.metadata.create_all(engine)
session = Session(engine)
stmt = (
insert(IoT)
.values(client_id="asdf", private_key=b"", cert_pem=b"")
.on_conflict_do_nothing()
)
session.exec(stmt)
session.commit()
Pandas vs Polars โ
ํ์ด์ฌ ํ๋ก์ ํธ์์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐ ๋ถ์์ ์ํด ๋ฐ์ดํฐ ํ๋ ์์ ๋ค๋ฃจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ ํต์ ์ผ๋ก ํ๋ค์ค๊ฐ ์ฌ์ฉ๋์์ง๋ง ์ต๊ทผ์๋ ํ๋ค์ค์ ๋จ์ ์ธ ์ฑ๋ฅ ์ด์๋ฅผ ๋ณด์ํ๊ธฐ ์ํด Rust๋ก ์์ฑ๋ ํด๋ผ์ค๋ก ๋์ฒด๋์ด ์ฌ์ฉ๋๋ ๊ฒ ๊ฐ๋ค. ์ ฏ๋ธ๋ ์ธ์ค ๋ธ๋ก๊ทธ์์ ๊ณต์ ํ Polars์ pandas ๋น๊ต: ์ด๋ป๊ฒ ๋ค๋ฅผ๊น์?๋ฅผ ์ฝ์ด๋ณด์.
Seaborn vs Plotly โ
๋ฐ์ดํฐ ๋ถ์์์ ์ฐจํธ ์๊ฐํ๋ Matplotlib, Seaborn, Plotly ์ค ํ๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ๊ฐ๋ค. ๋ค์๊ณผ ๊ฐ์ด Polars DataFrame ์ Visualizationํ ์ ์๋ค.
import polars as pl
import plotly.express as px
if __name__ == "__main__":
df = pl.DataFrame({"category": ["A", "B", "C", "D"], "value": [10, 25, 15, 30]})
fig = px.bar(
df, x="category", y="value", title="Polars DataFrame with Plotly Express"
)
fig.show()