회사 내부 일정 관리 웹 애플리케이션입니다. 부서/직급별 일정 공유, 알림 기능을 갖춘 캘린더 시스템입니다.
- 캘린더: 월간/주간/일간 뷰 전환
- 일정 공유 범위: 회사 전체, 부서별, 개인, 특정 직급 이상
- 알림: 일정 시작 전 인앱 알림 + 이메일 알림
- 관리자 패널: 부서, 직급, 사용자 관리
- 다크모드: 라이트/다크 테마 지원
- 반응형: 모바일/태블릿/데스크탑 대응
- Next.js 16 (App Router) + TypeScript
- Tailwind CSS + shadcn/ui
- MySQL + Prisma ORM
- NextAuth.js v5 (Credentials, JWT)
- Nodemailer (SMTP 이메일)
- SWR, react-hook-form, Zod, date-fns
npm install.env 파일을 프로젝트 루트에 생성합니다.
# Database
DATABASE_URL="mysql://schedule:schedule@localhost:3306/schedule"
# NextAuth
NEXTAUTH_URL="https://your-domain.com"
NEXTAUTH_SECRET="your-secret-key"
# SMTP (Nodemailer)
SMTP_HOST="smtp.example.com"
SMTP_PORT=587
SMTP_USER="[email protected]"
SMTP_PASSWORD="your-smtp-password"
SMTP_FROM="일정관리 <[email protected]>"
# Cron secret
CRON_SECRET="your-cron-secret"# MySQL에서 DB 및 사용자 생성
mysql -u root -p -e "
CREATE DATABASE schedule;
CREATE USER 'schedule'@'localhost' IDENTIFIED BY 'schedule';
GRANT ALL PRIVILEGES ON *.* TO 'schedule'@'localhost';
FLUSH PRIVILEGES;
"
# 마이그레이션 실행
npx prisma migrate dev
# 초기 데이터 (직급 11단계, 부서 6개, 관리자 계정)
npx tsx prisma/seed.ts# 빌드
npm run build
# 실행 (개발)
npm run dev
# 실행 (프로덕션, PM2)
pm2 start ecosystem.config.jsecosystem.config.js 파일을 프로젝트 루트에 생성합니다. (.gitignore에 포함되어 push되지 않음)
module.exports = {
apps: [
{
name: "schedule",
script: "node_modules/.bin/next",
args: "start -p 3101",
cwd: "/home/your-user/schedule",
env: {
NODE_ENV: "production",
PORT: 3101,
},
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: "512M",
},
],
};# PM2 명령어
pm2 start ecosystem.config.js # 시작
pm2 stop schedule # 중지
pm2 restart schedule # 재시작
pm2 logs schedule # 로그 확인
pm2 save # 현재 상태 저장
pm2 startup # 서버 재부팅 시 자동 시작<VirtualHost *:80>
ServerName schedule.your-domain.com
ProxyPreserveHost On
ProxyPass / http://localhost:3101/
ProxyPassReverse / http://localhost:3101/
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:3101/$1 [P,L]
</VirtualHost># 필요 모듈 활성화
sudo a2enmod proxy proxy_http proxy_wstunnel rewrite ssl headers
# 사이트 활성화
sudo a2ensite schedule.your-domain.com.conf
sudo systemctl reload apache2
# SSL 인증서 발급
sudo certbot --apache -d schedule.your-domain.com| 구분 | 값 |
|---|---|
| 이메일 | [email protected] |
| 비밀번호 | admin123 |
| 역할 | 관리자 |
| 범위 | 설명 |
|---|---|
| 회사 전체 | 모든 사용자가 볼 수 있음 |
| 부서 | 지정한 부서의 사용자만 볼 수 있음 |
| 본인만 | 작성자만 볼 수 있음 |
| 직급 이상 | 지정 직급 이상의 사용자만 볼 수 있음 |
/register에서 회원가입 (이름, 이메일, 비밀번호, 부서, 직급 선택)- 관리자가
/admin/users에서 상태를 활성으로 변경 - 승인된 사용자가 로그인 가능
일정 생성 시 "알림" 옵션으로 시작 전 알림 시간을 설정합니다. 크론 엔드포인트를 주기적으로 호출해야 이메일 알림이 발송됩니다.
# 크론탭 설정 (1분마다 실행)
crontab -e
* * * * * curl -s -H "x-cron-secret: your-cron-secret" https://schedule.your-domain.com/api/cron/notifynpm run dev # 개발 서버
npm run build # 프로덕션 빌드
npm run start # 프로덕션 서버
npm run db:migrate # Prisma 마이그레이션
npm run db:seed # 초기 데이터 시드
npm run db:push # 스키마 강제 동기화
npm run db:studio # Prisma Studio (DB GUI)