Django to React + Express
SW DevelopmentMovie Page: Django to React + Express
Migrated a Django-rendered movie review page (/my_flix/) — previously just an empty
template with all logic (Firestore reads/writes, KOBIS box-office lookups, card
rendering) running in inline browser jQuery — to a React + TypeScript frontend and a
Node.js + Express API, while keeping the rest of the Django site untouched.
The existing page had a plaintext "secret key" and a KOBIS API key exposed directly in
client-side JS (committed to git), and review text was inserted via string HTML
concatenation into innerHTML.
| Layer | Before | After |
|---|---|---|
| Review list / box office | Browser reads Firestore/KOBIS directly | Express API reads them server-side |
| Review text rendering | String HTML → innerHTML |
JSX text nodes |
| Review submission | Client-side secret-key compare + direct Firestore write | Kept unchanged, by explicit scope decision |
Key design decisions
- Investigated real Firestore data before writing normalization logic — found 1 of 23 documents had zero fields at all (not just a missing date), and excluded it from the response instead of guessing a display for it.
- Kept the legacy write path as-is — scoped this round to the read path only; server-side write auth was explicitly left out.
- Staged rollout with a configurable Vite base path — the same build was deployed
first to
/movie-preview/on the real production server, memory-checked, then cut over to/my_flix/only after that passed. The old Django route was never removed, so rollback is a single nginx location change. - Legacy Firestore field names preserved internally (
image/title/comment/star/created_at) so the old template and any rollback path can still read the same documents.
Tech: React 19, TypeScript, Vite, Node.js, Express, Firestore (Admin SDK), KOBIS Open API, Docker, nginx
===
Django가 빈 템플릿만 내려주고 나머지 로직(Firestore 읽기/쓰기, KOBIS 박스오피스 조회,
카드 렌더링)은 전부 브라우저 jQuery가 처리하던 영화 리뷰 페이지(/my_flix/)를
React + TypeScript 프론트엔드와 Node.js + Express API로 옮겼다. 사이트의 나머지
부분(Django)은 그대로 두었다.
기존 페이지는 평문 "비밀키"와 KOBIS API 키가 클라이언트 JS에 그대로 노출되어 있었고
(git에도 커밋), 리뷰 텍스트는 문자열 HTML을 innerHTML에 직접 삽입하고 있었다.
| 구분 | 이전 | 이후 |
|---|---|---|
| 리뷰 목록 / 박스오피스 | 브라우저가 Firestore/KOBIS 직접 조회 | Express API가 서버에서 조회 |
| 리뷰 텍스트 렌더링 | 문자열 HTML → innerHTML |
JSX 텍스트 노드 |
| 리뷰 등록 | 클라이언트 비밀키 비교 + Firestore 직접 쓰기 | 그대로 유지(의도적 범위 결정) |
핵심 설계 결정
- 정규화 로직을 짜기 전에 실제 Firestore 데이터부터 조사 — 23개 문서 중 1개는 날짜만 없는 게 아니라 필드가 아예 없는 빈 문서였고, 임의로 표시하지 않고 응답에서 제외했다.
- 쓰기 경로는 그대로 유지 — 이번 범위를 읽기로만 한정했고, 서버 측 쓰기 인증은 의도적으로 넣지 않았다.
- Vite base path를 환경변수로 받아 단계적 배포 — 같은 빌드를 먼저
/movie-preview/로 실 서버에 올려 메모리를 확인한 뒤에만/my_flix/로 전환했다. 기존 Django 라우트를 지우지 않아서, nginx 설정 한 줄만 되돌리면 즉시 롤백된다. - Firestore 필드명은 내부적으로 레거시 그대로 유지(
image/title/comment/star/created_at) — 기존 템플릿이나 롤백 경로가 같은 문서를 계속 읽을 수 있게.
사용 기술: React 19, TypeScript, Vite, Node.js, Express, Firestore (Admin SDK), KOBIS Open API, Docker, nginx
Links
-
Github: https://github.com/SangjinKO/movie-react-express
-
Velog: https://velog.io/@kosang234/Django-%ED%85%9C%ED%94%8C%EB%A6%BF-%ED%8E%98%EC%9D%B4%EC%A7%80%EB%A5%BC-React-Express%EB%A1%9C-%EB%8B%A8%EA%B3%84%EC%A0%81-%EC%A0%84%ED%99%98%ED%95%98%EB%A9%B4%EC%84%9C-%EA%B9%A8%EB%8B%AC%EC%9D%80-%EA%B2%83%EB%93%A4
Leave a Comment: