portfolio

๐Ÿฆ ์‚ฌ์ž์‚ฌ์ž ๊ฐ€๊ณ„๋ถ€ - Backend

๋ถ€๋ชจ์™€ ์ž๋…€๊ฐ€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ธˆ์œต ๊ต์œก ๊ธฐ๋ฐ˜ ๊ฐ€๊ณ„๋ถ€ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.
์ž๋…€์˜ ์†Œ๋น„/์ €์ถ• ์Šต๊ด€์„ ๊ธฐ๋กํ•˜๊ณ , ๋ถ€๋ชจ๊ฐ€ ์•ˆ์ „ํ•˜๊ฒŒ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ Django REST API ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค.

OZ Coding School Backend Team Project
๊ฐœ๋ฐœ ๊ธฐ๊ฐ„: 2026.02.19 ~ 2026.02.27


๐Ÿ‘จโ€๐Ÿ’ป ๋‹ด๋‹น ์—ญํ•  - ๋ฐ•์ง„๊ทœ

๋‹ด๋‹น ๋„๋ฉ”์ธ

๊ตฌํ˜„ ๊ธฐ๋Šฅ

๐Ÿ“’ Finance

๐Ÿ’ก Contents


๐Ÿ›  Tech Stack

Backend

Infra / DevOps

Security


๐Ÿ“‚ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

oz-be-16-team1/
โ”œโ”€โ”€ config/
โ”œโ”€โ”€ users/
โ”œโ”€โ”€ assets/
โ”œโ”€โ”€ finance/
โ”œโ”€โ”€ missions/
โ”œโ”€โ”€ contents/
โ””โ”€โ”€ manage.py

๐Ÿ“’ Finance ๋„๋ฉ”์ธ ์„ค๊ณ„

Transaction ํ•ต์‹ฌ ๊ธฐ๋Šฅ

โœ… ๊ฑฐ๋ž˜ CRUD

โœ… ๊ถŒํ•œ ์ฒ˜๋ฆฌ

โœ… ์ž์‚ฐ ์†Œ์œ ๊ถŒ ๊ฒ€์ฆ

Asset.objects.get(
    pk=asset_id,
    user=request.user
)

ํƒ€์ธ์˜ ์ž์‚ฐ ์—ฐ๊ฒฐ์„ ์ฐจ๋‹จํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.


FixedExpense ํ•ต์‹ฌ ๊ธฐ๋Šฅ


๐Ÿ’ก Contents ๋„๋ฉ”์ธ ์„ค๊ณ„

๋žœ๋ค ๋ช…์–ธ ์กฐํšŒ

MoneyProverb.objects.order_by("?").first()

๋งค ์š”์ฒญ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ธˆ์œต ๋ช…์–ธ์„ ์ œ๊ณตํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.


๋ช…์–ธ ์Šคํฌ๋žฉ

์ค‘๋ณต ๋ฐฉ์ง€

UniqueConstraint(
    fields=["user", "proverb"],
    name="unique_user_proverb"
)

๋™์ผ ์‚ฌ์šฉ์ž์˜ ์ค‘๋ณต ์Šคํฌ๋žฉ์„ DB ๋ ˆ๋ฒจ์—์„œ ์ฐจ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„ ๊ธฐ๋Šฅ


๐Ÿ” ๊ถŒํ•œ ๋ฐ ๋ณด์•ˆ ์ฒ˜๋ฆฌ

Transaction ์ˆ˜์ •/์‚ญ์ œ ๊ถŒํ•œ

if obj.user != request.user:
    raise PermissionDenied()

์ž‘์„ฑ์ž ๋ณธ์ธ๋งŒ ์ˆ˜์ •/์‚ญ์ œ ๊ฐ€๋Šฅํ•˜๋„๋ก ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.


์ธ์ฆ ์ •์ฑ…


๐Ÿ“Œ ์ฃผ์š” API

Finance API

