๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿš€ Backend18

[FastAPI] Middleware ๋ฏธ๋“ค์›จ์–ด (CORS, Logging) 1. ๋ฏธ๋“ค์›จ์–ด๋ž€?FastAPI์˜ ๋ฏธ๋“ค์›จ์–ด๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ(Request)์™€ ์‘๋‹ต(Response) ์‚ฌ์ด์— ์‹คํ–‰๋˜๋Š” ๊ฐ€๋กœ์ฑ„๊ธฐ ํ•จ์ˆ˜์ฃผ๋กœ ์ธ์ฆ, ๋กœ๊น…, ์„ฑ๋Šฅ ์ธก์ •, ์—๋Ÿฌ ์ฒ˜๋ฆฌ, ๋ณด์•ˆ ๋“ฑ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅ๋น„์ฆˆ๋‹ˆ์Šค & ๋„๋ฉ”์ธ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด, ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ 2. FastAPI ์˜ˆ์‹œimport timefrom fastapi import FastAPI, Requestapp = FastAPI()@app.middleware("http")async def add_process_time_header(request: Request, call_next): start_time = time.perf_counter() # ์‹ค์ œ ๋ผ์šฐํ„ฐ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ „ response = await ca.. 2025. 4. 20.
[FastAPI] SSE (Server-Sent Events) 1. Server-Sent EventsSSE(Server-Sent Events) ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•œ ์ฑ„, ์„œ๋ฒ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์‹ค์‹œ๊ฐ„ ์ด๋ฒคํŠธ๋ฅผ ์ง€์†์ ์œผ๋กœ ์ „๋‹ฌ๋ฐ›๋Š” ๋ฐฉ์‹๐Ÿ“Œ “์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ํ•œ ๋ฒˆ ์—ฐ๊ฒฐ๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ์‘๋‹ต์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” HTTP ๊ธฐ๋ฐ˜ ๊ธฐ์ˆ ” 2. SSE ๊ตฌ์กฐํด๋ผ์ด์–ธํŠธ๋Š” EventSource ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.์„œ๋ฒ„๋Š” text/event-stream ํƒ€์ž…์œผ๋กœ ์‘๋‹ต์„ ๋ณด๋‚ด๊ณ  ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•œ ์ฑ„ ์—ฌ๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๊ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.# ClientGET /stream HTTP/1.1Accept: text/event-stream # Responseevent: datadata: Hello, world!event: fin.. 2025. 4. 16.
[FastAPI] SQLModel 1. SQLModel์ด๋ž€?๊ธฐ์กด Python SQL ORM ๊ตฌํ˜„์ฒด์ธ SQLAlchemy์™€ ๊ฒ€์ฆ ํŒจํ‚ค์ง€ Pydantic์„ ๊ฒฐํ•ฉํ•œ Python ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ๋ณด๋‹ค ๊ฐ„๊ฒฐํ•˜๊ณ  ์ง๊ด€์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.SQLAlchemy์˜ ORM ๊ธฐ๋Šฅ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ Pydantic์˜ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ํŠน์ง•์ด๋‹ค.  2. SQLAlchemy vs SQLModelSQLAlchemy๋Š” ๋‘ ๊ฐ€์ง€ ์ฃผ์š” API ์Šคํƒ€์ผ์„ ์ œ๊ณตํ•œ๋‹ค.SQLAlchemy Core: ์ €์ˆ˜์ค€ SQL ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜์—ฌ SQL์„ ์ง์ ‘ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋จSQLAlchemy ORM: ๊ฐ์ฒด-๊ด€๊ณ„ ๋งคํ•‘(Object-Relational Mapping)์„ ํ†ตํ•ด Python ํด๋ž˜์Šค๋กœ DB ๋ชจ๋ธ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์ŒSQLModel์€ SQLAlchemy .. 2025. 3. 14.
[FastAPI] Best Practices - Project Structure Project StructureFastAPI ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์„ค๊ณ„ ํ• ๋•Œ ์ฐธ๊ณ ํ•˜๊ธฐ ์ข‹๋‹ค.Netflaix/Dipatch๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ์ˆ˜์ •ํ•œ ์ž๋ฃŒ์ด๋‹ค.fastapi-projectโ”œโ”€โ”€ alembic/โ”œโ”€โ”€ app # ์›๋ณธ์€ src ์ด์ง€๋งŒ ๋ณธ์ธ์€ app ์„ ํ˜ธํ•จ.โ”‚ โ”œโ”€โ”€ authโ”‚ โ”‚ โ”œโ”€โ”€ router.pyโ”‚ โ”‚ โ”œโ”€โ”€ schemas.py # pydantic modelsโ”‚ โ”‚ โ”œโ”€โ”€ models.py # db modelsโ”‚ โ”‚ โ”œโ”€โ”€ dependencies.pyโ”‚ โ”‚ โ”œโ”€โ”€ config.py # local configsโ”‚ โ”‚ โ”œโ”€โ”€ constants.pyโ”‚ โ”‚ โ”œโ”€โ”€ exceptions.pyโ”‚ โ”‚ โ”œโ”€โ”€ service.pyโ”‚ โ”‚ โ””โ”€โ”€ ut.. 2025. 2. 14.
[SQL] SELECT ๊ด€๋ จ ํ•จ์ˆ˜ ์ง‘๊ณ„ ํ•จ์ˆ˜ (Aggregate Functions)AVG(): ํ‰๊ท ๊ฐ’ ๊ณ„์‚ฐSUM(): ํ•ฉ๊ณ„ ๊ตฌํ•˜๊ธฐCOUNT(): ์ „์ฒด ํ–‰ ๊ฐœ์ˆ˜COUNT(*): ๋ชจ๋“  ํ–‰์˜ ๊ฐœ์ˆ˜COUNT(์ปฌ๋Ÿผ๋ช…): NULL์ด ์•„๋‹Œ ๊ฐ’์˜ ๊ฐœ์ˆ˜MAX() / MIN(): ์ตœ๋Œ€๊ฐ’๊ณผ ์ตœ์†Œ๊ฐ’GROUP_CONCAT(): ๋ฌธ์ž์—ด ํ•ฉ์น˜๊ธฐROUND() / CEIL() / FLOOR(): ๋ฐ˜์˜ฌ๋ฆผ, ์˜ฌ๋ฆผ, ๋‚ด๋ฆผ ๋‘๋ฒˆ์งธ ์ธ์ž๋กœ ์–ด๋А ์ž๋ฆฌ๊นŒ์ง€ ํ‘œํ˜„ ์ •ํ•จTRUNCATE(): ์ง€์ •ํ•œ ์ž๋ฆฌ์ˆ˜๊นŒ์ง€ ๋ฒ„๋ฆผ์ƒ์œ„ N๊ฐœ ๋ฐ์ดํ„ฐ ์ถ”์ถœ (LIMIT)LIMIT N: ๊ฒฐ๊ณผ์—์„œ ์ƒ์œ„ N๊ฐœ๋งŒ ์ถœ๋ ฅ ๋‚ ์งœ ๋‹ค๋ฃจ๊ธฐ# ๋‚ ์งœ ๋ฒ”์œ„ ์กฐํšŒWHERE JOINED BETWEEN '2021-01-01' AND '2021-12-31'๋˜๋Š”WHERE YEAR(JOINED) = 2021 # ๋‚ ์งœ ํฌ๋งท ๋ณ€๊ฒฝDATE_F.. 2025. 2. 5.
[Security] ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ Spring Security์ธ์ฆ(Authentication), ๊ถŒํ•œ ๋ถ€์—ฌ(Authorize) ๋ฐ ๋ณดํ˜ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ 2024. 2. 27.