546 lines
22 KiB
Markdown
546 lines
22 KiB
Markdown
# 구글 그룹 연동 작업계획서
|
|
|
|
> 작성일: 2026-01-10
|
|
> 예상 기간: 1~2주
|
|
> 우선순위: 6
|
|
> 선행 작업: 4번 (Gmail OAuth 로그인)
|
|
|
|
---
|
|
|
|
## 1. 기능 개요
|
|
|
|
### 1.1 핵심 컨셉
|
|
- 사용자가 **Google OAuth로 로그인한 상태**에서
|
|
- 본인이 속한 **Google 그룹의 게시물 조회** (가져오기)
|
|
- 본인 **주간보고를 Google 그룹에 게시** (등록)
|
|
- 모두 **그룹 멤버 권한**으로 동작 (관리자 권한 불필요)
|
|
|
|
### 1.2 권한 구조
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Google 그룹: developers@company.com │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 멤버들: │
|
|
│ ├─ hyosung@company.com (시스템 관리자이기도 함) │
|
|
│ ├─ hyewon@company.com │
|
|
│ ├─ gildong@company.com │
|
|
│ └─ ... │
|
|
│ │
|
|
│ 멤버라면 누구나: │
|
|
│ ✅ 그룹 게시물 읽기 │
|
|
│ ✅ 그룹에 글 게시 │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
|
|
※ 시스템 관리자 ≠ 그룹 관리자
|
|
※ 시스템 관리자도 그냥 그룹 멤버로서 읽기/쓰기
|
|
```
|
|
|
|
### 1.3 기능 요약
|
|
|
|
| 기능 | 누가 | 설명 |
|
|
|------|------|------|
|
|
| **가져오기** | 그룹 멤버 | 그룹 게시물 목록/내용 조회 |
|
|
| **등록** | 그룹 멤버 | 본인 주간보고 → 그룹에 게시 |
|
|
|
|
### 1.4 결정 사항
|
|
|
|
| # | 항목 | 결정 |
|
|
|:-:|------|:----:|
|
|
| 1 | 권한 | 그룹 멤버 권한만 사용 |
|
|
| 2 | 가져오기 | 본인이 속한 그룹 게시물 조회 |
|
|
| 3 | 등록 | Gmail API로 그룹 이메일에 발송 |
|
|
| 4 | OAuth 연계 | 4번 작업(Gmail OAuth) 토큰 활용 |
|
|
|
|
---
|
|
|
|
## 2. 기능 상세
|
|
|
|
### 2.1 가져오기 (그룹 게시물 조회)
|
|
|
|
```
|
|
[주간보고시스템]
|
|
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 📬 Google 그룹 게시물 [새로고침] │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 그룹 선택: [developers@company.com ▼] │
|
|
│ ───────────────────────── │
|
|
│ developers@company.com │
|
|
│ team-leads@company.com │
|
|
│ all@company.com │
|
|
│ │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 📧 [주간보고] 2026년 2주차 - 서혜원 │
|
|
│ hyewon@company.com · 2026-01-10 09:30 │
|
|
│ │
|
|
│ 📧 [공지] 이번 주 회의 일정 변경 │
|
|
│ gildong@company.com · 2026-01-09 14:00 │
|
|
│ │
|
|
│ 📧 [주간보고] 2026년 2주차 - 홍길동 │
|
|
│ gildong@company.com · 2026-01-09 10:00 │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**사용 API**: Gmail API (그룹 이메일 검색)
|
|
```
|
|
GET /gmail/v1/users/me/messages?q=list:developers@company.com
|
|
```
|
|
|
|
### 2.2 등록 (주간보고 → 그룹 게시)
|
|
|
|
```
|
|
[주간보고 상세]
|
|
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 2026년 2주차 주간보고 - 조효성 [수정] [삭제] │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 금주 업무: │
|
|
│ - 로그인 기능 개발 완료 │
|
|
│ - 사용자 관리 페이지 수정 │
|
|
│ ... │
|
|
│ │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 🔗 Google 그룹 공유 │
|
|
│ ─────────────────────────────────────────────────────────────── │
|
|
│ │
|
|
│ 공유할 그룹: [developers@company.com ▼] │
|
|
│ │
|
|
│ [📤 그룹에 공유하기] │
|
|
│ │
|
|
│ ─────────────────────────────────────────────────────────────── │
|
|
│ 공유 이력: │
|
|
│ ✅ developers@company.com · 2026-01-10 09:30 │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**발송되는 이메일 형식**:
|
|
```
|
|
From: hyosung@company.com (본인)
|
|
To: developers@company.com (그룹)
|
|
Subject: [주간보고] 2026년 2주차 - 조효성
|
|
|
|
────────────────────────────────────────
|
|
2026년 2주차 주간보고
|
|
작성자: 조효성
|
|
소속: 개발팀
|
|
────────────────────────────────────────
|
|
|
|
[금주 업무]
|
|
- 로그인 기능 개발 완료
|
|
- 사용자 관리 페이지 수정
|
|
...
|
|
|
|
[차주 계획]
|
|
...
|
|
|
|
────────────────────────────────────────
|
|
※ 주간보고시스템에서 발송됨
|
|
```
|
|
|
|
**사용 API**: Gmail API (메일 발송)
|
|
```
|
|
POST /gmail/v1/users/me/messages/send
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 데이터 모델
|
|
|
|
### 3.1 그룹 공유 이력 테이블
|
|
|
|
```sql
|
|
CREATE TABLE wr_report_group_share (
|
|
share_id SERIAL PRIMARY KEY,
|
|
report_id INTEGER NOT NULL REFERENCES wr_weekly_report(report_id),
|
|
employee_id INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
|
|
group_email VARCHAR(200) NOT NULL, -- developers@company.com
|
|
gmail_message_id VARCHAR(100), -- Gmail 메시지 ID
|
|
shared_at TIMESTAMP DEFAULT NOW(),
|
|
share_status VARCHAR(20) DEFAULT 'SENT', -- SENT, FAILED
|
|
error_message TEXT
|
|
);
|
|
|
|
CREATE INDEX idx_report_share_report ON wr_report_group_share(report_id);
|
|
CREATE INDEX idx_report_share_employee ON wr_report_group_share(employee_id);
|
|
```
|
|
|
|
### 3.2 사용자 테이블 - OAuth 토큰 저장 (4번 작업 확장)
|
|
|
|
```sql
|
|
-- 4번 작업에서 추가 필요
|
|
ALTER TABLE wr_employee_info
|
|
ADD COLUMN google_access_token TEXT,
|
|
ADD COLUMN google_refresh_token TEXT,
|
|
ADD COLUMN google_token_expires_at TIMESTAMP;
|
|
```
|
|
|
|
---
|
|
|
|
## 4. API 설계
|
|
|
|
### 4.1 그룹 관련 API
|
|
|
|
| Method | Endpoint | 설명 |
|
|
|--------|----------|------|
|
|
| GET | /api/google-group/my-groups | 내가 속한 그룹 목록 |
|
|
| GET | /api/google-group/[groupEmail]/messages | 그룹 게시물 목록 |
|
|
| GET | /api/google-group/message/[messageId] | 게시물 상세 |
|
|
| POST | /api/google-group/share | 주간보고 그룹에 공유 |
|
|
| GET | /api/report/[id]/share-history | 공유 이력 조회 |
|
|
|
|
### 4.2 API 상세
|
|
|
|
#### GET /api/google-group/my-groups
|
|
```json
|
|
// Response
|
|
{
|
|
"groups": [
|
|
{ "email": "developers@company.com", "name": "개발팀" },
|
|
{ "email": "all@company.com", "name": "전체" }
|
|
]
|
|
}
|
|
```
|
|
|
|
#### POST /api/google-group/share
|
|
```json
|
|
// Request
|
|
{
|
|
"reportId": 123,
|
|
"groupEmail": "developers@company.com"
|
|
}
|
|
|
|
// Response
|
|
{
|
|
"success": true,
|
|
"messageId": "18d1234567890abc",
|
|
"sharedAt": "2026-01-10T09:30:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. OAuth Scope 설정
|
|
|
|
### 5.1 필요한 Scope (4번 작업 확장)
|
|
|
|
| Scope | 용도 |
|
|
|-------|------|
|
|
| `openid` | 기본 인증 |
|
|
| `email` | 이메일 주소 |
|
|
| `profile` | 프로필 정보 |
|
|
| **`https://www.googleapis.com/auth/gmail.readonly`** | 그룹 게시물 조회 |
|
|
| **`https://www.googleapis.com/auth/gmail.send`** | 그룹에 메일 발송 |
|
|
| **`https://www.googleapis.com/auth/gmail.labels`** | 라벨 조회 (선택) |
|
|
|
|
### 5.2 Google Cloud Console 설정 변경
|
|
|
|
1. **OAuth 동의 화면** > **범위 추가**
|
|
2. Gmail API 관련 scope 추가
|
|
3. **민감한 범위**로 분류되어 Google 검토 필요할 수 있음
|
|
|
|
```
|
|
⚠️ 주의: Gmail API scope는 "민감한 범위"로 분류됨
|
|
- 앱 인증 필요할 수 있음 (내부용은 대체로 OK)
|
|
- Google Workspace 도메인 내 사용 시 관리자 승인으로 해결
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 화면 설계
|
|
|
|
### 6.1 메뉴 추가
|
|
|
|
```
|
|
사이드바 메뉴:
|
|
├─ 📊 대시보드
|
|
├─ 📝 주간보고
|
|
│ ├─ 작성
|
|
│ ├─ 목록
|
|
│ └─ 통계
|
|
├─ 📬 Google 그룹 ← 신규
|
|
│ └─ 게시물 조회
|
|
├─ 👥 사용자 관리
|
|
└─ ⚙️ 설정
|
|
```
|
|
|
|
### 6.2 그룹 게시물 조회 (/google-group)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 📬 Google 그룹 게시물 │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 그룹: [developers@company.com ▼] [새로고침] │
|
|
│ │
|
|
│ ───────────────────────────────────────────────────────────────│
|
|
│ □ 제목 보낸 사람 날짜 │
|
|
│ ───────────────────────────────────────────────────────────────│
|
|
│ ☐ [주간보고] 2026년 2주차 - 서혜원 서혜원 01-10 09:30 │
|
|
│ ☐ [공지] 회의 일정 변경 홍길동 01-09 14:00 │
|
|
│ ☐ [주간보고] 2026년 2주차 - 홍길동 홍길동 01-09 10:00 │
|
|
│ ☐ [주간보고] 2026년 1주차 - 서혜원 서혜원 01-03 09:00 │
|
|
│ ... │
|
|
│ │
|
|
│ [1] [2] [3] ... [10] │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
|
|
※ Google OAuth 미연결 시:
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ │
|
|
│ Google 계정 연결이 필요합니다. │
|
|
│ │
|
|
│ [Google 계정 연결하기] │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### 6.3 주간보고 상세 - 그룹 공유 섹션
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 2026년 2주차 주간보고 [수정] [삭제] │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ (주간보고 내용...) │
|
|
│ │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ 📤 Google 그룹 공유 │
|
|
│ ─────────────────────────────────────────────────────────────── │
|
|
│ │
|
|
│ 그룹 선택: [developers@company.com ▼] [공유하기] │
|
|
│ │
|
|
│ 공유 이력: │
|
|
│ ┌─────────────────────────────────────────────────────────────┐ │
|
|
│ │ ✅ developers@company.com 2026-01-10 09:30 │ │
|
|
│ │ ✅ team-leads@company.com 2026-01-10 09:35 │ │
|
|
│ └─────────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 7. 구현 상세
|
|
|
|
### 7.1 그룹 목록 조회
|
|
|
|
Gmail API로는 직접 그룹 목록 조회가 어려움.
|
|
대안:
|
|
1. **사용자가 직접 입력** (간단)
|
|
2. **시스템 설정에서 그룹 목록 관리** (권장)
|
|
3. **Directory API 사용** (Google Workspace 필요)
|
|
|
|
```sql
|
|
-- 시스템 설정 테이블에 그룹 목록 저장
|
|
CREATE TABLE wr_google_group (
|
|
group_id SERIAL PRIMARY KEY,
|
|
group_email VARCHAR(200) NOT NULL UNIQUE,
|
|
group_name VARCHAR(100),
|
|
is_active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
INSERT INTO wr_google_group (group_email, group_name) VALUES
|
|
('developers@company.com', '개발팀'),
|
|
('team-leads@company.com', '팀장단'),
|
|
('all@company.com', '전체');
|
|
```
|
|
|
|
### 7.2 그룹 게시물 조회 로직
|
|
|
|
```typescript
|
|
// Gmail API로 특정 그룹 메일 검색
|
|
async function getGroupMessages(accessToken: string, groupEmail: string) {
|
|
const response = await fetch(
|
|
`https://gmail.googleapis.com/gmail/v1/users/me/messages?q=list:${groupEmail}`,
|
|
{
|
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
}
|
|
);
|
|
|
|
const data = await response.json();
|
|
return data.messages; // [{id, threadId}, ...]
|
|
}
|
|
|
|
// 메시지 상세 조회
|
|
async function getMessage(accessToken: string, messageId: string) {
|
|
const response = await fetch(
|
|
`https://gmail.googleapis.com/gmail/v1/users/me/messages/${messageId}`,
|
|
{
|
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
}
|
|
);
|
|
|
|
return response.json();
|
|
}
|
|
```
|
|
|
|
### 7.3 그룹에 메일 발송 로직
|
|
|
|
```typescript
|
|
async function sendToGroup(accessToken: string, to: string, subject: string, body: string) {
|
|
const email = [
|
|
`To: ${to}`,
|
|
`Subject: =?UTF-8?B?${Buffer.from(subject).toString('base64')}?=`,
|
|
'Content-Type: text/plain; charset=UTF-8',
|
|
'',
|
|
body
|
|
].join('\r\n');
|
|
|
|
const encodedEmail = Buffer.from(email)
|
|
.toString('base64')
|
|
.replace(/\+/g, '-')
|
|
.replace(/\//g, '_')
|
|
.replace(/=+$/, '');
|
|
|
|
const response = await fetch(
|
|
'https://gmail.googleapis.com/gmail/v1/users/me/messages/send',
|
|
{
|
|
method: 'POST',
|
|
headers: {
|
|
Authorization: `Bearer ${accessToken}`,
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ raw: encodedEmail })
|
|
}
|
|
);
|
|
|
|
return response.json();
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 8. 작업 일정
|
|
|
|
### Phase 1: OAuth Scope 확장 + 토큰 저장 (2일)
|
|
- [ ] 시작:
|
|
- [ ] 완료:
|
|
- [ ] 소요시간:
|
|
|
|
**작업 내용:**
|
|
- [ ] Google Cloud Console OAuth scope 추가
|
|
- [ ] wr_employee_info에 토큰 저장 컬럼 추가
|
|
- [ ] OAuth 콜백에서 access/refresh 토큰 저장
|
|
- [ ] 토큰 갱신 로직
|
|
|
|
---
|
|
|
|
### Phase 2: 그룹 게시물 조회 (3일)
|
|
- [ ] 시작:
|
|
- [ ] 완료:
|
|
- [ ] 소요시간:
|
|
|
|
**작업 내용:**
|
|
- [ ] wr_google_group 테이블 생성
|
|
- [ ] 그룹 목록 API
|
|
- [ ] 그룹 게시물 목록 API (Gmail API 연동)
|
|
- [ ] 게시물 상세 API
|
|
- [ ] 그룹 게시물 조회 페이지
|
|
|
|
---
|
|
|
|
### Phase 3: 주간보고 그룹 공유 (3일)
|
|
- [ ] 시작:
|
|
- [ ] 완료:
|
|
- [ ] 소요시간:
|
|
|
|
**작업 내용:**
|
|
- [ ] wr_report_group_share 테이블 생성
|
|
- [ ] 그룹 공유 API (Gmail 발송)
|
|
- [ ] 공유 이력 API
|
|
- [ ] 주간보고 상세에 공유 UI 추가
|
|
- [ ] 이메일 본문 템플릿
|
|
|
|
---
|
|
|
|
### Phase 4: 테스트 + 마무리 (2일)
|
|
- [ ] 시작:
|
|
- [ ] 완료:
|
|
- [ ] 소요시간:
|
|
|
|
**작업 내용:**
|
|
- [ ] 전체 플로우 테스트
|
|
- [ ] 토큰 만료 시 갱신 테스트
|
|
- [ ] 오류 처리 (권한 없음, 그룹 미가입 등)
|
|
- [ ] 관리자 - 그룹 목록 관리 페이지
|
|
|
|
---
|
|
|
|
## 작업 완료 결과
|
|
|
|
### Phase별 작업 시간
|
|
|
|
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|
|
|:-----:|----------|:----:|:----:|:--------:|
|
|
| 1 | OAuth Scope 확장 + 토큰 저장 | - | - | - |
|
|
| 2 | 그룹 게시물 조회 | - | - | - |
|
|
| 3 | 주간보고 그룹 공유 | - | - | - |
|
|
| 4 | 테스트 + 마무리 | - | - | - |
|
|
| | | | **총 소요시간** | **-** |
|
|
|
|
---
|
|
|
|
### 생성/수정된 파일
|
|
|
|
| 구분 | 파일 | 작업 |
|
|
|------|------|:----:|
|
|
| **DB** | wr_employee_info | 수정 (토큰 컬럼 추가) |
|
|
| **DB** | wr_google_group | 신규 테이블 |
|
|
| **DB** | wr_report_group_share | 신규 테이블 |
|
|
| **API** | backend/api/google-group/my-groups.get.ts | 신규 |
|
|
| **API** | backend/api/google-group/[groupEmail]/messages.get.ts | 신규 |
|
|
| **API** | backend/api/google-group/message/[id].get.ts | 신규 |
|
|
| **API** | backend/api/google-group/share.post.ts | 신규 |
|
|
| **API** | backend/api/report/[id]/share-history.get.ts | 신규 |
|
|
| **Frontend** | frontend/pages/google-group/index.vue | 신규 |
|
|
| **Frontend** | frontend/pages/report/[id].vue | 수정 (공유 UI) |
|
|
| **Utils** | backend/utils/gmail-api.ts | 신규 |
|
|
| **Utils** | backend/utils/google-token.ts | 신규 |
|
|
|
|
---
|
|
|
|
## 9. 기술 스택
|
|
|
|
- **Backend**: Nitro (H3) + PostgreSQL
|
|
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
|
|
- **외부 API**: Gmail API v1
|
|
- **인증**: OAuth 2.0 (4번 작업 확장)
|
|
|
|
---
|
|
|
|
## 10. 주의사항
|
|
|
|
### 10.1 Gmail API 제한
|
|
- **일일 할당량**: 사용자당 250개 할당량 단위/일
|
|
- **메일 발송**: 건당 100 할당량 단위
|
|
- 대량 발송 시 제한 주의
|
|
|
|
### 10.2 민감한 Scope
|
|
- Gmail readonly/send는 "민감한 범위"
|
|
- Google Workspace 내부 앱은 관리자 승인으로 해결
|
|
|
|
### 10.3 토큰 보안
|
|
- access_token, refresh_token 암호화 저장 권장
|
|
- HTTPS 필수
|
|
|
|
---
|
|
|
|
## 11. 향후 확장 고려
|
|
|
|
1. **게시물 시스템 연동**: 그룹 게시물 → 회의록/공지사항으로 저장
|
|
2. **자동 공유**: 주간보고 확정 시 자동으로 그룹 공유
|
|
3. **그룹별 자동 선택**: 프로젝트 → 그룹 매핑으로 자동 선택
|
|
4. **공유 알림**: 그룹 공유 시 시스템 알림
|