개발 기록 2026-10-25 docs/devlog/2026-10-25-3-Render-첫-배포와-외부-확인.md GitHub에서 보기

Render 첫 배포와 외부 접속 확인 (WBS 5.4)

목표

PR #3 으로 main 에 들어간 배포 준비 (release, Dockerfile, 부팅 시드, render.yaml) 를 실제로 Render Free + Neon Free 에 올리고, 외부에서 데모가 열리는지 확인한다. 로컬에서 확인 필요로 남긴 다섯 가지를 실제 환경에서 푼다.

한 일

  • 변경 확인: 작업 트리는 .claude/ 만 추적 밖이고, origin/main 은 ce33571 (PR #3 병합). 배포할 코드가 모두 main 에 있다.
  • 사용자와 나눠서 진행했다. 비밀값이 오가는 단계는 사용자가 하고, 나머지는 내장 브라우저로 내가 했다.
    • 사용자: Neon, Render 로그인. Blueprint 생성 화면의 sync: false 값 세 개 (DATABASE_URL, SECRET_KEY_BASE, TICKMARK_DEMO_PASSWORD) 입력. 배포된 앱에 kim.writer@example.com 으로 로그인.
    • 메인: Neon 프로젝트 화면 확인, Blueprint 로 서비스 tickmark (Free, Singapore, Docker, main) 생성 진행, 빌드와 배포 로그 읽기, curl 로 외부 HTTP 확인, 로그인 뒤 S1-S6 와 /docs 화면 읽기.
  • 배포 가이드 5.2절 (첫 배포 결과), 6장 제약 표, WBS 5.4 와 M5 완료, TASKS 갱신.

결정과 트레이드오프

  • 비밀값은 내가 입력하지 않는다. DB 주소, secret, 데모 비밀번호를 내가 화면에 치면 대화 기록에 남는다. 가이드 3장 규칙 ("값은 Render 대시보드에만") 을 지키려고 그 칸만 사용자가 채웠다. 대가는 왕복이 몇 번 늘어난 것이다.
  • 데모 데이터는 읽기만 했다. 실행 시작, 결론 제출, 승인, AI 요청을 누르면 audit_events 에 영구히 남는다 (append-only). 면접에서 보여 줄 첫 상태 (이벤트 #1-#6, 검토 큐 52, 결론 0) 를 지키려고 페이지를 여는 것까지만 했다. 그래서 쓰기 경로 (결론, 승인, AI 트리아지) 는 배포 환경에서 확인하지 않았다. 같은 코드가 로컬 테스트 588개와 10/20 브라우저 확인을 통과한 것으로 갈음한다.
  • 값 확인을 배포 결과로 대신했다. 가려진 값을 미리 볼 방법이 없어 (아래 막힌 점) 배포 뒤 결과로 세 값을 확인했다. 틀렸으면 배포가 실패하거나 로그인이 안 됐을 것이고, 다시 넣고 재배포하면 되는 일이라 위험이 작다고 봤다.
  • 문서에 URL 은 남기고 비밀번호는 남기지 않는다. 데모 주소는 저장소를 공개하면 README 와 위키에서 쓸모가 있다. 비밀번호는 지원서에만 적는다. 가이드 4장 7단계 문구를 이렇게 분명히 했다. 대가는 누구나 주소로 들어와 잠든 서버를 깨울 수 있다는 점이다. 새로 가입한 계정은 메일이 없어 로그인할 수 없다.

막힌 점과 해결

  • Blueprint 값이 가려져 확인할 수 없음. Render 는 sync: false 칸을 점 12개로 보여 주고, 칸에 포커스를 줘도 값이 나오지 않는다. 사용자가 넣은 값이 맞는지 배포 전에 볼 수 없었다. 배포 결과로 확인했다: 마이그레이션 성공은 DATABASE_URL 과 TLS, 세션 쿠키가 붙은 200 은 SECRET_KEY_BASE 길이, 사용자 로그인은 데모 비밀번호.
  • 로그 화면이 "Build not found". 서비스의 로그와 이벤트 화면에서 빌드 로그가 보이지 않았다. 이벤트 목록에서 해당 배포 (/deploys/dep-...) 화면을 직접 여니 빌드와 배포 로그가 모두 나왔다.
  • 브라우저 확인 중 클립보드 경고. 내장 브라우저가 "합성 입력 중 페이지가 OS 클립보드에 썼다" 고 한 번 알렸다. 원인은 확인 필요. 이후 동작과 결과에는 영향이 없었다.

실행 결과

시각은 KST. 세부 표는 배포 가이드 5.2절.

  • 빌드: 09:35 시작, Docker 이미지 (amd64) 약 2분 30초. deps.compile 51.5초, 앱 111개 파일. 경고는 mix.exs xref exclude 사용 중단 안내 1건.
  • 부팅: 마이그레이션 10개 약 1.5초 (Neon, TLS). Running TickmarkWeb.Endpoint with Bandit 1.13.1 at :::10000 (http). 14초 뒤 demo seed: created 누리정밀 주식회사 FY2025, GL import succeeded, test run completed. 09:38 Deploy succeeded, Live.
  • 외부 HTTP: /, /users/log-in, /users/register, /docs 200, /engagements 302, 없는 경로 404, http 301. HSTS, CSP, nosniff, secure HttpOnly 쿠키. 로그인 화면에 #mail-off-notice.
  • 화면 (작성자로 로그인, 읽기만): S1 누리정밀 (검토 큐 52), S2 전표 8,341건, 라인 19,804건, S4 룰 8/8, 적중 전표 265건 (검토 큐 52, 경미 213), S5 JE2025-008261 점수 55, S6 이벤트 6건 (생성, 멤버 추가, 적재 시작과 완료, 실행 시작과 완료), /docs. LiveView 연결, 콘솔 오류 0.
  • 숫자는 로컬 시드와 같다 (라인 19,804, 검토 큐 52). 시드가 결정적이라 환경이 바뀌어도 같은 데이터가 나온다.
  • 확인 필요: Linux 메모리 (무료 플랜에 지표 없음. 메모리 초과 이벤트는 없었다). 검토자 (park.reviewer@example.com) 로그인은 하지 않았다.
  • 보안 권고: mix deps.get 이 plug_crypto 2.2.0 의 EEF-CVE-2026-105963 (MEDIUM) 을 알렸다. 2.2.1 로 올리는 일을 TASKS 에 넣었다.

Elixir 학습 포인트

  • Docker 안의 release 는 Mix 없이 돈다. 빌드 단계 이미지에서 mix release 로 만든 _build/prod/rel/tickmark 만 실행 단계 이미지로 복사한다. 그래서 컨테이너 안에는 mix ecto.migrate 가 없고, bin/migrate 가 bin/tickmark eval Tickmark.Release.migrate 로 마이그레이션을 돈다. eval 은 앱을 시작하지 않고 코드만 올리므로 Ecto.Migrator.with_repo/2 가 Repo 하나만 잠깐 띄워 마이그레이션하고 내린다. 그 뒤 bin/server 가 앱 전체를 시작한다.
  • :: 바인딩. Endpoint 의 ip: {0, 0, 0, 0, 0, 0, 0, 0} 은 IPv6 의 모든 주소 (::) 다. Linux 기본값 (net.ipv6.bindv6only=0) 에서는 이 소켓이 IPv4 연결도 받는다. Render 가 포트 10000 을 찾고 요청이 들어온 것으로 이 바인딩이 Render 에서 문제없음을 확인했다. Render 내부 라우터가 IPv4 와 IPv6 중 무엇으로 붙는지는 확인 필요.
  • secret 길이는 첫 요청에서 드러난다. Plug.Session.COOKIE 는 세션 쿠키를 서명할 때 secret_key_base 가 64바이트보다 짧으면 예외를 낸다. 부팅만으로는 모르고 세션을 쓰는 첫 요청에서 500 이 난다. 그래서 쿠키가 붙은 /users/log-in 200 이 길이 확인이 된다.
  • 부팅 시드 Task 의 순서. 감사 로그의 첫 이벤트 (09:38:47) 는 Endpoint 시작 (09:38:44) 3초 뒤다. 자식 목록에서 Task 가 Endpoint 뒤에 있어서, 서버가 요청을 받기 시작한 다음에 시드가 돈다는 것을 실제 시각으로 볼 수 있다.

다음 할 일

  • plug_crypto 2.2.1 로 갱신, mix precommit, PR, 재배포 (메인. mix.lock 은 메인 소유).
  • 사용자: 지원서에 URL, 데모 계정, 첫 접속이 1분쯤 걸린다는 안내 (WBS 6.4).
  • 6.2 데모 GIF, 6.3 공개 전 점검과 저장소 공개 전환.
  • 남은 일: 라운드 4b 나머지, S3 브라우저 확인, FN/IF 교차 링크.

관련 커밋

  • ce33571 PR #3 병합 (배포한 커밋)
  • 이 devlog 와 문서 갱신은 뒤이은 docs 커밋