Method Endpoint Description
GET /api/finance/transaction/ ๊ฑฐ๋ž˜ ๋ชฉ๋ก ์กฐํšŒ
POST /api/finance/transaction/ ๊ฑฐ๋ž˜ ์ƒ์„ฑ
PATCH /api/finance/transaction/{id}/ ๊ฑฐ๋ž˜ ์ˆ˜์ •
DELETE /api/finance/transaction/{id}/ ๊ฑฐ๋ž˜ ์‚ญ์ œ
GET /api/finance/fixed/ ๊ณ ์ •์ง€์ถœ ๋ชฉ๋ก
POST /api/finance/fixed/ ๊ณ ์ •์ง€์ถœ ์ƒ์„ฑ

Contents API

Method Endpoint Description
GET /api/contents/ ๋žœ๋ค ๋ช…์–ธ ์กฐํšŒ
GET /api/contents/proverb_scrap/ ๋‚ด ์Šคํฌ๋žฉ ๋ชฉ๋ก
POST /api/contents/proverb_scrap/ ์Šคํฌ๋žฉ ์ƒ์„ฑ
DELETE /api/contents/proverb_scrap/{id}/ ์Šคํฌ๋žฉ ์‚ญ์ œ

๐Ÿงช ํ…Œ์ŠคํŠธ ๋ฐ ๊ฒ€์ฆ

ํ…Œ์ŠคํŠธ ์ค‘์ 

๊ฒฐ๊ณผ

68 tests, OK

์ „์ฒด ํ…Œ์ŠคํŠธ ํ†ต๊ณผ๋กœ ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์•ˆ์ •์„ฑ์„ ๊ฒ€์ฆํ–ˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ“– ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด ๋ฐฐ์šด ์ 

๊ธˆ์œต ์„œ๋น„์Šค๋Š” ๋‹จ์ˆœ CRUD๋ณด๋‹ค ๊ถŒํ•œยท๋ณด์•ˆ ์„ค๊ณ„๊ฐ€ ๋” ์ค‘์š”ํ•˜๋‹ค๋Š” ์ ์„ ์‹ค๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋„๋ฉ”์ธ ๊ทœ์น™์„ Serializer์™€ DB Constraint๋กœ ์ด์ค‘ ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ์‹, ๋ถ€๋ชจ/์ž๋…€ ๊ด€๊ณ„ ๊ธฐ๋ฐ˜ ์กฐํšŒ ์ •์ฑ… ์„ค๊ณ„, ๊ทธ๋ฆฌ๊ณ  API ์„ค๊ณ„ ๋‹จ๊ณ„(PRD/FlowChart/ERD)์˜ ์ค‘์š”์„ฑ์„ ์ง์ ‘ ๊ฒฝํ—˜ํ•˜๋ฉฐ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์‹ค์ œ ๊ธˆ์œต ์„œ๋น„์Šค ์ˆ˜์ค€์„ ๋ชฉํ‘œ๋กœ ์™ธ๋ถ€ API ์—ฐ๋™๊นŒ์ง€ ์‹œ๋„ํ•˜๋ฉฐ ๊ธฐ์ˆ ์  ํ™•์žฅ ๊ฐ€๋Šฅ์„ฑ์„ ๊ณ ๋ฏผํ•œ ๊ฒฝํ—˜๋„ ์˜๋ฏธ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ์„ ํ•  ์ ์œผ๋กœ๋Š” ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ ํ˜„์‹ค์  ์ œ์•ฝ๊ณผ ๋„๋ฉ”์ธ ์˜ˆ์™ธ ์ƒํ™ฉ์„ ๋” ์ถฉ๋ถ„ํžˆ ์ •์˜ํ–ˆ์–ด์•ผ ํ–ˆ๊ณ , ํŒ€์› ๊ฐ„ ์ฝ”๋“œ ๊ณต์œ ์™€ ๊ฒ€์ฆ ๊ธฐ์ค€์„ ๋งž์ถ”๋Š” ํ˜‘์—… ์—ญ๋Ÿ‰์ด ๋ถ€์กฑํ–ˆ๋‹ค๋Š” ์ ์„ ๋А๊ผˆ์Šต๋‹ˆ๋‹ค.


๐Ÿš€ ๊ฐœ์„ ํ•˜๊ณ  ์‹ถ์€ ๋ถ€๋ถ„


๐Ÿ”— GitHub