Post

[Dr.Yum] Day 1 — 개발 환경 구축과 첫 Hello World

[Dr.Yum] Day 1 — 개발 환경 구축과 첫 Hello World

🚀 Day 1: 모든 사이드 프로젝트는 환경 설정에서 시작된다

“야, 홍대 근처 맛집 어디가 좋아?”

이 질문을 받을 때마다
네이버 지도를 뒤적이거나, 카카오톡 나에게 보내기를 열거나,
결국은 “어… 잠깐만!”을 외치게 된다.

내 취향이 담긴 맛집 리스트를
지도 위에 예쁘게 올려서
링크 하나로 “여기 가” 하고 던질 수 있으면 좋겠다.

그래서 시작했다.
3주(21일) 만에 만드는 나만의 맛집 지도 서비스, Dr.Yum(쩝쩝박사).

오늘은 그 대망의 Day 1,
본격적인 기능 개발에 앞서 개발 환경 구축을 진행했다.


🛠️ 기술 스택 (MVP 기준)

빠르고 효율적인 MVP 개발을 위해
익숙하면서도 생산성이 높은 조합을 선택했다.

  • Backend
    • NestJS (Node.js)
    • TypeORM
  • Database
    • PostgreSQL 15
    • Docker / Docker Compose
  • Frontend
    • React (Vite)
    • TypeScript
    • Zustand
  • Infra
    • Docker Compose

오늘의 목표는 “잘 만들기”가 아니라 “프론트와 백엔드가 서로 말을 하게 만들기”였다.


💣 오늘의 삽질 로그 (Troubleshooting)

개발을 시작하기 전, 솔직히 이렇게 생각했다.

“도커로 DB 하나 띄우고,
백엔드에서 CORS만 대충 열어주고,
프론트에서 요청 한 번 보내면
초기 세팅은 끝나는 거 아닌가?

NestJS도 예전에 써봤고, React + Axios로 API를 붙이는 작업도 익숙했다.

그래서 오늘의 목표도 단순했다.

  • Docker로 PostgreSQL 띄우기
  • NestJS에서 DB 연결
  • CORS 설정
  • 프론트에서 API 호출

이 정도면 “환경 세팅 완료” 도장 하나 찍을 수 있을 거라 생각했다.


하지만 현실은 달랐다.

  • 컨테이너는 분명 잘 떠 있는데 연결이 안 되고
  • 설정은 맞는 것 같은데 에러는 계속 나오고
  • 문제는 코드가 아니라 환경 어딘가에 숨어 있었다

결국 오늘의 삽질은 “Docker를 띄운다”와
“Docker 기반 환경을 이해한다”는 전혀 다른 일이라는 걸 깨닫는 과정이었다.


사실 이번 문제를 겪으면서 한 가지 더 분명해진 사실이 있다.

나는 Docker를 ‘제대로’ 배운 적이 없었다.

그동안 Docker를 사용하긴 했지만,
공식 문서나 개념을 차근차근 이해했다기보다는
“이렇게 하면 되네?”라는 감각에 의존해 이미지를 만들고, 컨테이너를 띄우고, 배포를 해왔다.

그러다 보니

  • 컨테이너와 로컬 환경의 경계
  • Volume이 실제로 어떤 역할을 하는지
  • 포트와 네트워크가 어떻게 연결되는지

같은 것들을 명확하게 이해하지 못한 상태로 프로젝트를 진행하고 있었다.

이번 삽질은 단순히 설정 하나를 잘못한 문제가 아니라,

“돌아가기만 하면 된 거지”

라는 태도로 개발 환경을 너무 대충 다뤄왔던 결과라는 생각이 들었다.


아래는
그 과정에서 겪은 대표적인 삽질들이다.


1️⃣ 좀비처럼 되살아나는 role does not exist 에러

Docker Compose로 PostgreSQL을 띄우고 NestJS에서 연결하려는데 계속 이런 에러가 떴다.

1
error: role "yum_admin" does not exist

docker-compose.yml에는 분명 이렇게 써 있었다.

1
POSTGRES_USER: yum_admin

그런데 왜 없다고 하지…?

🕵️ 원인

Docker의 Volume(볼륨) 이 문제였다.

처음 컨테이너를 잘못된 설정으로 실행하면서
초기 DB 데이터가 로컬 폴더(pgdata)에 생성되었고,
이후 설정을 아무리 바꿔도 Docker는:

“이미 데이터 있네? 그럼 이거 쓸게~”

하고 기존 데이터를 계속 재사용하고 있었다.

✅ 해결

과감하게 볼륨 초기화 후 재시작.

1
2
3
4
5
6
7
8
# 1. 컨테이너 종료
docker-compose down

# 2. 로컬 볼륨 폴더 삭제
rm -rf ./pgdata

