여행 맞춤 설문을 기반으로 루트를 추천하는 FastAPI 백엔드입니다.
PostgreSQL + SQLAlchemy + Alembic, JWT 인증, bcrypt 해싱을 사용합니다.
- Python 3.11
- PostgreSQL 13+ (로컬:
localhost:5432) - OS X / Linux / WSL 권장
python3.11 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt루트 경로에 .env 파일을 생성합니다.
# DB
DATABASE_URL=postgresql://postgres:mypassword@localhost:5432/travel_db
# JWT
JWT_SECRET=change-me-to-a-long-random-string
# (선택) 서버 설정
APP_HOST=127.0.0.1
APP_PORT=8000dropdb -U postgres travel_db
createdb -U postgres travel_dbalembic init alembic(중요) 생성된 alembic/env.py 파일을 수정하여, 프로젝트의 .env 파일과 데이터베이스 모델을 직접 참조하도록 설정해야 합니다. (자세한 설정 코드는 프로젝트 내 alembic/env.py 파일 참조)
이렇게 하면 alembic.ini 파일에 데이터베이스 접속 정보를 직접 적을 필요 없이 안전하게 마이그레이션을 관리할 수 있습니다.
리비전에 Vector 타입 컬럼이 포함되면, 해당 리비전 파일 상단과 upgrade() 초기에 아래를 반드시 추가하세요.
# alembic/versions/xxxx_init_schema.py
from alembic import op
import sqlalchemy as sa
from pgvector.sqlalchemy import Vector # ★ 추가
def upgrade():
# ★ DB 확장 설치 보장 (여러 번 실행되어도 안전)
op.execute("CREATE EXTENSION IF NOT EXISTS vector;")
# 예시: 벡터 컬럼 포함 테이블
op.create_table(
"place_embeddings",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("embedding", Vector(768), nullable=True), # ★ Vector 타입
)alembic revision --autogenerate -m "sync schema with new models"
alembic upgrade headINSERT INTO region_provinces (province_id, kor_name, eng_name)
VALUES ('11', '서울', 'Seoul')
ON CONFLICT (province_id) DO NOTHING;
INSERT INTO region_cities (region_id, province_id, kor_name, eng_name)
VALUES ('110000', '11', '서울특별시', 'Seoul')
ON CONFLICT (region_id) DO NOTHING;uvicorn app.main:app --reloadSwagger UI: http://127.0.0.1:8000/docs
ReDoc: http://127.0.0.1:8000/redoc
- User: 이메일/비밀번호(해시), 닉네임, 소개, 거주지 코드
- Place: 장소 정보
- Route: 맞춤 태그 기반 추천
- SurveySession: 설문 응답 저장
POST /api/v1/auth/register
Content-Type: application/json
{
"email": "[email protected]",
"nickname": "traveler1",
"password": "mypassword123",
"city_id": "110000"
}POST /api/v1/auth/login
Content-Type: application/x-www-form-urlencoded
[email protected]&password=mypassword123POST /api/v1/recommendations/survey
Authorization: Bearer <token>
Content-Type: application/json
{
"period_days": 3,
"env": "city",
"with_whom": "friend",
"move": "public",
"atmosphere": "자유롭고 감성적인",
"place_count": 3
}POST /api/v1/recommendations/routes
Content-Type: application/json
{
"period_days": 2,
"env": "sea",
"with_whom": "love",
"move": "car",
"atmosphere": "아늑하고 로맨틱한",
"place_count": 2
}- ModuleNotFoundError: No module named 'jwt' →
pip install PyJWT - ForeignKeyViolation (users.city_id) →
region_cities시드 필요 - Mapper 'User(users)' has no property 'trips' → Trip 모델 잔존 확인
- AttributeError: crud_user.get_by_email → CRUD 패턴 통일 필요