Django to React + Express

SW Development
Movie Page: Django to React + Express
Posted on Oct. 5, 2026, 3:32 p.m. by SANGJIN
random_image

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

  • 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: