4장. 로컬에서 서비스 만들기 (React + Express + PostgreSQL)
드디어 서비스를 만듭니다. 3장에서 "무엇을 만들지"를 기획으로 정리했으니, 이번 장에서는 그 기획을 실제로 동작하는 서비스로 바꿉니다. 다시 강조하지만, 여러분은 코드를 한 줄도 직접 타이핑하지 않습니다. 3장에서 정리한 기획을 Claude Code에게 넘기고, "요청(프롬프트) → 승인 → 확인"을 반복하며 완성해 나갑니다. 이 장의 핵심은 "어떤 코드가 만들어지는가"가 아니라 "어떻게 요청하고, 무엇을 확인하는가" 입니다.
한 조각을 만들 때마다 눈으로 확인하고 다음으로 넘어갑니다. 그래야 문제가 생겨도 어디서 틀어졌는지 바로 찾을 수 있습니다. 순서대로 따라오세요.
[지금 여기]
우리는 22단계를 거쳐 "라이브 투표 서비스"를 직접 만들고, 컨테이너에 담아, AWS 클라우드에 배포합니다. 아래가 그 전체 여정 지도입니다. 지금은 4단계, 서비스를 처음으로 내 컴퓨터에서 동작시키는 자리에 있습니다.
- 1장개발 환경 준비 (터미널 / Node.js / Git / GitHub / VS Code / Claude Code)
- 2장Claude Code 사용법 익히기
- 3장무엇을 만들지 기획 (라이브 투표 서비스)
- 4장로컬에서 서비스 만들기 (React + Express + PostgreSQL)
- 5장Docker 개념
- 6장Dockerfile 작성
- 7장컨테이너 빌드·실행
- 8장AWS 시작 (계정 / IAM / 리전 / 비용)
- 9장이미지 태깅
- 10장ECR에 이미지 올리기
- 11장VPC 네트워크 구성
- 12장RDS 데이터베이스 생성
- 13장SSM 터널로 RDS 초기화
- 14장ECS Fargate + ALB로 배포 (기본 완성)
- 15장CI/CD (GitHub Actions)
- 16장IaC (Terraform)
- 17장배포 자동화 연결
- 18장현업 운영 구조 이해
- 19장무중단 배포
- 20장신규 버전 배포 & 롤백
- 21장(심화) 프론트를 Vercel로 분리 배포
- 22장마무리 (회고 + 리소스 삭제)
- 방금 끝낸 것: 3장에서 "라이브 투표 서비스"를 무엇으로 만들지 기획했습니다. 설문·선택지·득표수 데이터 모델과, 서버가 열어 줄 세 개의 창구(엔드포인트)를 종이에 그리듯 정리해 두었습니다.
- 이번 장에서 하는 것: 그 기획을 Claude Code에게 넘겨, 프론트엔드 + API 서버 + 데이터베이스로 이루어진 투표 서비스를 내 컴퓨터(localhost)에서 실제로 동작시킵니다. 마지막에는 GitHub에도 올립니다.
이번 장에서 완성되는 것
한 문장으로: 투표를 만들고, 표를 던지고, 결과를 막대그래프로 보는 웹 서비스가 내 컴퓨터에서 돌아가고, 새로고침해도 결과가 그대로 남습니다.
이렇게 되면 성공입니다: 브라우저에서 http://localhost:5173에 접속해
설문을 만들고 투표한 뒤, 페이지를 새로고침해도 득표수가 사라지지 않고
그대로 보입니다. 그리고 그 코드가 GitHub의 내 비공개 저장소에 올라가 있습니다.
사전 조건
이 장은 1~3장의 결과물 위에서 시작합니다. 아래가 갖춰져 있어야 합니다.
- 1장 완료: Node.js, Git, VS Code, Claude Code가 설치돼 있고, 문서
폴더에
vote-app폴더가 있으며, VS Code로 그 폴더를 열 수 있습니다. - 2장 완료: Claude Code에 프롬프트로 지시하고, 오류가 나면 메시지를 붙여넣어 고쳐 달라고 하는 흐름에 익숙합니다.
- 3장 완료: 투표 서비스의 기획(설문 데이터 모델 polls/options, 세 엔드포인트)이 정리돼 있습니다.
- 시작 상태 만들기: VS Code를 실행해 파일 → 폴더 열기(Open Folder)로
vote-app을 엽니다. 터미널 → 새 터미널(New Terminal)로 터미널을 열고, 아래로 위치를 확인한 뒤claude를 실행합니다.
pwd # 경로 끝이 /vote-app 이어야 합니다
claude # Claude Code 실행 (AI 입력창이 뜹니다)
이 장에는 Docker Desktop이 하나 더 필요합니다
뒤(4.6)에서 데이터베이스를 Docker로 띄웁니다. 그때 Docker Desktop이
설치돼 있고 실행 중이어야 합니다. 아직 없다면 지금 미리
https://www.docker.com/products/docker-desktop 에서 내 운영체제용
설치 파일을 받아 설치하고, 설치 후 Docker Desktop 앱을 한 번 실행해
두세요. (Docker가 정확히 무엇인지는 5장에서 제대로 배웁니다. 여기서는
"DB를 간편하게 띄우는 도구"로만 씁니다.) 설치가 부담되면 4.5까지 먼저
진행하고, 5장의 Docker 설치 안내를 본 뒤 4.6으로 돌아와도 됩니다.
4.1 우리가 만들 서비스의 3층 구조
본격적으로 만들기 전에, 우리가 만들 서비스가 어떤 조각들로 이루어지는지 알아 둡시다. 대부분의 웹 서비스는 세 개의 층으로 나뉩니다.
프론트엔드(Frontend) 사용자가 눈으로 보고 클릭하는 화면 부분입니다. 브라우저에서 돌아갑니다. 우리 서비스에서는 투표 화면, 결과 막대그래프가 여기에 해당합니다. (React로 만듭니다.)
백엔드 / API 서버(Backend) 화면 뒤에서 실제 일을 처리하는 부분입니다. "투표 한 표 더하기", "설문 정보 가져오기" 같은 요청을 받아 처리하고, 데이터베이스를 다룹니다. 사용자 눈에는 보이지 않습니다. (Node.js + Express로 만듭니다.)
데이터베이스(Database, DB) 정보를 저장해 두는 창고입니다. 설문 내용, 선택지, 득표수가 여기에 쌓입니다. 서버가 이 창고에 정보를 넣고 꺼냅니다. (PostgreSQL을 씁니다.)
세 층은 이렇게 협력합니다. 사용자가 화면(프론트엔드)에서 버튼을 누르면, 그 요청이 API 서버(백엔드)로 가고, 서버는 데이터베이스에서 값을 꺼내거나 바꾼 뒤 결과를 화면으로 돌려줍니다.
실제로 어디에 쓰이나. 이 3층 구조는 우리 투표 서비스만의 특별한 방식이 아니라, 여러분이 매일 쓰는 서비스 대부분이 이 구조입니다.
- 쇼핑몰: 상품 목록 화면(프론트) → 주문·결제 처리(API) → 상품·주문 정보 저장(DB).
- SNS: 피드 화면(프론트) → 글 올리기·좋아요 처리(API) → 게시물·댓글 저장(DB).
- 배달 앱: 가게·메뉴 화면(프론트) → 주문 접수·배차(API) → 주문 상태 저장(DB).
공통점이 보이죠. 보여 주는 층 / 처리하는 층 / 저장하는 층을 나누면, 각 층을 따로 만들고 따로 고칠 수 있어 편합니다. 우리도 이 순서대로 프론트 → API → DB를 하나씩 붙여 갑니다. 이 그림을 머릿속에 넣어 두면, 앞으로 무엇을 만드는지 길을 잃지 않습니다.
4.2 프로젝트 뼈대 만들기
이제 3장에서 준비한 기획을 Claude Code에 넣습니다. 곧바로 코드를 만들게 하지 말고, 계획을 먼저 받아 보는 게 좋습니다. 2장에서 배운 대로 "아직 코드는 만들지 말고 계획부터"를 잊지 마세요.
Claude Code가 만들 순서를 계획으로 제시하면, 방향이 맞는지 읽어 봅니다. 프론트 → API → DB 순서로 하나씩 붙이는 계획이면 좋습니다. 확인했으면 뼈대부터 만들라고 승인합니다.
프로젝트 뼈대(Boilerplate / Scaffold) 서비스의 기본 틀입니다. 아직 기능은 없지만, 프론트엔드 폴더와 백엔드 폴더, 기본 설정 파일 등 "앞으로 살을 붙일 골격"이 갖춰진 상태입니다.
Claude Code는 뼈대를 만들 때 여러분 대신 명령을 실행합니다. 예를 들어
프론트는 npm create vite@latest frontend -- --template react 같은 명령으로
React 프로젝트를 만들고, 백엔드는 npm init으로 Express 프로젝트를 준비합니다.
이런 명령을 실행하기 전에 Claude Code가 "실행해도 될까요?"라고 물으면,
내용을 보고 승인하면 됩니다. (직접 외워서 칠 필요는 없습니다.)
4.3 프론트엔드 만들기 — 투표 화면
이제 사용자가 볼 화면부터 만들어 달라고 합니다. 화면은 React라는 도구로 만듭니다.
React / Vite - React: 화면(프론트엔드)을 만드는 데 가장 널리 쓰는 도구입니다. 화면을 "버튼", "목록", "그래프" 같은 조각(컴포넌트)으로 나눠서 만들고, 데이터가 바뀌면 화면을 알아서 다시 그려 줍니다. - Vite: React로 만든 화면을 빠르게 실행하고 미리 볼 수 있게 해 주는 도구입니다. 개발 중 화면을 브라우저에 띄워 확인할 때 씁니다. 둘 다 Claude Code가 알아서 설정하므로, 이름과 역할만 알아 두면 됩니다.
실제로 어디에 쓰이나. React는 취미 프로젝트용 장난감이 아니라, 큰 회사들이 실제 서비스 화면을 만드는 데 씁니다.
- 인스타그램·페이스북을 만든 회사(Meta)가 React를 직접 만들어 씁니다.
- 넷플릭스, 토스, 배달의민족 같은 서비스의 웹 화면도 React 계열로 만들어져 있습니다.
- 사내 관리자 화면(대시보드, 통계 페이지)처럼 데이터가 자주 바뀌는 화면에도 React가 흔히 쓰입니다.
즉, 우리가 배우는 도구가 곧 현업에서 쓰는 도구입니다. 이제 투표 화면을 만들어 달라고 요청합시다.
"우선 가짜 데이터로 화면만"이라고 요청한 데 주목하세요. 서버와 DB가 아직 없어도 화면을 먼저 눈으로 확인하기 위한 요령입니다. 이렇게 조각을 하나씩 확인하며 나아가면 문제가 생겨도 원인을 찾기 쉽습니다. 프롬프트 뒤쪽의 "상대 경로(/api) + 개발 프록시"가 왜 중요한지는 4.5에서 따로 설명합니다. 지금은 그냥 그렇게 시켜 두기만 하면 됩니다.
[맛보기] 만든 화면을 브라우저에 띄워 보기
만들어졌으면 실제로 화면을 띄워, 처음으로 내 손으로 결과를 확인해 봅니다.
Claude Code가 개발 서버를 실행하고 http://localhost:5173 같은 주소를
알려 줍니다. 그 주소를 브라우저 주소창에 입력해, 투표 화면이 뜨는지 눈으로
확인하세요. 아직 가짜 데이터지만 질문·선택지·막대그래프 모양이 잡혔으면
성공입니다.
http://localhost:5173의 5173은 Vite 개발 서버가 쓰는
"포트 번호"입니다. 한 컴퓨터 안에서 여러 프로그램이 각자 다른 번호(문)로
통신하는데, Vite는 보통 5173번을 씁니다. 뒤에서 만들 API 서버는 3000번을
씁니다. 번호가 다르면 서로 다른 프로그램이라고 생각하면 됩니다.
화면이 이상하거나 안 뜨면, 2장에서 배운 대로 터미널에 나온 오류 메시지를 그대로 복사해 Claude Code에게 붙여넣고 고쳐 달라고 하세요. 이 "오류 붙여넣고 고치기" 과정 자체가 정상적인 개발 흐름입니다.
설문 만들기 화면도 추가하기
투표 화면이 잡혔으니, 새 설문을 직접 만드는 화면도 있어야 3장 완료 기준의 "설문을 만들고"가 채워집니다. 이어서 요청합니다.
완성되면 홈 화면이 이렇게 보입니다. (선택지는 아직 서버가 없으니, 이 화면의 "만들기"가 실제로 저장되는 것은 4.4~4.6에서 API와 DB를 붙인 뒤부터입니다.)
4.4 API 서버 만들기 — 설문·투표·결과
화면이 잡혔으니, 이번엔 뒤에서 일할 API 서버를 만듭니다. API 서버는 Express라는 도구로 만듭니다.
Express Node.js에서 API 서버를 만들 때 가장 많이 쓰는 도구입니다. "이 주소로 요청이 오면 이 일을 해라"라는 규칙(엔드포인트)을 간단하게 정의할 수 있게 해 줍니다.
엔드포인트(Endpoint)
서버가 열어 두는 "요청 창구"입니다. POST /api/polls처럼 "주소 + 방식"의
짝으로, 각 창구가 하나의 일(설문 만들기, 투표하기 등)을 맡습니다.
실제로 어디에 쓰이나. 우리가 화면에서 무언가를 누를 때, 뒤에서는 거의 항상 이런 API 서버가 요청을 받아 처리합니다.
- 로그인 버튼을 누르면 → "이 아이디·비밀번호가 맞나?"를 확인하는 API가 일합니다.
- 쇼핑몰에서 주문하기를 누르면 → 재고를 줄이고 주문을 기록하는 API가 일합니다.
- 지도 앱에서 길찾기를 누르면 → 경로를 계산해 돌려주는 API가 일합니다.
우리 투표 서비스에서는 3장에서 정리한 세 개의 창구(엔드포인트)를 그대로 요청합니다.
여기서도 "DB는 나중에, 지금은 임시 저장으로 먼저"라는 단계 나누기를 썼습니다. 서버가 혼자서도 동작하는지 먼저 확인한 뒤 DB를 붙이면, 문제의 원인이 서버인지 DB인지 구분하기 쉽습니다.
[맛보기] API가 실제로 응답하는지 확인하기
Claude Code가 서버를 실행하고, 스스로 요청을 보내 응답을 확인한 결과를 알려 줍니다. "설문 생성 성공", "투표 후 득표수 증가 확인" 같은 결과가 나오면 서버가 제대로 도는 것입니다. 화면 없이 서버 혼자서도 일을 한다는 걸 눈으로 본 셈입니다.
4.5 왜 상대 경로 /api로 부를까 — CORS와 개발 프록시
이제 화면(5173번)과 API 서버(3000번)가 둘 다 준비됐습니다. 그런데 이 둘을 연결하려 할 때 초보자가 거의 반드시 만나는 문제가 하나 있습니다. 미리 피해 두었으니, 왜 그렇게 했는지 이해하고 넘어갑시다.
CORS (교차 출처 요청 차단)
브라우저의 보안 규칙입니다. 화면이 실행되는 주소(localhost:5173)와,
화면이 데이터를 요청하는 주소(localhost:3000)가 서로 다르면, 브라우저는
"출처(origin)가 다르다"며 그 요청을 기본적으로 막습니다. 이 막힘을 CORS
문제라고 부릅니다.
개발 프록시(Dev Proxy)
"요청을 대신 전달해 주는 중개인"입니다. 화면은 늘 자기 자신(5173번)에게만
요청을 보내고, Vite가 그중 /api로 시작하는 요청만 몰래 3000번(API
서버)으로 넘겨 줍니다. 화면 입장에서는 계속 같은 주소랑만 대화하므로,
브라우저가 "출처가 다르다"고 막을 일이 없습니다.
그래서 4.3의 프롬프트에서 두 가지를 미리 시켜 둔 것입니다.
- 화면이 API를 부를 때 절대 주소(
http://localhost:3000/...)가 아니라 상대 경로(/api/...)로 부르게 했습니다. vite.config에 개발 프록시를 설정해,/api요청을 3000번으로 넘기게 했습니다. (Vite가 만들어 준 설정은 대략 이런 모습입니다.)
// frontend/vite.config.js — Claude Code가 만든 설정 예시 (직접 칠 필요 없음)
server: {
proxy: {
'/api': {
target: 'http://localhost:3000', // /api 요청을 API 서버로 넘김
changeOrigin: true,
},
},
}
실제로 어디에 쓰이나. "화면과 API가 같은 주소인 것처럼 보이게" 하는 이 방식은 개발 현장에서 표준처럼 쓰입니다.
- 개발 중에는 이렇게 Vite 개발 프록시로 화면과 API를 이어 붙입니다.
- 배포할 때는 프록시 역할을 Nginx 같은 웹서버가 대신 맡습니다(2부에서
직접 합니다). 방식이 바뀌어도 화면 코드는 그대로
/api만 부르면 되니, 화면을 고칠 필요가 없습니다.
즉 이 "상대 경로 /api" 습관 하나로 개발할 때도, 나중에 AWS에 배포할 때도
CORS 문제를 아예 겪지 않게 됩니다. 그래서 처음부터 이렇게 시켜 둔 것입니다.
4.6 데이터베이스 붙이기 — 로컬에서 PostgreSQL
지금까지는 서버 메모리에 임시로 저장했습니다. 문제는, 서버를 끄면 그 데이터가 전부 사라진다는 점입니다. 3장 완료 기준의 마지막 항목, "새로고침해도 결과가 유지된다"를 만족하려면 데이터를 진짜 창고(DB)에 저장해야 합니다.
PostgreSQL 널리 쓰이는 무료 데이터베이스입니다. 표(테이블) 형태로 데이터를 저장하고, 정확하고 안정적이어서 실무에서 많이 씁니다. 뒤에서 AWS에 배포할 때 쓰는 클라우드 DB(RDS)도 이 PostgreSQL을 그대로 씁니다.
우리가 쓸 DB는 PostgreSQL입니다. 그런데 내 컴퓨터에 PostgreSQL을 직접 설치하는 대신, Docker로 띄웁니다.
Docker (지금은 맛보기) 프로그램을 "상자"에 담아 어디서든 똑같이 실행하게 해 주는 도구입니다. PostgreSQL을 내 컴퓨터에 복잡하게 설치하지 않고도, Docker로 명령 한 번에 깔끔하게 띄웠다가 지울 수 있습니다. Docker가 정확히 무엇이고 왜 쓰는지는 바로 다음 5장에서 제대로 배웁니다. 지금은 "DB를 간편하게 띄우는 도구"라는 정도로만 알고, 실행은 Claude Code에게 맡깁니다.
왜 설치 대신 Docker로 띄우나. 데이터베이스를 컴퓨터에 직접 설치하면 버전이 꼬이거나, 나중에 지우기가 번거롭습니다. Docker로 띄우면 명령 한 줄로 깨끗하게 시작하고, 필요 없어지면 상자째 지우면 그만이라 내 컴퓨터가 지저분해지지 않습니다. 그래서 로컬 개발용 DB는 Docker로 띄우는 경우가 많습니다.
Docker Desktop이 실행 중이어야 합니다 사전 조건에서 설치한 Docker Desktop이 지금 실행 중인지 확인하세요. (macOS는 위쪽 메뉴막대의 고래 아이콘, Windows는 작업 표시줄의 고래 아이콘이 떠 있으면 실행 중입니다.) 실행돼 있지 않으면 Docker로 DB를 띄우는 단계에서 오류가 납니다. Docker Desktop 앱을 먼저 실행해 두세요.
DB 붙이기 요청
Claude Code가 Docker로 PostgreSQL을 실행하고(예: docker run 명령으로
postgres 상자를 5432번 포트에 띄웁니다), 테이블을 만들고, 서버가 DB를
쓰도록 코드를 고쳐 줍니다. 중간에 여러 명령을 실행하며 승인을 요청할
텐데, 내용을 보며 승인하면 됩니다.
테이블(Table)
DB 안에서 정보를 담는 "표"입니다. 3장에서 그린 polls, options 데이터
모델이 실제로는 이 테이블 두 개가 됩니다. polls에는 설문 하나하나가,
options에는 그 설문의 선택지와 득표수가 한 줄씩 쌓입니다.
DB에 연결하려면 서버 코드가 "DB 주소, 사용자 이름, 비밀번호"를
알아야 합니다. 지금은 Claude Code가 우선 동작하게 채워 넣지만, 이렇게
코드에 들어간 접속 정보(특히 비밀번호)는 4.8에서 .env 파일로 옮겨
분리합니다. 지금은 일단 동작부터 확인하고 넘어갑니다.
4.7 전체 흐름 로컬에서 확인하기
이제 세 층(프론트 → API → DB)이 모두 준비됐습니다. 실제로 처음부터 끝까지 이어지는지 확인할 차례입니다.
여러 개가 동시에 돕니다 이 단계에서는 세 가지(프론트 개발 서버, API 서버, DB)가 동시에 켜져 있어야 합니다. Claude Code는 이를 위해 터미널을 여러 개 열거나 프로그램을 백그라운드로 돌릴 수 있습니다. 승인을 요청하면 그대로 승인하세요. 이때 claude가 실행 중인 터미널은 닫지 마세요. 무언가 멈추면 Claude Code에게 "지금 프론트, API, DB가 다 켜져 있는지 확인해 줘"라고 물으면 됩니다.
브라우저에서 알려 준 주소(보통 http://localhost:5173)에 접속해, 3장의
완료 기준을 하나씩 직접 체크해 보세요.
- □ 질문과 선택지를 입력해 설문을 만들 수 있는가
- □ 선택지를 누르면 득표수가 늘어나는가
- □ 결과가 막대그래프로 보이는가
- □ 페이지를 새로고침해도 투표 결과가 그대로 남아 있는가
마지막 항목이 이제 통과되어야 합니다. 새로고침해도 데이터가 유지된다면, 값이 화면이나 서버 메모리가 아니라 DB에 제대로 저장되고 있다는 확실한 증거입니다. 축하합니다. 프론트 + API + DB로 이루어진 진짜 웹 서비스가 내 컴퓨터에서 돌고 있습니다.
선택지를 누르면 아래처럼 득표수가 막대그래프와 퍼센트로 나타납니다.
새로고침했더니 결과가 사라진다면, 아직 DB가 아니라 메모리에 저장되고 있을 수 있습니다. Claude Code에게 "새로고침하면 투표 결과가 사라져. DB에 저장되고 있는 게 맞는지 확인하고 고쳐 줘"라고 요청하세요.
4.8 환경변수 분리 — 접속 정보를 코드에 넣지 않기
서비스가 동작하니, 넘어가기 전에 한 가지 중요한 습관을 짚습니다. DB에 접속하려면 주소, 사용자 이름, 비밀번호 같은 정보가 필요합니다. 이런 민감한 정보를 코드 안에 그대로 적어 두면 안 됩니다.
환경변수(Environment Variable) 프로그램 바깥에서 값을 주입하는 설정값입니다. DB 비밀번호처럼 환경마다 달라지거나 숨겨야 하는 값을, 코드에 직접 쓰지 않고 바깥에서 전달합니다.
시크릿(Secret) 비밀번호, 접속 키처럼 남에게 노출되면 안 되는 민감한 값들을 가리킵니다. 환경변수로 관리하는 대표적인 대상입니다.
왜 코드에 직접 쓰면 안 되나. 두 가지 이유가 있고, 둘 다 실무에서 실제로 사고로 이어지는 것들입니다.
- 보안: 코드를 GitHub에 올리면, 코드에 박아 둔 비밀번호까지 인터넷에 공개됩니다. 실제로 이렇게 유출된 접속 정보로 남의 DB가 털리는 사고가 흔합니다.
- 유연성: 내 컴퓨터의 DB와, 나중에 AWS의 DB는 접속 정보가 다릅니다. 코드에 박아 두면 환경이 바뀔 때마다 코드를 고쳐야 합니다. 환경변수로 빼 두면 코드는 그대로 두고 값만 바꾸면 됩니다.
그래서 이런 값들은 보통 .env라는 별도 파일에 모아 둡니다.
환경변수 이름을 왜 콕 집어 주나요
DB_HOST 같은 이름을 지정하지 않으면 AI가 DATABASE_URL 하나로
합치거나 POSTGRES_HOST처럼 다른 이름을 고를 수 있습니다. 그런데
이 다섯 개 이름은 7장(도커 컴포즈)과 2부(AWS 배포)에서 그대로
다시 씁니다. 지금 이름을 맞춰 두면, 나중에 배포할 때 서버 코드를
한 줄도 고치지 않아도 됩니다. 그래서 처음부터 못 박아 둡니다.
[용어] .gitignore
"GitHub에 올리지 않을 파일 목록"을 적어 두는 파일입니다. 여기에 .env를
넣어 두면, 비밀번호가 담긴 파일이 실수로 인터넷에 공개되는 걸 막습니다.
[확인] 분리가 끝나면 VS Code 파일 목록에 .env 파일이 보이고, 그
안에 DB_PASSWORD=... 같은 값이 들어 있습니다. 그리고 .gitignore
파일 안에 .env라는 줄이 있어야 합니다. 이 두 가지를 눈으로 확인하세요.
4.9 Git으로 저장하고 GitHub에 올리기
마지막으로, 지금까지 만든 것을 안전하게 저장하고 GitHub에 올립니다. 2부와 3부의 자동 배포가 이 GitHub 저장소를 기반으로 이루어지므로, 여기서 꼭 올려 둬야 합니다. 1장에서 Git 설치와 GitHub 계정을 준비해 둔 걸 이제 씁니다.
커밋(Commit) 지금까지의 변경 사항을 하나의 "저장 지점"으로 기록하는 것입니다. 게임의 세이브 포인트처럼, 나중에 이 시점으로 되돌아올 수 있습니다.
푸시(Push) 내 컴퓨터에 기록한 커밋들을 GitHub(인터넷 저장소)로 올려 보내는 것입니다.
리포지토리(Repository, 줄여서 repo) GitHub에서 하나의 프로젝트 코드가 통째로 저장되는 공간입니다. "vote-app 저장소"처럼 프로젝트마다 하나씩 만듭니다.
실제로 어디에 쓰이나. 이 커밋·푸시·저장소는 개발자라면 매일 쓰는 기본 도구입니다.
- 백업: 내 컴퓨터가 고장 나도 코드가 GitHub에 안전하게 남아 있습니다.
- 되돌리기: 무언가 잘못 고쳤을 때, 예전 커밋 지점으로 되돌릴 수 있습니다.
- 협업·자동 배포: 팀원과 코드를 공유하고, "GitHub에 코드가 올라오면 자동으로 서버에 배포"하게 만들 수 있습니다(3부에서 직접 합니다).
이 과정도 Claude Code에게 맡길 수 있습니다.
왜 프라이빗(비공개)으로 하나요?
퍼블릭(공개) 저장소는 전 세계 누구나 코드를 볼 수 있습니다. 우리
저장소에는 앞으로 배포 설정 등 우리 서비스의 속사정이 쌓이므로, 실습에서는
비공개로 두는 것이 안전합니다. (비공개여도 GitHub Actions 등 이 책의
모든 실습은 그대로 됩니다.)
[주의] GitHub 연결(인증)
처음 올릴 때는 GitHub 로그인/인증 절차가 필요할 수 있습니다. Claude
Code가 안내하는 대로 따라가면 되고, 막히면 오류 메시지를 그대로 붙여넣어
도움을 받으세요. gh라는 GitHub 공식 도구를 쓰면 편한데, 없으면 Claude
Code가 설치 방법을 알려 줍니다.
[확인] 올리고 나면 브라우저에서 github.com/내아이디/vote-app에
접속해, 코드가 실제로 올라왔는지 확인하세요. frontend, backend
폴더가 보여야 합니다. 이때 .env 파일은 목록에 없어야 정상입니다
(4.8에서 제외했으니까요). 만약 .env가 올라가 있다면, Claude Code에게
".env가 저장소에 올라가 있어. .gitignore에서 제외하고 저장소에서도
지운 뒤 다시 올려 줘"라고 요청하세요.
[확인]
이번 장이 제대로 끝났는지 눈으로 확인합니다.
- 브라우저에서
http://localhost:5173에 접속하면 투표 화면이 뜬다. - 설문을 만들고, 선택지를 눌러 투표하면 득표수가 막대그래프로 늘어난다.
- 페이지를 새로고침해도 득표수가 그대로 남아 있다.
github.com/내아이디/vote-app에 코드가 올라와 있고,.env는 그 목록에 없다.
여기까지 보였다면, 내 컴퓨터에서 도는 진짜 웹 서비스가 완성된 것입니다.
막히면
이 장에서 자주 나는 오류와 대처법입니다.
-
투표 화면(5173)에서 투표하면 오류가 나거나 아무 반응이 없다. API 서버(3000번)가 안 켜져 있거나, 개발 프록시가 빠졌을 수 있습니다. Claude Code에게 "API 서버가 켜져 있는지, vite 개발 프록시가 /api를 3000번으로 넘기게 돼 있는지 확인해 줘"라고 요청하세요. (4.5 참고.)
-
브라우저 개발자 도구에
CORS오류가 보인다. 화면이 API를 절대 주소로 부르고 있을 가능성이 큽니다. Claude Code에게 "API 호출을 상대 경로 /api로 바꾸고, vite 프록시로 3000번에 넘기게 해 줘"라고 요청하세요. (4.5의 방식으로 고치면 CORS가 사라집니다.) -
DB 붙이는 단계에서 Docker 관련 오류가 난다. Docker Desktop이 실행 중이 아닐 때가 많습니다. Docker Desktop 앱을 먼저 실행한 뒤(고래 아이콘 확인), Claude Code에게 다시 시도해 달라고 하세요. 5432번 포트가 이미 쓰이고 있다는 오류라면, 예전에 띄운 DB가 남아 있는 것이니 "기존 postgres 컨테이너를 정리하고 다시 띄워 줘"라고 요청합니다.
-
새로고침하면 투표 결과가 사라진다. 아직 데이터가 서버 메모리에 저장되고 있는 것입니다. Claude Code에게 "새로고침하면 결과가 사라져. DB에 저장하고 DB에서 읽어 오는 게 맞는지 확인하고 고쳐 줘"라고 요청하세요. (4.6 참고.)
-
GitHub에 올릴 때 인증(로그인)에서 막힌다. 터미널에 나온 안내나 오류 메시지를 그대로 Claude Code에게 붙여넣으세요.
gh auth login으로 GitHub에 로그인하도록 안내해 줍니다. -
.env파일이 GitHub에 올라가 버렸다. Claude Code에게 ".env를 저장소에서 지우고.gitignore에 넣은 뒤 다시 올려 줘"라고 요청하세요. 비밀번호가 노출됐다면, 그 DB 비밀번호는 새로 바꾸는 게 안전합니다.
[체크리스트]
아래가 모두 됐는지 확인해 보세요. 하나라도 안 됐다면 해당 절로 돌아가 다시 진행합니다.
- □ 프론트엔드 / 백엔드 / 데이터베이스 3층 구조를 설명할 수 있다 (4.1)
- □
vote-app안에frontend,backend폴더로 뼈대가 만들어졌다 (4.2) - □ 브라우저(
localhost:5173)에서 투표 화면이 뜬다 (4.3) - □ API 서버(3000번)의 세 엔드포인트가 동작하는 걸 확인했다 (4.4)
- □ 화면이 API를 상대 경로 /api로 부르고, 개발 프록시로 이어진다 (4.5)
- □ Docker로 PostgreSQL을 띄우고, 서버가 DB에 저장하도록 연결했다 (4.6)
- □ 투표 후 새로고침해도 결과가 유지된다 (DB 저장 확인) (4.7)
- □ 민감한 정보를
.env로 분리하고.gitignore에 넣었다 (4.8) - □ 코드를 GitHub 비공개 저장소에 올렸고,
.env는 올라가지 않았다 (4.9)
이제 "내 컴퓨터에서 도는 서비스"가 생겼습니다. 하지만 이걸 다른 사람에게 보여 주려면 내 컴퓨터를 계속 켜 둘 수도 없고, "내 컴퓨터에선 되는데 남의 컴퓨터에선 안 되는" 문제도 있습니다. 이 문제를 푸는 것이 다음 여정, Docker와 클라우드 배포입니다.