diff --git a/getcloser/backend/Dockerfile b/getcloser/backend/Dockerfile new file mode 100644 index 0000000..a7a81a1 --- /dev/null +++ b/getcloser/backend/Dockerfile @@ -0,0 +1,14 @@ +FROM python:3.10-slim + +WORKDIR /app + +# 시스템 의존성 설치 +RUN apt-get update && apt-get install -y build-essential libpq-dev gcc --no-install-recommends && rm -rf /var/lib/apt/lists/* + +COPY src/requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY ./src ./src + +EXPOSE 8000 +CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/getcloser/backend/README.md b/getcloser/backend/README.md new file mode 100644 index 0000000..3d0b8ee --- /dev/null +++ b/getcloser/backend/README.md @@ -0,0 +1,33 @@ + +### Backend 서버 세팅 +1. docker 설치 +2. docker 빌드: `docker-compose -f docker-compose.yaml up --build` + +3. API 서버 접속: +`http://localhost:8000/docs` + +4. 초기 구조: +- FastAPI 기반 REST API 서버 +- PostgreSQL 연결 및 ORM 지원 +- `/test/ping_db` 엔드포인트를 통한 DB 연결 상태 확인 + + +### 폴더 구조 +``` +. +├── docker-compose.yaml +├── Dockerfile +├── README.md +└── src + ├── __init__.py + ├── assets + ├── config.py + ├── database.py + ├── main.py + ├── models + ├── requirements.txt + ├── routers + │ └── test_db.py + ├── services + └── utils +``` \ No newline at end of file diff --git a/getcloser/backend/docker-compose.yaml b/getcloser/backend/docker-compose.yaml new file mode 100644 index 0000000..b692ad2 --- /dev/null +++ b/getcloser/backend/docker-compose.yaml @@ -0,0 +1,28 @@ +version: "3.9" + +services: + web: + build: . + container_name: getcloser_backend + ports: + - "8000:8000" + depends_on: + - db + env_file: + - .env + restart: unless-stopped + + db: + image: postgres:15 + container_name: postgres_db + environment: + POSTGRES_USER: user + POSTGRES_PASSWORD: password + POSTGRES_DB: app_db + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" + +volumes: + postgres_data: \ No newline at end of file diff --git a/getcloser/backend/src/__init__.py b/getcloser/backend/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/getcloser/backend/src/config.py b/getcloser/backend/src/config.py new file mode 100644 index 0000000..09e7a64 --- /dev/null +++ b/getcloser/backend/src/config.py @@ -0,0 +1,10 @@ +import os +from pydantic_settings import BaseSettings + +class Settings(BaseSettings): + DATABASE_URL: str = os.getenv("DATABASE_URL", "postgresql+psycopg2://user:password@db:5432/app_db") + SECRET_KEY: str = os.getenv("SECRET_KEY", "change-me-in-prod") + ALGORITHM: str = "HS256" + ACCESS_TOKEN_EXPIRE_MINUTES: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "60")) + +settings = Settings() diff --git a/getcloser/backend/src/database.py b/getcloser/backend/src/database.py new file mode 100644 index 0000000..7608cd5 --- /dev/null +++ b/getcloser/backend/src/database.py @@ -0,0 +1,15 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, declarative_base +from .config import settings + +engine = create_engine(settings.DATABASE_URL, echo=False, future=True) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, future=True) +Base = declarative_base() + +# 간단한 의존성 +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() diff --git a/getcloser/backend/src/main.py b/getcloser/backend/src/main.py new file mode 100644 index 0000000..39cbd69 --- /dev/null +++ b/getcloser/backend/src/main.py @@ -0,0 +1,50 @@ +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from dotenv import load_dotenv +import os + +from .database import engine, Base +from .routers import test_db + + +# .env 파일 로드 +load_dotenv() + +# 간단히 앱 시작 시 테이블 생성 (개발용) +Base.metadata.create_all(bind=engine) + +# FastAPI 앱 생성 +app = FastAPI( + title="Devfactory 친해지길바라", + description="Devfactory 친해지길바라 API 서버", + version="1.0.0", + docs_url="/docs", + redoc_url="/redoc", +) + +# CORS 미들웨어 설정 +origins = os.getenv("CORS_ORIGINS", "").split(",") +app.add_middleware( + CORSMiddleware, + allow_origins=origins, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +app.include_router(test_db.test_router) + + +@app.get("/") +async def read_root(): + """루트 엔드포인트""" + return { + "message": "Devfactory 친해지길바라 API 서버", + "version": "1.0.0", + "status": "running" + } + +@app.get("/health") +async def health_check(): + """헬스 체크 엔드포인트""" + return {"status": "healthy"} diff --git a/getcloser/backend/src/requirements.txt b/getcloser/backend/src/requirements.txt new file mode 100644 index 0000000..fd0299d --- /dev/null +++ b/getcloser/backend/src/requirements.txt @@ -0,0 +1,6 @@ +fastapi +uvicorn[standard] +SQLAlchemy +pydantic +pydantic_settings +psycopg2-binary \ No newline at end of file diff --git a/getcloser/backend/src/routers/test_db.py b/getcloser/backend/src/routers/test_db.py new file mode 100644 index 0000000..6e202b1 --- /dev/null +++ b/getcloser/backend/src/routers/test_db.py @@ -0,0 +1,15 @@ +from fastapi import FastAPI, Depends, APIRouter +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy import text +from ..database import get_db + +test_router = APIRouter(prefix="/test", tags=["test"]) + +@test_router.get("/ping_db") +def ping_db(db=Depends(get_db)): + try: + # 단순 쿼리 실행 (PostgreSQL 연결 확인) + db.execute(text("SELECT 1")) + return {"status": "ok", "message": "PostgreSQL 연결 성공"} + except SQLAlchemyError as e: + return {"status": "error", "message": str(e)} \ No newline at end of file diff --git a/getcloser/frontend/Dockerfile b/getcloser/frontend/Dockerfile new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/getcloser/frontend/Dockerfile @@ -0,0 +1 @@ +