25 KiB
25 KiB
Gmail OAuth 로그인 작업계획서
작성일: 2026-01-10 예상 기간: 5~7일 우선순위: 4
1. 기능 개요
1.1 핵심 컨셉
- Google OAuth + 비밀번호 인증 모두 지원 (개발/운영 동일)
- Gmail 주소로 기존 사용자(wr_employee_info.email) 매칭
- 매칭 안되면 로그인 거부 → "관리자에게 문의하세요"
- OAuth 로그인 후 비밀번호 미설정 시 설정 안내
- 비밀번호 찾기: 이름+이메일+핸드폰 매칭 → 임시 비밀번호 이메일 발송
1.2 로그인 플로우 (개발/운영 동일)
┌─────────────────────────────────────────────────────────────────┐
│ 로그인 페이지 │
│ │
│ [G] Google로 로그인 │
│ [S] Synology로 로그인 ← (5번 작업 후 추가) │
│ │
│ ──────────── 또는 ──────────── │
│ │
│ 이메일: [_______________] │
│ 비밀번호: [_______________] │
│ │
│ [로그인] [비밀번호 찾기] │
└─────────────────────────────────────────────────────────────────┘
1.3 Google OAuth 로그인 플로우
[Google로 로그인] 클릭
↓
Google OAuth 인증
↓
Gmail 주소 획득
↓
wr_employee_info.email 매칭?
├─ NO → "등록되지 않은 사용자입니다. 관리자에게 문의하세요."
└─ YES ↓
비밀번호 설정됨?
├─ YES → 메인 페이지로 이동
└─ NO → 비밀번호 설정 페이지
"비상시 로그인을 위해 비밀번호를 설정해주세요"
1.4 비밀번호 찾기 플로우
[비밀번호 찾기] 클릭
↓
┌─────────────────────────────────────┐
│ 이름: [_______________] │
│ 이메일: [_______________] │
│ 핸드폰: [_______________] │
│ │
│ [임시 비밀번호 발송] │
└─────────────────────────────────────┘
↓
세 가지 모두 매칭되는 사용자 확인
├─ 매칭됨 → 이메일로 임시 비밀번호 발송 → "이메일을 확인해주세요"
└─ 불일치 → "일치하는 정보가 없습니다"
1.5 결정 사항
| # | 항목 | 결정 |
|---|---|---|
| 1 | 매칭 안되는 Gmail | 로그인 거부, 관리자 문의 안내 |
| 2 | 비밀번호 관리 | 필수 (OAuth 로그인 후 미설정 시 설정 유도) |
| 3 | Google 계정 연결 | 1인 1계정 |
| 4 | 환경별 로그인 | 개발/운영 동일 (OAuth + 비밀번호 모두 지원) |
| 5 | 비밀번호 찾기 | 이름+이메일+핸드폰 매칭 → 임시 비밀번호 이메일 발송 |
2. 데이터 모델
2.1 사용자 테이블 수정 (wr_employee_info)
-- 기존 테이블에 컬럼 추가
ALTER TABLE wr_employee_info
ADD COLUMN password_hash VARCHAR(200), -- 비밀번호 해시
ADD COLUMN google_id VARCHAR(100), -- Google 고유 ID (sub)
ADD COLUMN google_email VARCHAR(100), -- Google 이메일 (확인용)
ADD COLUMN google_linked_at TIMESTAMP, -- Google 연결 일시
ADD COLUMN last_login_at TIMESTAMP, -- 마지막 로그인
ADD COLUMN last_login_ip VARCHAR(50); -- 마지막 로그인 IP
-- 인덱스
CREATE UNIQUE INDEX idx_employee_google_id ON wr_employee_info(google_id) WHERE google_id IS NOT NULL;
2.2 로그인 이력 테이블 (wr_login_history) - 선택
CREATE TABLE wr_login_history (
history_id SERIAL PRIMARY KEY,
employee_id INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
login_type VARCHAR(20) NOT NULL, -- GOOGLE, PASSWORD
login_ip VARCHAR(50),
user_agent VARCHAR(500),
login_at TIMESTAMP DEFAULT NOW(),
success BOOLEAN DEFAULT true,
fail_reason VARCHAR(200) -- 실패 시 사유
);
CREATE INDEX idx_login_history_employee ON wr_login_history(employee_id);
CREATE INDEX idx_login_history_at ON wr_login_history(login_at);
3. API 설계
3.1 인증 API
| Method | Endpoint | 설명 |
|---|---|---|
| GET | /api/auth/google | Google OAuth 시작 (리다이렉트) |
| GET | /api/auth/google/callback | Google 콜백 처리 |
| POST | /api/auth/login | 이메일/비밀번호 로그인 |
| POST | /api/auth/logout | 로그아웃 |
| GET | /api/auth/me | 현재 사용자 정보 |
3.2 비밀번호 관리 API
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/auth/set-password | 비밀번호 최초 설정 (OAuth 후) |
| PUT | /api/auth/change-password | 비밀번호 변경 (본인) |
| POST | /api/auth/find-password | 비밀번호 찾기 (임시 비밀번호 발송) |
| PUT | /api/admin/user/[id]/reset-password | 비밀번호 초기화 (관리자) |
4. 화면 설계
4.1 로그인 페이지 (/login)
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 📊 주간보고 시스템 │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ [G] Google로 로그인 │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ [S] Synology로 로그인 │ │ ← 5번 작업 후
│ └─────────────────────────────────────┘ │
│ │
│ ─────────────── 또는 ─────────────── │
│ │
│ 이메일: [_________________________] │
│ 비밀번호: [_________________________] │
│ │
│ [로그인] [비밀번호 찾기] │
│ │
└─────────────────────────────────────────────────────────────────┘
4.2 비밀번호 설정 페이지 (/auth/set-password)
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 🔐 비밀번호 설정 │
│ │
│ Google 계정으로 로그인되었습니다. │
│ 비상시 로그인을 위해 비밀번호를 설정해주세요. │
│ │
│ 새 비밀번호: [_________________________] │
│ 비밀번호 확인: [_________________________] │
│ │
│ ※ 8자 이상, 영문+숫자 조합 권장 │
│ │
│ [비밀번호 설정] │
│ │
│ [나중에 설정하기 →] │
│ │
└─────────────────────────────────────────────────────────────────┘
* "나중에 설정하기" 클릭 시 메인으로 이동하지만, 다음 로그인 시 다시 안내
4.3 비밀번호 찾기 페이지 (/auth/find-password)
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 🔑 비밀번호 찾기 │
│ │
│ 등록된 정보와 일치하면 이메일로 임시 비밀번호를 발송합니다. │
│ │
│ 이름: [_________________________] │
│ 이메일: [_________________________] │
│ 핸드폰: [_________________________] │
│ │
│ [임시 비밀번호 발송] │
│ │
│ [← 로그인으로] │
│ │
└─────────────────────────────────────────────────────────────────┘
↓ 발송 성공 시 ↓
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ✅ 발송 완료 │
│ │
│ 임시 비밀번호가 이메일로 발송되었습니다. │
│ 이메일: hyo****@company.com │
│ │
│ ※ 로그인 후 비밀번호를 변경해주세요. │
│ │
│ [로그인하러 가기] │
│ │
└─────────────────────────────────────────────────────────────────┘
4.4 로그인 실패 시 (매칭 안됨)
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ⚠️ 로그인 실패 │
│ │
│ "unknown@gmail.com"은 등록되지 않은 사용자입니다. │
│ │
│ 시스템 사용을 위해서는 관리자에게 문의하여 │
│ 사용자 등록을 요청해주세요. │
│ │
│ 관리자 연락처: admin@company.com │
│ │
│ [다시 로그인] │
│ │
└─────────────────────────────────────────────────────────────────┘
4.4 마이페이지 - 비밀번호 변경 (/mypage)
┌─────────────────────────────────────────────────────────────────┐
│ 마이페이지 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 👤 기본 정보 │
│ ─────────────────────────────────────────────────────────────── │
│ 이름: 조효성 │
│ 이메일: hyosung@company.com │
│ 소속: 개발팀 │
│ 권한: 관리자 │
│ │
│ 🔗 Google 연결 │
│ ─────────────────────────────────────────────────────────────── │
│ 상태: ✅ 연결됨 (hyosung@gmail.com) │
│ 연결일: 2026-01-10 │
│ │
│ 🔒 비밀번호 변경 │
│ ─────────────────────────────────────────────────────────────── │
│ 현재 비밀번호: [_________________________] │
│ 새 비밀번호: [_________________________] │
│ 비밀번호 확인: [_________________________] │
│ │
│ [비밀번호 변경] │
│ │
│ 마지막 로그인: 2026-01-10 09:30 (Google) │
│ │
└─────────────────────────────────────────────────────────────────┘
4.5 관리자 - 사용자 관리 수정 (/admin/user)
┌─────────────────────────────────────────────────────────────────┐
│ 사용자 상세 [수정] [삭제] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 기본 정보 │
│ ─────────────────────────────────────────────────────────────── │
│ 이름: 조효성 │
│ 이메일: hyosung@company.com │
│ ... │
│ │
│ 🔐 계정 관리 │
│ ─────────────────────────────────────────────────────────────── │
│ Google 연결: ✅ 연결됨 (hyosung@gmail.com) [연결 해제] │
│ 비밀번호: ******** [초기화] │
│ 마지막 로그인: 2026-01-10 09:30 │
│ │
└─────────────────────────────────────────────────────────────────┘
* [초기화] 클릭 → 임시 비밀번호 생성 → 사용자에게 전달
5. 환경 설정
5.1 환경 변수
# .env (공통)
# Google OAuth
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=xxx
GOOGLE_REDIRECT_URI=https://weeklyreport.company.com/api/auth/google/callback
# 이메일 발송 (비밀번호 찾기용)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=noreply@company.com
SMTP_PASS=xxx
SMTP_FROM=주간보고시스템 <noreply@company.com>
5.2 개발/운영 분기 (필요 시)
# .env.development
GOOGLE_REDIRECT_URI=http://localhost:3000/api/auth/google/callback
# .env.production
GOOGLE_REDIRECT_URI=https://weeklyreport.company.com/api/auth/google/callback
6. Google OAuth 설정
6.1 Google Cloud Console 설정
- 프로젝트 생성: Google Cloud Console
- OAuth 동의 화면 설정:
- 앱 이름: 주간보고 시스템
- 범위: email, profile
- 사용자 인증 정보 생성:
- OAuth 2.0 클라이언트 ID
- 승인된 리디렉션 URI:
https://weeklyreport.company.com/api/auth/google/callback
6.2 OAuth 흐름
1. 사용자 → [Google로 로그인] 클릭
2. 서버 → Google 인증 페이지로 리다이렉트
3. 사용자 → Google 계정 선택, 권한 승인
4. Google → 콜백 URL로 리다이렉트 (code 포함)
5. 서버 → code로 access_token 요청
6. 서버 → access_token으로 사용자 정보 요청
7. 서버 → email로 wr_employee_info 조회
- 있으면: 세션 생성, 로그인 완료
- 없으면: 에러 페이지 표시
7. 보안 고려사항
7.1 비밀번호 정책
| 항목 | 정책 |
|---|---|
| 최소 길이 | 8자 이상 |
| 복잡도 | 영문 + 숫자 조합 권장 |
| 해시 알고리즘 | bcrypt (salt rounds: 10) |
| 임시 비밀번호 | 랜덤 생성 (12자, 영문+숫자+특수문자) |
7.2 세션 관리
| 항목 | 설정 |
|---|---|
| 세션 유효기간 | 24시간 (또는 설정 가능) |
| 세션 저장소 | 기존 방식 유지 (쿠키/메모리) |
| 동시 로그인 | 허용 (기기별 세션) |
7.3 비밀번호 찾기 이메일 템플릿
제목: [주간보고시스템] 임시 비밀번호 안내
───────────────────────────────────────
안녕하세요, {이름}님.
요청하신 임시 비밀번호를 안내드립니다.
임시 비밀번호: {임시비밀번호}
보안을 위해 로그인 후 반드시 비밀번호를 변경해주세요.
※ 본 메일은 발신 전용입니다.
※ 본인이 요청하지 않은 경우 관리자에게 문의해주세요.
───────────────────────────────────────
주간보고시스템
8. 작업 일정
Phase 1: DB + 환경 설정 (1일)
- 시작:
- 완료:
- 소요시간:
작업 내용:
- wr_employee_info 컬럼 추가 (password_hash, google_id 등)
- wr_login_history 테이블 생성 (선택)
- 환경 변수 설정 (Google OAuth, SMTP)
- Google Cloud Console OAuth 설정
Phase 2: 비밀번호 인증 (1.5일)
- 시작:
- 완료:
- 소요시간:
작업 내용:
- bcrypt 해시 처리
- 이메일/비밀번호 로그인 API
- 비밀번호 변경 API
- 비밀번호 초기화 API (관리자)
Phase 3: Google OAuth (1.5일)
- 시작:
- 완료:
- 소요시간:
작업 내용:
- Google OAuth 시작/콜백 API
- 사용자 매칭 로직 (email 기준)
- 비밀번호 미설정 시 설정 페이지 리다이렉트
- 비밀번호 최초 설정 API
Phase 4: 비밀번호 찾기 + 이메일 발송 (1일)
- 시작:
- 완료:
- 소요시간:
작업 내용:
- 이메일 발송 유틸 (nodemailer)
- 비밀번호 찾기 API (이름+이메일+핸드폰 매칭)
- 임시 비밀번호 생성 및 발송
- 비밀번호 찾기 페이지
Phase 5: 로그인 UI + 테스트 (1일)
- 시작:
- 완료:
- 소요시간:
작업 내용:
- 로그인 페이지 (OAuth + 비밀번호)
- 비밀번호 설정 페이지
- 로그인 실패 페이지
- 마이페이지 비밀번호 변경 UI
- 관리자 사용자 관리 수정 (비밀번호 초기화)
- 전체 플로우 테스트
작업 완료 결과
Phase별 작업 시간
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|---|---|---|---|---|
| 1 | DB + 환경 설정 | - | - | - |
| 2 | 비밀번호 인증 | - | - | - |
| 3 | Google OAuth | - | - | - |
| 4 | 비밀번호 찾기 + 이메일 발송 | - | - | - |
| 5 | 로그인 UI + 테스트 | - | - | - |
| 총 소요시간 | - |
생성/수정된 파일
| 구분 | 파일 | 작업 |
|---|---|---|
| DB | wr_employee_info | 수정 (컬럼 추가) |
| DB | wr_login_history | 신규 테이블 (선택) |
| API | backend/api/auth/google.get.ts | 신규 |
| API | backend/api/auth/google/callback.get.ts | 신규 |
| API | backend/api/auth/login.post.ts | 수정 |
| API | backend/api/auth/set-password.post.ts | 신규 |
| API | backend/api/auth/change-password.put.ts | 신규 |
| API | backend/api/auth/find-password.post.ts | 신규 |
| API | backend/api/admin/user/[id]/reset-password.put.ts | 신규 |
| Frontend | frontend/pages/login.vue | 수정 |
| Frontend | frontend/pages/auth/set-password.vue | 신규 |
| Frontend | frontend/pages/auth/find-password.vue | 신규 |
| Frontend | frontend/pages/mypage.vue | 수정 |
| Frontend | frontend/pages/admin/user/[id].vue | 수정 |
| Utils | backend/utils/password.ts | 신규 |
| Utils | backend/utils/email.ts | 신규 |
| Config | .env | 수정 (OAuth, SMTP 설정) |
9. 기술 스택
- Backend: Nitro (H3) + PostgreSQL
- Frontend: Nuxt3 + Vue3 + Bootstrap 5
- OAuth: Google OAuth 2.0
- 비밀번호: bcrypt
- 이메일 발송: nodemailer
- 세션: 기존 방식 유지
10. 향후 확장 고려
- Synology SSO 연동: 다음 작업 (5번)
- 2단계 인증 (2FA): TOTP 기반 추가 인증
- 소셜 로그인 확장: Microsoft, Kakao 등
- 비밀번호 만료: 90일 주기 변경 강제
- 로그인 알림: 새 기기 로그인 시 이메일 알림
- 임시 비밀번호 만료: 24시간 후 만료 처리