# 3. 다시 실행 (Clean Start!)
docker-compose up -d

2️⃣ 범인은 내 안에 있었다 (PostgreSQL 포트 충돌)

볼륨을 지웠는데도 에러가 완전히 사라지지 않았다.

알고 보니
내 맥북에는 예전에 설치해둔 로컬 PostgreSQL
이미 5432 포트를 점령하고 있었다.

결과적으로 NestJS는
Docker DB가 아니라
로컬의 정체불명 PostgreSQL에 계속 연결을 시도하고 있었던 것.

✅ 해결

Docker의 포트를 5433으로 이사시켰다.

1
2
3
# docker-compose.yml
ports:
  - "5433:5432"  # 로컬 5433 -> 컨테이너 5432

3️⃣ Git 안에 Git이? (Nested Git 이슈)

프로젝트 구조를 잡으면서
Dr.Yum 폴더 안에 프론트엔드(dr-yum-fe)를 넣었다.

백엔드와 프론트를 한 저장소에서 관리하는
모노레포(Monorepo) 구조로 가고 싶었기 때문이다.

하지만 Git에 커밋하려는 순간 에러가 발생했다.

알고 보니 Vite로 프론트엔드 프로젝트를 생성하면
해당 폴더 안에 자동으로 .git 디렉토리가 만들어진다.

부모 저장소 입장에서는 이 상태가 이런 느낌이다.

“이 폴더는 이미 다른 Git이 관리 중인데? 나는 여기까지는 못 들어가.”

🤔 왜 이런 문제가 생겼을까?

솔직히 말하면, 모노레포 구조를 실제로 써보는 게 처음이었다.

  • “한 레포 안에 프론트/백엔드 같이 두면 되겠지?”
  • “Git이 알아서 잘 해주지 않을까?”

라는 생각으로 시작했고, 하위 프로젝트에도 Git이 생긴다는 사실을 몰랐던 것이 원인이었다.


📦 잠깐, 모노레포(Monorepo)란?

모노레포는 여러 개의 프로젝트(예: 프론트엔드, 백엔드)를 하나의 Git 저장소에서 함께 관리하는 방식이다.

이번 프로젝트 구조는 대략 이런 형태다.

1
2
3
Dr.Yum/
 ├── dr-yum-be/   # NestJS 백엔드
 └── dr-yum-fe/   # React 프론트엔드

이 구조의 핵심은 👉 Git 저장소는 하나라는 점이다.

즉,

  • 루트에만 .git이 있어야 하고
  • 하위 폴더들은 Git의 관리 대상일 뿐, 독립된 저장소가 아니다

✅ 해결

하위 프론트엔드 폴더에 생성된 .git을 제거하고, 부모 저장소에서 통합 관리하도록 수정했다.

1
2
3
4
5
# 프론트엔드 폴더 내 .git 삭제
rm -rf dr-yum-fe/.git

# 이미 Git이 추적하던 캐시 정리
git rm --cached dr-yum-fe

이후에는 프론트엔드와 백엔드 모두 하나의 커밋 히스토리로 정상 관리할 수 있었다.


이번 삽질 덕분에 “모노레포 구조에서는 Git의 기준점이 어디인지”를 몸으로 확실히 이해하게 됐다.


🎉 결론: Hello World!

수많은 고비를 넘기고
드디어 프론트엔드와 백엔드가 만났다.

  • NestJS에서 CORS 허용
  • React에서 Axios로 GET / 요청
  • 서버 응답: "Hello World!"

화면에 Hello World가 뜨는 순간, 오늘 하루의 피로가 싹 가셨다.

역시 개발자는 푸른 글씨를 보면 행복해진다.


🧠 오늘의 교훈

  • Docker는 “띄우는 것”보다 어떤 환경을 만들고 있는지 이해하는 게 먼저다.

  • 컨테이너가 정상적으로 실행된다는 사실이 곧 애플리케이션이 올바르게 연결된다는 의미는 아니다.

  • 생성형 AI는 빠른 힌트를 주지만, 개념을 대신 이해해주지는 않는다.

  • 특히 모노레포와 Docker 환경에서는 경로, 네트워크, 기준점을 정확히 인식하지 않으면 문제가 코드가 아닌 곳에서 발생한다.

오늘은 기능을 거의 만들지 못했지만, 대신 앞으로의 개발에서 같은 삽질을 반복하지 않기 위한 기본기를 점검한 하루였다.


👉 Next Step (Day 2)

환경 설정은 끝났다. 내일부터는 진짜 기능을 만든다.

  • 카카오 소셜 로그인 연동
  • JWT 발급
  • 유저 정보 저장

이제부터가 진짜 시작이다.

This post is licensed under CC BY 4.0 by the author.