고용노동 정책 어시스턴트 배포 후기: FastAPI + MySQL(Railway) + React(Vercel) 조합 완전체 구축기

오늘은 React 프론트엔드와 FastAPI 백엔드로 구성된 ‘고용노동 정책 어시스턴트’ 애플리케이션을 배포하는 과정에서 마주친 여러 문제와 이를 해결한 방법에 대해 자세히 공유하려고 합니다. 특히 Vercel과 Render라는 두 다른 플랫폼에 배포하면서 발생한 데이터베이스 연결, CORS, 라이브러리 의존성 등의 이슈를 어떻게 해결했는지 정리했습니다.

##

1. 배포 환경 구성

프로젝트는 다음과 같이 구성되어 있습니다:

  • 프론트엔드: React (Vercel에 배포)
  • 백엔드: FastAPI (Render에 배포)
  • 데이터베이스: MySQL (Railway에 호스팅)

처음에는 로컬에서 모든 것이 잘 작동했지만, 실제 배포 환경에서는 여러 문제가 발생했습니다.


🛠 배포 과정

1. Railway로 MySQL 무료 DB 생성

MySQL을 로컬에서 뭘로 바꿀지 고민했다. 처음엔 맨날 쓰던 aws RDS DB를 쓸까 하다가 굳이 aws로 배포 안 할건데 하다가 찾다가 발견했다. 꽤나 괜찮은 것 같다. 관련 정보가 좀 부족하긴한데 앞으로도 유용하게 쓸듯?

image-20250425025403816

DATABASE_URL=mysql:*********************net:42077/railway
MYSQL_HOST=****
MYSQL_PORT=42077
MYSQL_USER=root
MYSQL_PASSWORD=****
MYSQL_DB=railway

문제 1: 데이터베이스 연결 오류

오류 현상

백엔드를 Render에 배포한 후 첫 번째로 마주친 문제는 다음과 같은 데이터베이스 연결 오류였습니다:

pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'mysql.railway.internal' ([Errno -2] Name or service not known)")

오류 원인

로그를 분석한 결과, FastAPI 애플리케이션이 mysql.railway.internal이라는 내부 호스트명으로 MySQL 데이터베이스에 연결을 시도하고 있었습니다. 이 호스트명은 Railway 플랫폼 내부에서만 접근 가능한 주소로, Render에서 호스팅되는 애플리케이션에서는 접근할 수 없었습니다.

해결 방법

Render 대시보드에서 환경 변수를 확인한 결과, MYSQL_HOSTmysql.railway.internal로 설정되어 있었습니다. 이를 Railway 데이터베이스의 외부 접속 URL인 centerbeam.proxy.rlwy.net으로 변경하고, 포트도 3306에서 42077로 수정했습니다.

# 변경 전
MYSQL_HOST=mysql.railway.internal
MYSQL_PORT=3306

# 변경 후
MYSQL_HOST=centerbeam.proxy.rlwy.net
MYSQL_PORT=42077

그리고 DATABASE_URL도 외부 접속 URL을 사용하도록 설정했습니다:

DATABASE_URL=mysql://root:sc****************xy.rlwy.net:42077/railway

##


2. Render로 FastAPI 배포

Render에 백엔드 프로젝트를 연결하고, 위에서 설정한 MySQL 변수들을 .env 파일 또는 Render 환경변수에 등록했다.

👉 주의할 점 .env 파일이 backend 폴더 내부가 아니라 루트(root) 에 있다면 Settings(BaseSettings) 에서 env_file = ".env"로는 못 불러온다. backend/.env로 위치를 맞춰줘야 정상 동작!

처음에 .env가 frontend에 한개, root에 한개 있어서 좀 이 에러가 오래 걸렸다. 다음부터는 .env파일 처음부터 디렉토리 잘 해놔야겠다. 로컬에서는 문제가 없어서 넘겼더니 이런 문제가 생겼다.


###

3. Pinecone 관련 에러

Exception: The official Pinecone python package has been renamed from `pinecone-client` to `pinecone`.

✅ 해결 방법

requirements.txt에서 pinecone-client를 제거하고 pinecone 최신 패키지를 설치한 후 다시 배포했다.

최신버전의 pinecone 에서는 pinecone-client가 아니라 pinecone을 사용한다. langchain도 그렇고 이런 건 공식문서에서 계속 바뀌어서 좀 귀찮다. 걍 둘 다 되게 나두면 안되나.


###

4. CORS 정책 문제

가장 시간을 오래 잡아먹었던 이슈 😵‍💫

증상

  • 프론트엔드에서 회원가입 버튼 클릭 시 다음 오류 발생:
XMLHttpRequest cannot load https://labor-policy-assistant.onrender.com/api/v1/auth/register due to access control checks.
Preflight response is not successful. Status code: 400

원인

.env 파일에 정의한 CORS_ORIGINS["http://localhost:3000"]만 있어서, 실제 배포된 프론트엔드 URL이 허용되지 않음.

✅ 해결 방법

.env에 다음처럼 배포 URL 추가:

CORS_ORIGINS=["http://localhost:3000", "https://labor-policy-assistant.vercel.app"]

그리고 config.py에서 이를 settings.CORS_ORIGINS로 불러오게 되어 있으므로, FastAPI에 CORS 미들웨어는 정상적으로 적용됨 ✅


5. React에서 API URL 하드코딩 문제

처음엔 http://localhost:8000으로 하드코딩된 상태였음 → 실제 배포된 백엔드 API는 Render에서 호스팅된 도메인이므로, 하드코딩하면 당연히 CORS 오류.

✅ 해결 방법

  • .env 파일에 다음처럼 작성:
REACT_APP_API_URL=https://labor-policy-assistant.onrender.com
  • 코드에서 하드코딩된 부분을 다음처럼 수정:
const API_URL = process.env.REACT_APP_API_URL;

✅ 최종 확인

  • 회원가입/로그인 정상 작동
  • 정책 목록 및 추천 정상 호출
  • AI 요약 및 챗봇 기능 정상 작동
  • 프론트와 백엔드 완벽 연동

🔚 마무리

이번 배포는 단순히 서버 올리는 수준이 아니라,

  • 환경변수 관리
  • CORS 처리
  • API 연결
  • 패키지 버전 이슈
  • 데이터베이스 연결

까지 모두 포함되어서 좀 오래걸렸던 것 같다. 그래도 하루만에 끝나서 다행이다. 이제 다음 프로젝트 바로 들어가자.