DailyDevQλ κ°λ°μλ₯Ό μν AI κΈ°λ°μ κΈ°μ λ©΄μ μ§λ¬Έ λ° νμ΅ κ΄λ¦¬ νλ«νΌμ λλ€. AWS μλ²λ¦¬μ€ μν€ν μ²μ λ€μν μμ λ‘κ·ΈμΈ κΈ°λ₯μ νμ©νμ¬ μ¬μ©μ μΉνμ μ΄κ³ ν¨μ¨μ μΈ νμ΅ νκ²½μ μ 곡ν©λλ€.
- μμ λ‘κ·ΈμΈ: Google, GitHub, Kakao, Naverλ₯Ό ν΅ν κ°νΈν λ‘κ·ΈμΈ μ§μ
- DynamoDB λ°μ΄ν° μ μ₯: μ¬μ©μ μ 보λ₯Ό μμ νκ² κ΄λ¦¬
- AI κΈ°λ° λ©΄μ μ§λ¬Έ μ 곡: OpenAI APIλ₯Ό νμ©νμ¬ λ§μΆ€ν λ©΄μ μ§λ¬Έ μμ±
- E-mail ꡬλ μλΉμ€: AWS SESλ₯Ό ν΅ν μΌμΌ λ©΄μ μ§λ¬Έ μ΄λ©μΌ λ°μ‘
- νμ΅ μ§ν μν© κ΄λ¦¬: Flask κΈ°λ° λμ보λλ‘ νμ΅ λ°μ΄ν°λ₯Ό μκ°ν
- Flask: μΉ νλ μμν¬
- Jinja2: ν νλ¦Ώ μμ§
- Bootstrap 5: UI ꡬμ±
- Python: 3.10+
- AWS DynamoDB: NoSQL λ°μ΄ν°λ² μ΄μ€
- AWS Lambda: μλ²λ¦¬μ€ μ»΄ν¨ν
- OpenAI API: GPT-3.5 Turbo
- AWS SES: μ΄λ©μΌ μλΉμ€
- AWS: EC2, S3, IAM, VPC
- Terraform: μΈνλΌ μ½λ κ΄λ¦¬
- GitHub Actions: CI/CD νμ΄νλΌμΈ ꡬμΆ
git clone https://github.com/DailyDevQ/dailydevq-main.git
cd dailydevq-main
# κ°μνκ²½ μμ± λ° νμ±ν
python -m venv dailydevq-venv
source dailydevq-venv/bin/activate # Windowsλ dailydevq-venv\Scripts\activatepip install -r requirements.txtνλ‘μ νΈ λ£¨νΈ λλ ν 리μ .env νμΌμ μμ±νκ³ μλ λ΄μ©μ μΆκ°ν©λλ€
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
KAKAO_CLIENT_ID=your_kakao_client_id
NAVER_CLIENT_ID=your_naver_client_id
NAVER_CLIENT_SECRET=your_naver_client_secret
AWS_ACCESS_KEY_ID=your_aws_access_key
AWS_SECRET_ACCESS_KEY=your_aws_secret_access_keyflask rundailydevq-main/
βββ frontend/
β βββ app/
β β βββ static/
β β β βββ css/ # CSS νμΌ
β β β β βββ style.css
β β β βββ js/ # JavaScript νμΌ
β β βββ templates/
β β β βββ auth/ # μΈμ¦ κ΄λ ¨ HTML ν
νλ¦Ώ
β β β β βββ dashboard/
β β β βββ 404.html # 404 μλ¬ νμ΄μ§
β β β βββ 500.html # 500 μλ¬ νμ΄μ§
β β β βββ base.html # κ³΅ν΅ λ μ΄μμ ν
νλ¦Ώ
β β β βββ index.html # λ©μΈ νμ΄μ§
β β βββ __init__.py # ν¨ν€μ§ μ΄κΈ°ν νμΌ
β β βββ app.py # Flask μ ν리μΌμ΄μ
μ§μ
μ
β β βββ routes.py # λΌμ°νΈ κ΄λ¦¬
βββ backend/
β βββ functions/
β β βββ email_sender/ # μ΄λ©μΌ λ°μ‘ κ΄λ ¨ μ½λ
β β βββ handler.py # Lambda νΈλ€λ¬
β β βββ user_service.py # μ¬μ©μ μ 보 κ΄λ¦¬ ν¨μ
βββ infrastructure/
β βββ dynamodb.tf # DynamoDB μ€μ
β βββ outputs.tf # Terraform μΆλ ₯
β βββ providers.tf # AWS νλ‘λ°μ΄λ μ€μ
β βββ terraform.tfvars # Terraform λ³μ κ° (Gitμ μ
λ‘λ κΈμ§) λ°λ‘ μμ± ν μ¬μ©.
β βββ variables.tf # Terraform λ³μ μ μ
βββ requirements/
β βββ base.txt # κΈ°λ³Έ ν¨ν€μ§ λͺ©λ‘
β βββ dev.txt # κ°λ°μ© ν¨ν€μ§
β βββ test.txt # ν
μ€νΈμ© ν¨ν€μ§
βββ requirements_split.py # requirements νμΌ μμ± μ€ν¬λ¦½νΈ
βββ .gitignore # Gitμμ μ μΈν νμΌ λͺ©λ‘
βββ LICENSE # λΌμ΄μ μ€ νμΌ
βββ MAIN-LOGO.jpg # DailyDevQ μν λ‘κ³ μ΄λ―Έμ§
βββ README.md # νλ‘μ νΈ μ€λͺ
νμΌ
βββ .env # νκ²½ λ³μ νμΌ (Gitμ μ
λ‘λ κΈμ§) λ°λ‘ μμ± ν μ¬μ©.
-
auth/λλ ν 리:- μΈμ¦ κ΄λ ¨ HTML νμΌμ
/templates/auth/λλ ν 리μ μ μ₯. - μΈλΆ μΈμ¦ νμ΄μ§(μ: λμ보λ λ±)λ
/templates/auth/dashboard/μμ κ΄λ¦¬.
- μΈμ¦ κ΄λ ¨ HTML νμΌμ
-
μλ¬ νμ΄μ§ μΆκ°:
404.html(Not Found) λ°500.html(Internal Server Error) νμ΄μ§ μΆκ°.
-
μ μ νμΌ λλ ν 리 ꡬ쑰ν:
static/λλ ν 리 μλcss/μjs/λ‘ νμΌμ ꡬλΆνμ¬ κ΄λ¦¬.
-
Terraform λλ ν 리 λͺ νν:
.terraform/λλ ν λ¦¬λ‘ Terraform μλ μμ± νμΌ κ΅¬λΆ.- μ£Όμ μ€μ νμΌμ μμ λλ ν 리μ μμΉ.
Note: μ΄ λλ ν 리 ꡬ쑰λ νμ¬ κ°λ° μ§ν μ€μΈ μνλ₯Ό λ°μνκ³ μμ΅λλ€. νλ‘μ νΈκ° μ§νλ¨μ λ°λΌ λλ ν 리μ νμΌμ΄ μΆκ°λ μ μμ΅λλ€.
requirements_split.pyλ Python νλ‘μ νΈμ μμ‘΄μ±μ κ΄λ¦¬νκΈ° μν μ€ν¬λ¦½νΈμ
λλ€. μ΄ μ½λλ₯Ό μ€ννλ©΄ requirements λλ ν 리μ μμ‘΄μ±μ λͺ©μ λ³λ‘ λλ κ΄λ¦¬νλ νμΌλ€μ μμ±ν©λλ€.
- μμ‘΄μ± νμΌ μλ μμ±:
base.txt,dev.txt,test.txtμμ± - μ€λ³΅ κ΄λ¦¬ λ°©μ§:
base.txtλ₯Ό λ€λ₯Έ μμ‘΄μ± νμΌμμ μ¬μ¬μ© - λͺ νν μμ‘΄μ± κ΅¬λΆ: κ°λ°, ν μ€νΈ, λ°°ν¬ λͺ©μ μ λ§λ ν¨ν€μ§ λΆλ¦¬
# ./requirements_split.py
import os
# κΈ°λ³Έ ν¨ν€μ§ λͺ©λ‘
base_packages = """Flask==3.1.0
requests==2.32.3
python-dotenv==1.0.1
"""
# κ°λ°μ© ν¨ν€μ§ λͺ©λ‘
development_packages = """black==24.10.0
flake8==7.1.1
"""
# ν
μ€νΈμ© ν¨ν€μ§ λͺ©λ‘
testing_packages = """pytest==8.3.3
coverage==7.3.1
"""
# requirements λλ ν 리 μμ±
os.makedirs('requirements', exist_ok=True)
# κ° λͺ©μ λ³ νμΌ μμ±
with open('requirements/base.txt', 'w') as f:
f.write(base_packages)
with open('requirements/dev.txt', 'w') as f:
f.write("-r base.txt\n") # κΈ°λ³Έ ν¨ν€μ§ ν¬ν¨
f.write(development_packages)
with open('requirements/test.txt', 'w') as f:
f.write("-r base.txt\n") # κΈ°λ³Έ ν¨ν€μ§ ν¬ν¨
f.write(testing_packages)
print("requirements λλ ν 리μ κ΄λ ¨ νμΌμ΄ μμ±λμμ΅λλ€.")- ν΄λΉ νμΌμ νλ‘μ νΈ λ£¨νΈ λλ ν 리μ μμΉμν΅λλ€.
- μλ λͺ
λ Ήμ΄λ₯Ό μ€νν©λλ€:
python requirements_split.py
requirements/λλ ν 리μ μμ±λ νμΌμ νμΈν©λλ€:base.txt: κΈ°λ³Έ ν¨ν€μ§dev.txt: κ°λ°μ© ν¨ν€μ§test.txt: ν μ€νΈμ© ν¨ν€μ§
μ΄ μ€ν¬λ¦½νΈλ μμ‘΄μ± κ΄λ¦¬λ₯Ό κ°μννκ³ , μ½λ μΆ©λμ λ°©μ§νλ λ° λμμ μ€λλ€.
- μ΄ μ μ₯μλ₯Ό ν¬ν¬ν©λλ€.
- κΈ°λ₯ μΆκ°λ λ²κ·Έ μμ μ μν λΈλμΉλ₯Ό μμ±ν©λλ€.
- μ½λλ₯Ό 컀λ°νκ³
git pushν©λλ€. - Pull Requestλ₯Ό μμ±νμ¬ λ³κ²½ μ¬νμ μμ²ν©λλ€.
μ΄ νλ‘μ νΈλ GitHub Flowλ₯Ό κΈ°λ°μΌλ‘ κ΄λ¦¬λ©λλ€.
-
master λΈλμΉ
- νμ λ°°ν¬ κ°λ₯ν μνλ₯Ό μ μ§ν©λλ€.
- μ§μ μ»€λ° κΈμ§, λͺ¨λ λ³κ²½μ PRμ ν΅ν΄ λ³ν©λ©λλ€.
-
μμ λΈλμΉ
- μλ‘μ΄ μμ
μ μν΄
feature/λλhotfix/λ‘ μμνλ λΈλμΉλ₯Ό μμ±ν©λλ€. - λΈλμΉ μ΄λ¦ κ·μΉ:
- κΈ°λ₯ μΆκ°:
feature/<κΈ°λ₯λͺ >(μ:feature/add-login) - λ²κ·Έ μμ :
hotfix/<λ²κ·Έλͺ >(μ:hotfix/fix-login-error)
- κΈ°λ₯ μΆκ°:
- μλ‘μ΄ μμ
μ μν΄
-
Pull Request(PR)
- PR μμ± ν, μ½λ λ¦¬λ·°κ° μλ£λλ©΄ λ³ν©ν©λλ€.
- λ³ν©λ λΈλμΉλ μλμΌλ‘ μμ λ©λλ€.
μ΄ νλ‘μ νΈλ Apache License 2.0 νμ λ°°ν¬λ©λλ€. μμΈν λ΄μ©μ LICENSEλ₯Ό μ°Έμ‘°νμΈμ.
- μ΄λ©μΌ: [email protected]
- GitHub: DailyDevQ