본문으로 건너뛰기
유재진kyoroho
← 목록으로
진행 중

교회 수련회 안내·신청·운영 웹앱

수련회 안내·예약·설문은 공개 사이트에서, 일정·참가자·조 편성·예약 확정은 관리자에서 처리하는 교회용 웹앱

  • 공개 사이트와 관리자, 교사용 토큰 링크, 설문을 Next.js 앱 하나에 담았습니다.
  • 예약을 확정하면 참가자가 자동 생성되고, 상태 변경이 활동 로그와 상태 이력에 남도록 했습니다.
  • Lightsail·Docker에서 Vercel·Neon·Blob으로 옮기며 업로드와 배포 구성을 정리했습니다.

문제

교회 수련회 하나를 치르려면 안내, 신청, 참가자 명단, 조 편성, 프로그램 일정, 사후 설문이 필요하다. 신청자는 자기 예약을 확인해야 하고, 현장 교사는 자기 조 명단을 봐야 한다. 지인의 부탁으로 이 흐름을 한 곳에서 처리하는 웹앱을 맡았다.

운영 중에는 호스팅 문제가 드러났다. Lightsail의 standalone 서버는 기동 시점의 public/만 서빙해서 나중에 올린 이미지가 404가 났다. 저사양 서버에서 next build를 돌리면 시스템이 다운됐다.

해결

Next.js App Router 앱 하나에 공개 사이트, 관리자, 설문, 교사 페이지를 모두 넣었다. 데이터는 Prisma와 PostgreSQL로 다룬다. 관리자 경로는 proxy.ts가 세션을 확인하고, API는 핸들러마다 세션을 다시 검사한다.

  • 공개 사이트: 소개, 갤러리와 좋아요, 아카이브, 공지를 제공한다. 신청자는 일정 상세에서 예약하고, 이름과 연락처로 예약을 조회한다.
  • 예약 확정: 관리자가 예약을 확정하면 참가자가 자동 생성된다. 변경 내용은 활동 로그와 상태 이력에 남는다.
  • 일정 상세: 정보, 프로그램, 참가자, 조, 후기의 다섯 탭으로 나눴다.
  • 교사 링크: 무작위 토큰에 만료일을 붙였다. 교사는 로그인 없이 일정과 프로그램, 전체 또는 지정 조의 참가자를 본다. 만료된 링크는 410을 돌려준다.
  • 설문: 단답·서술·단일선택·중복선택·날짜의 5개 유형을 지원한다. 겨울과 여름 시즌 테마를 분리했다. 필수 항목을 빠뜨리면 해당 문항으로 스크롤하고 포커스를 옮긴다. 응답은 CSV로 내려받는다.
  • 호스팅: 처음에는 Docker Compose로 Lightsail에 배포했다. 업로드 이미지는 볼륨과 서빙 라우트로 유지했고, 이미지 빌드는 GitHub Actions로 옮겼다. 이후 Vercel로 이관하며 다음을 바꿨다.
    • 업로드를 Vercel Blob으로 바꾸고 서빙 라우트를 제거했다.
    • 함수 리전을 Neon DB와 같은 sin1로 고정했다.
    • 후원 관리 기능(페이지·API·대시보드 지표)을 제거했다.
    • Lightsail 워크플로는 수동 실행 전용으로 동결했다.
결정 기록
정한 것대신 버린 것이유
이미지 빌드 위치 (Lightsail 시절)GitHub Actions에서 이미지 빌드 후 GHCR push, 서버는 pull만Lightsail 서버에서 직접 next build저사양 서버에서 next build를 돌리면 시스템이 다운됐다. 빌드를 서버 밖으로 옮겨 서버는 완성된 이미지만 받게 했다.
운영 DB에 설문 추가여름 설문 전용 시드 스크립트전체 시드 재실행전체 시드는 관리자 비밀번호와 사이트 설정을 초기값으로 덮어쓴다. 운영 데이터를 건드리지 않고 설문만 생성·갱신하도록 분리했다.
설문 응답 CSV 다운로드fetch(인증 쿠키 포함) + Blob URL 다운로드window.open으로 CSV URL 열기CSV는 관리자 인증이 필요한 API에서 나온다. 인증 쿠키를 실어 요청하고 실패하면 토스트로 알리도록 바꿨다. 한글 파일명은 RFC 5987로 인코딩했다.

결과

25개
페이지 (공개 9 · 관리자 14 · 설문 1 · 교사 1)
39개
API Route Handler
3곳
CSV 내보내기 (예약 · 참가자 · 설문)
  • Vercel에서 운영 중이고 자체 도메인을 연결했다. main에 푸시하면 자동 배포된다.
  • 호스팅을 이관할 때 기존 DB의 데이터를 Neon으로 옮겨 검증했다.
  • 겨울캠프와 여름수련회 설문을 같은 설문 모델 위에 시즌 테마만 달리해 구성했다.
  • 남은 과제는 점검 문서에 기록했다. 예약 정원 검사, 확정 과정의 트랜잭션 처리, 예약 취소 시 참가자 정리, 자동 테스트와 마이그레이션 이력이 아직 없다.

이 프로젝트가 궁금하시면 편하게 물어보세요.

연락하기