Vercel에서 안 되길래 Railway로 옮겼다 — 비개발자의 첫 Docker 배포

AI 코딩 시작하기··15분 읽기·
Railway+Docker로 Next.js 앱을 배포하는 과정 — Vercel 서버리스 한계 해결

"Vercel에 올렸는데 메일 감시가 안 돼요"

Echo Mail은 메일이 오면 자동으로 알림을 보내주는 서비스예요. 근데 Vercel에 올리니까 메일 감시가 안 됐습니다.

이유는 간단했어요. 비유하자면 이런 겁니다:

Vercel = 편의점 알바생. 손님(요청)이 오면 일하고, 손님이 없으면 퇴근함. Railway = 24시간 경비원. 손님이 없어도 자리를 지키고 있음.

메일 감시는 "5분마다 메일함을 확인하는" 작업이에요. 손님이 요청하지 않아도 계속 확인해야 하는 거라, 편의점 알바생(Vercel)한테는 시킬 수 없는 일이었습니다.

Docker가 뭔데?

Railway로 옮기려면 Docker라는 걸 써야 했어요. 처음 들으면 겁나는데, 비유하면:

Docker = 이사할 때 쓰는 포장 박스

내 컴퓨터에서 돌아가는 프로그램을 박스에 넣어서, 다른 컴퓨터(Railway 서버)에 가져다 놓으면 그대로 돌아가는 겁니다. "내 컴퓨터에선 되는데 서버에선 안 돼요" 문제를 해결하는 기술이에요.

박스에 뭘 넣을지 적어놓는 목록이 Dockerfile이고, AI한테 이 목록을 만들게 시켰습니다.

AI한테 Dockerfile 시키기 — "Docker로 배포해줘"의 결과

Docker로 배포해줘

이렇게 시켰더니, 박스 크기가 1GB(!)짜리 Dockerfile이 나왔어요. 서버 비용이 박스 크기에 비례하는데, 이건 이사할 때 안 쓰는 짐까지 전부 넣은 거나 마찬가지.

프롬프트를 바꿨습니다:

당신은 DevOps 전문가입니다.

[현재 상태]
- Next.js 14 + TypeScript 프로젝트
- 데이터베이스 연결 도구(Prisma ORM) 사용 중
- 5분마다 메일함을 확인하는 스케줄러 포함

[요구사항]
- 최종 박스(이미지) 크기 300MB 이하
- 실행에 필요한 파일만 최종 박스에 넣을 것
- 데이터베이스 연결 설정이 빌드 단계에 포함될 것
- 보안을 위해 관리자 권한 없이 실행

[제약조건]
- 환경변수는 Railway에서 주입 (코드에 넣지 말 것)
- 빌드할 때 실제 데이터베이스에 연결하지 말 것
비교 "배포해줘" 바꾼 프롬프트
역할 부여 없음 "DevOps 전문가"
크기 제한 없음 300MB 이하
보안 없음 관리자 권한 없이 실행
DB 연결 빌드 중 연결 시도 (실패) "빌드 때 DB 연결 금지" 명시
결과 1GB 박스 250MB 박스
마지막 제약조건 "빌드할 때 DB에 연결하지 말 것"이 가장 중요했어요. 이걸 안 넣었더니 빌드가 17분 동안 멈추다가 타임아웃 났거든요.

삽질 3연속 — 빌드 성공까지

AI가 만든 Dockerfile로 첫 빌드를 돌렸는데, 3번 연속 실패했습니다.

삽질 1: "파일이 없다"는 에러
Error: @prisma/client did not initialize yet.

데이터베이스 설정 파일을 박스에 안 넣은 거였어요. AI한테 피드백:

빌드에서 위 에러가 납니다.
데이터베이스 설정 파일(prisma 폴더)을
빌드 초기 단계에서 복사해주세요.

한 줄 추가로 해결.

삽질 2: 설정 파일이 무시 목록에 있었다

Docker에는 "이 파일은 박스에 안 넣겠다"는 무시 목록(.dockerignore)이 있는데, 거기에 필요한 설정 파일이 들어가 있었어요. 무시 목록에서 빼니까 해결.

