- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동 - book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서) - 빈 폴더 제거 (journey/assets/*)
166 lines
6.0 KiB
Markdown
166 lines
6.0 KiB
Markdown
# Auth Server 구축 및 Email Skill 클린 아키텍처 리팩토링 + Frontend-Customer 정적 빌드 배포 전환
|
|
|
|
**날짜**: 2025-07-17
|
|
**작업자**: happybell80 & Claude
|
|
|
|
## 오후 5시 37분
|
|
|
|
### Gmail OAuth 구현 및 파일 기반 토큰 저장
|
|
|
|
**배경**:
|
|
- email skill을 사용하기 위해 Gmail OAuth 인증 필요
|
|
- 중앙 인증 서버(auth.ro-being.com) 구축하여 토큰 관리
|
|
|
|
**주요 작업 내용**:
|
|
|
|
1. **초기 상태 확인**
|
|
- auth-server 컨테이너는 실행 중이었으나 Gmail OAuth 구현 안됨
|
|
- 서버와 로컬 코드 불일치 (서버에 placeholder만 존재)
|
|
|
|
2. **Google OAuth 설정 문제**
|
|
- Google Client Secret이 실제 값이 아님
|
|
- OAuth consent screen이 테스트 모드
|
|
- 테스트 사용자 추가 필요 (goeun2dc@gmail.com, happybell80@naver.com)
|
|
|
|
3. **Scope 문제 해결**
|
|
- Google이 scope 순서를 자동 변경하여 오류 발생
|
|
- 처음 시도: openid, email scope 추가 → 실패
|
|
- 해결: gmail.modify scope 사용 (읽기/쓰기/전송 모두 포함)
|
|
- 최종 해결: requests.post()로 직접 토큰 교환하여 scope 검증 우회
|
|
|
|
4. **파일 권한 문제**
|
|
- `/code/tokens` 디렉토리 권한 부족으로 토큰 저장 실패
|
|
- 해결: `chmod 777 tokens`로 모든 권한 부여
|
|
|
|
5. **구현 내용**
|
|
- 파일 기반 토큰 저장 (`/code/tokens/{user_id}_gmail.json`)
|
|
- status API: 토큰 상태 확인
|
|
- tokens API: 저장된 토큰 조회
|
|
- aiofiles 패키지 추가
|
|
|
|
**최종 결과**:
|
|
- Gmail OAuth 인증 성공
|
|
- 토큰 파일 생성 및 저장 완료
|
|
- Access Token과 Refresh Token 모두 획득
|
|
- auth-server API 정상 작동
|
|
|
|
**다음 단계**:
|
|
- email skill과 auth-server 연동
|
|
- PostgreSQL 기반 영구 저장소 구현
|
|
|
|
## 오후 10시 00분
|
|
|
|
### Email Skill 클린 아키텍처 리팩토링
|
|
|
|
**배경**:
|
|
- Email skill이 절차형 코드로 작성되어 테스트와 확장이 어려움
|
|
- 로빙 프로젝트의 함수형 프로그래밍 패러다임과 불일치
|
|
- 비즈니스 로직과 API 레이어가 혼재
|
|
|
|
**주요 리팩토링 작업**:
|
|
|
|
1. **아키텍처 개선**
|
|
- 비즈니스 로직을 `GmailService` 클래스로 분리
|
|
- `CredentialsProvider` 인터페이스로 토큰 제공자 추상화
|
|
- FastAPI 의존성 주입 패턴 적용
|
|
|
|
2. **함수형 프로그래밍 적용**
|
|
- `Result[T, E]` 타입으로 성공/실패 명시적 처리
|
|
- 순수 함수와 부작용(IO) 분리
|
|
- 불변 데이터 구조 사용 (`@dataclass(frozen=True)`)
|
|
|
|
3. **테스트 코드 작성**
|
|
- 단위 테스트: `test_gmail_service.py` (서비스 로직)
|
|
- 통합 테스트: `test_api.py` (API 엔드포인트)
|
|
- Mock 객체로 외부 의존성 격리
|
|
|
|
4. **코드 정리**
|
|
- 중복 파일 제거 (read_email.py, send_email.py 등)
|
|
- 함수형 실험 파일 통합 완료
|
|
- README 업데이트 및 .gitignore 추가
|
|
|
|
**최종 파일 구조**:
|
|
```
|
|
skill_email/
|
|
├── main.py # FastAPI 애플리케이션 (리팩토링됨)
|
|
├── functional_types.py # Result, IO 등 함수형 타입
|
|
├── services/
|
|
│ └── gmail_service.py # Gmail 비즈니스 로직
|
|
└── tests/
|
|
├── test_gmail_service.py # 서비스 단위 테스트
|
|
└── test_api.py # API 통합 테스트
|
|
```
|
|
|
|
**테스트 결과**:
|
|
- 12/13 테스트 통과 (92% 성공률)
|
|
- API 서버 정상 작동 (http://localhost:8100)
|
|
- 실제 이메일 전송 성공 (Message ID: 198184a9bd05587a)
|
|
- auth-server 토큰으로 Gmail API 정상 연동
|
|
|
|
**기술적 성과**:
|
|
- 테스트 가능한 구조로 개선 (Mock 주입)
|
|
- 확장 가능한 설계 (Provider 패턴)
|
|
- 타입 안전성 확보 (Result 패턴)
|
|
- 로빙 프로젝트 함수형 철학 구현
|
|
|
|
**개발 프로세스**:
|
|
- happybell80 브랜치로 작업
|
|
- 상세한 PR 작성 및 코드 리뷰 준비
|
|
- 서버에서 실제 환경 테스트 완료
|
|
|
|
**다음 계획**:
|
|
- PostgreSQL 기반 토큰 저장소 구현 (`DbCredentialsProvider`)
|
|
- 토큰 자동 갱신 로직 추가
|
|
- 로빙과 연동 (rb10508_test에서 email skill 호출)
|
|
|
|
## 오후 11시 30분
|
|
|
|
### Frontend-Customer 정적 빌드 배포 전환
|
|
|
|
**배경**:
|
|
- frontend-customer가 Docker 컨테이너 5173 포트에서 Vite 개발 서버로 실행 중
|
|
- 정적 빌드(dist 폴더)는 생성되었으나 사용되지 않음
|
|
- 프로덕션 환경에서는 nginx 정적 서빙이 더 효율적
|
|
|
|
**문제 상황**:
|
|
1. **CI/CD 배포 실패**: frontend-base 배포 중 500 에러
|
|
2. **admin 페이지 경로 문제**: Docker 컨테이너에서 admin-ui 폴더 접근 불가
|
|
3. **Health check 실패**: 고정 sleep과 admin 페이지 체크로 인한 타임아웃
|
|
|
|
**해결 과정**:
|
|
|
|
1. **CI/CD 파이프라인 개선**
|
|
- 고정 `sleep 30` 대신 retry 로직 구현 (최대 10회)
|
|
- 점진적 대기 시간 (3초, 6초, 9초...)
|
|
- 500 에러 발생하던 admin 페이지 체크 제거
|
|
|
|
2. **Docker 볼륨 마운트 수정**
|
|
- docker-compose.yml에 admin-ui 볼륨 추가: `./admin-ui:/app/admin-ui`
|
|
- Dockerfile의 잘못된 COPY 명령 제거
|
|
|
|
3. **nginx 설정 정적 파일 서빙으로 전환**
|
|
- HTTP (80포트): `/home/admin/frontend-customer/dist` 설정
|
|
- HTTPS (443포트): proxy_pass 제거, 정적 파일 서빙으로 변경
|
|
- try_files 중복 지시어 제거로 syntax 에러 해결
|
|
|
|
4. **권한 문제 해결**
|
|
- nginx(www-data) 사용자가 `/home/admin/` 접근 불가 문제
|
|
- 최소 권한 부여: `sudo chmod o+x /home` + `sudo chmod o+x /home/admin`
|
|
- 심볼릭 링크 대신 직접 경로 사용
|
|
|
|
**최종 결과**:
|
|
- **성능**: HTTP/HTTPS 모두 200 OK 응답
|
|
- **효율성**: Docker 컨테이너 제거로 메모리 사용량 감소
|
|
- **배포**: CI/CD 빌드 후 nginx 자동 반영
|
|
- **포트**: 5173 포트 해제
|
|
|
|
**기술적 성과**:
|
|
- 개발 서버 → 정적 파일 서빙으로 전환
|
|
- nginx 직접 서빙으로 응답 속도 향상
|
|
- CI/CD retry 로직으로 배포 안정성 확보
|
|
- 최소 권한 원칙 적용한 보안 개선
|
|
|
|
**최종 구조**:
|
|
```
|
|
nginx (www-data) → /home/admin/frontend-customer/dist/ (직접 연결)
|
|
``` |