← 목록으로
교회 수련회 안내·신청·운영 웹앱Next.js · React · TypeScript
진행 중
교회 수련회 안내·신청·운영 웹앱
수련회 안내·예약·설문은 공개 사이트에서, 일정·참가자·조 편성·예약 확정은 관리자에서 처리하는 교회용 웹앱
- 공개 사이트와 관리자, 교사용 토큰 링크, 설문을 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으로 옮겨 검증했다.
- 겨울캠프와 여름수련회 설문을 같은 설문 모델 위에 시즌 테마만 달리해 구성했다.
- 남은 과제는 점검 문서에 기록했다. 예약 정원 검사, 확정 과정의 트랜잭션 처리, 예약 취소 시 참가자 정리, 자동 테스트와 마이그레이션 이력이 아직 없다.
이 프로젝트가 궁금하시면 편하게 물어보세요.
연락하기