삽질 3: 빌드가 17분 동안 멈춤

이게 제일 당황스러웠어요. 빌드 로그를 보니까 데이터베이스에 연결하려고 무한 대기하고 있었습니다. 박스를 만드는 단계(빌드)에서는 아직 서버가 아니니까 DB에 접근할 수가 없는 건데, 빌드 스크립트에 DB 연결 코드가 들어있던 거예요.

빌드가 17분 이상 걸린 후 타임아웃됩니다.
빌드 스크립트에서 DB 연결 코드를 제거하고,
순수하게 코드 컴파일만 실행되도록 수정해주세요.
교훈: 박스를 만들 때(빌드)는 코드만 넣고, 실제 연결은 박스를 열었을 때(실행)에 하는 구조여야 합니다. 이사 박스 포장할 때 전기 콘센트 꽂아보는 것처럼 — 아직 새 집에 안 갔는데 그건 안 되잖아요.

배포 후에도 터진 버그 4개

빌드 성공이 끝이 아니었어요. 실제로 돌리니까 바로 4개 버그:

뭐가 터졌나 어떻게 고쳤나
같은 메일 반복 처리 메일을 "읽음" 처리하는 코드에 버그 데이터 형식 수정
납품일이 하루 밀림 서버 시간이 한국이 아님 (Railway는 미국) 한국 시간 변환 추가
알림 기록이 안 남음 개발 중 주석 처리해놓고 까먹음 주석 해제
알림 중복 발송 기록이 없으니 중복 체크 불가 기록 기반 중복 체크 추가
3번(주석 처리 까먹음)이 4번(중복 발송)을 일으킨 연쇄 버그였어요. 개발할 때 "나중에 켜야지"라고 해놓은 걸 까먹은 거죠.

AI한테 피드백할 때 이렇게 했습니다:

알림이 중복 발송됩니다.
확인해보니 알림 기록 테이블에 데이터가 하나도 없습니다.
DB 저장 코드가 주석 처리되어 있는 것 같습니다.

1. 주석 해제해주세요
2. 이미 보낸 건 중복 체크하는 로직 추가해주세요
3. 개발용 주석은 TODO로 표시해서 배포 전에 찾을 수 있게 해주세요

3번 요청이 핵심이에요. 같은 실수를 반복하지 않으려면 "까먹을 수 있는 것"을 찾기 쉽게 만들어야 합니다.

Vercel vs Railway — 뭘 쓸지 고르는 기준

이런 경우 Vercel Railway
웹사이트/블로그 O
API 서버 O O
5분마다 메일 체크 X O
실시간 채팅(WebSocket) X O
대용량 파일 처리 X O
기준은 하나예요: "서버가 항상 떠 있어야 하나?"
  • 아니면 → Vercel (무료 플랜도 넉넉)
  • 맞으면 → Railway (월 $5부터)
실제로 Echo Mail은 둘 다 씁니다. 웹 화면은 Vercel, 메일 감시는 Railway. 하나만 골라야 하는 게 아니에요.

자주 하는 실수 정리

  • "Vercel에서 왜 안 돼요?" — 서버리스는 요청이 없으면 꺼짐. 상시 실행 작업은 구조적으로 불가
  • Dockerfile에서 DB 연결 — 빌드(포장)할 때 DB에 접근하면 안 됨. 실행(개봉) 때 연결할 것
  • 개발 중 주석 처리 까먹기 — TODO 표시로 배포 전 체크리스트 만들어둘 것
  • 서버 시간 = 한국 시간 아님 — 해외 서버는 UTC 기준. 한국 시간 변환 반드시 필요
  • Docker가 어려워 보이지만, AI한테 "현재 상태 + 요구사항 + 제약조건"을 주면 Dockerfile을 만들어줍니다. 다만 한 번에 성공하지는 않았어요. 삽질 3번, 운영 버그 4번 — 총 7번 고쳐서 안정화됐습니다. 그래도 직접 Docker를 배우는 것보다는 훨씬 빨랐어요.

    공유

    댓글