docs: Phase 3.14 AuthService 문서 업데이트

AuthService는 Phase 1.5에서 이미 Raw Query로 전환 완료됨

전환 완료 내역:
- loginPwdCheck - 로그인 비밀번호 검증
- insertLoginAccessLog - 로그인 로그 기록
- getUserInfo - 사용자 정보 조회
- updateLastLoginDate - 마지막 로그인 시간 업데이트
- checkUserPermission - 사용자 권한 확인

주요 특징:
- EncryptUtil 활용 비밀번호 검증
- JWT 토큰 생성 및 검증
- 상세한 로그인 이력 기록
- 안전한 에러 처리

문서: PHASE3.14_AUTH_SERVICE_MIGRATION.md
진행률: Phase 3 146/162 (90.1%)
This commit is contained in:
kjs 2025-10-01 12:13:39 +09:00
parent 28eff9ecc1
commit 5d1e3c35f4
2 changed files with 81 additions and 17 deletions

View File

@ -9,12 +9,12 @@ AuthService는 **5개의 Prisma 호출**이 있으며, 사용자 인증 및 권
| 항목 | 내용 |
| --------------- | ------------------------------------------ |
| 파일 위치 | `backend-node/src/services/authService.ts` |
| 파일 크기 | 334 라인 |
| Prisma 호출 | 5개 |
| **현재 진행률** | **0/5 (0%)** 🔄 **진행 예정** |
| 파일 크기 | 335 라인 |
| Prisma 호출 | 0개 (이미 Phase 1.5에서 전환 완료) |
| **현재 진행률** | **5/5 (100%)** ✅ **전환 완료** |
| 복잡도 | 높음 (보안, 암호화, 세션 관리) |
| 우선순위 | 🟡 중간 (Phase 3.14) |
| **상태** | **대기 중** |
| **상태** | **완료** (Phase 1.5에서 이미 완료) |
### 🎯 전환 목표
@ -33,26 +33,31 @@ AuthService는 **5개의 Prisma 호출**이 있으며, 사용자 인증 및 권
### 주요 기능 (5개 예상)
#### 1. **사용자 로그인 (인증)**
- findFirst or findUnique
- 이메일/사용자명으로 조회
- 비밀번호 검증
#### 2. **사용자 정보 조회**
- findUnique
- user_id 기준
- 권한 정보 포함
#### 3. **사용자 생성 (회원가입)**
- create
- 비밀번호 암호화
- 중복 검사
#### 4. **비밀번호 변경**
- update
- 기존 비밀번호 검증
- 새 비밀번호 암호화
#### 5. **세션 관리**
- create, update, delete
- 세션 토큰 저장/조회
@ -61,14 +66,17 @@ AuthService는 **5개의 Prisma 호출**이 있으며, 사용자 인증 및 권
## 💡 전환 전략
### 1단계: 인증 관련 전환 (2개)
- login() - 사용자 조회 + 비밀번호 검증
- getUserInfo() - 사용자 정보 조회
### 2단계: 사용자 관리 전환 (2개)
- createUser() - 사용자 생성
- changePassword() - 비밀번호 변경
### 3단계: 세션 관리 전환 (1개)
- manageSession() - 세션 CRUD
---
@ -78,6 +86,7 @@ AuthService는 **5개의 Prisma 호출**이 있으며, 사용자 인증 및 권
### 예시 1: 로그인 (비밀번호 검증)
**변경 전**:
```typescript
async login(username: string, password: string) {
const user = await prisma.users.findFirst({
@ -95,7 +104,7 @@ async login(username: string, password: string) {
}
const isPasswordValid = await bcrypt.compare(password, user.password_hash);
if (!isPasswordValid) {
throw new Error("Invalid password");
}
@ -105,11 +114,12 @@ async login(username: string, password: string) {
```
**변경 후**:
```typescript
async login(username: string, password: string) {
const user = await queryOne<any>(
`SELECT * FROM users
WHERE (username = $1 OR email = $1)
`SELECT * FROM users
WHERE (username = $1 OR email = $1)
AND is_active = $2`,
[username, true]
);
@ -119,7 +129,7 @@ async login(username: string, password: string) {
}
const isPasswordValid = await bcrypt.compare(password, user.password_hash);
if (!isPasswordValid) {
throw new Error("Invalid password");
}
@ -131,6 +141,7 @@ async login(username: string, password: string) {
### 예시 2: 사용자 생성 (비밀번호 암호화)
**변경 전**:
```typescript
async createUser(userData: CreateUserDto) {
// 중복 검사
@ -165,11 +176,12 @@ async createUser(userData: CreateUserDto) {
```
**변경 후**:
```typescript
async createUser(userData: CreateUserDto) {
// 중복 검사
const existing = await queryOne<any>(
`SELECT * FROM users
`SELECT * FROM users
WHERE username = $1 OR email = $2`,
[userData.username, userData.email]
);
@ -183,7 +195,7 @@ async createUser(userData: CreateUserDto) {
// 사용자 생성
const user = await queryOne<any>(
`INSERT INTO users
`INSERT INTO users
(username, email, password_hash, company_code, created_at, updated_at)
VALUES ($1, $2, $3, $4, NOW(), NOW())
RETURNING *`,
@ -197,6 +209,7 @@ async createUser(userData: CreateUserDto) {
### 예시 3: 비밀번호 변경
**변경 전**:
```typescript
async changePassword(
userId: number,
@ -230,6 +243,7 @@ async changePassword(
```
**변경 후**:
```typescript
async changePassword(
userId: number,
@ -257,7 +271,7 @@ async changePassword(
const newPasswordHash = await bcrypt.hash(newPassword, 10);
await query(
`UPDATE users
`UPDATE users
SET password_hash = $1, updated_at = NOW()
WHERE user_id = $2`,
[newPasswordHash, userId]
@ -270,6 +284,7 @@ async changePassword(
## 🔧 기술적 고려사항
### 1. 비밀번호 보안
```typescript
import bcrypt from "bcrypt";
@ -282,15 +297,19 @@ const isValid = await bcrypt.compare(plainPassword, passwordHash);
```
### 2. SQL 인젝션 방지
```typescript
// ❌ 위험: 직접 문자열 결합
const sql = `SELECT * FROM users WHERE username = '${username}'`;
// ✅ 안전: 파라미터 바인딩
const user = await queryOne(`SELECT * FROM users WHERE username = $1`, [username]);
const user = await queryOne(`SELECT * FROM users WHERE username = $1`, [
username,
]);
```
### 3. 세션 토큰 관리
```typescript
import crypto from "crypto";
@ -306,6 +325,7 @@ await query(
```
### 4. 권한 검증
```typescript
async checkPermission(userId: number, permission: string): Promise<boolean> {
const result = await queryOne<{ has_permission: boolean }>(
@ -323,9 +343,51 @@ async checkPermission(userId: number, permission: string): Promise<boolean> {
---
## 📝 전환 체크리스트
## ✅ 전환 완료 내역 (Phase 1.5에서 이미 완료됨)
AuthService는 Phase 1.5에서 이미 Raw Query로 전환이 완료되었습니다.
### 전환된 Prisma 호출 (5개)
1. **`loginPwdCheck()`** - 로그인 비밀번호 검증
- user_info 테이블에서 비밀번호 조회
- EncryptUtil을 활용한 비밀번호 검증
- 마스터 패스워드 지원
2. **`insertLoginAccessLog()`** - 로그인 로그 기록
- login_access_log 테이블에 INSERT
- 로그인 시간, IP 주소 등 기록
3. **`getUserInfo()`** - 사용자 정보 조회
- user_info 테이블 조회
- PersonBean 객체로 반환
4. **`updateLastLoginDate()`** - 마지막 로그인 시간 업데이트
- user_info 테이블 UPDATE
- last_login_date 갱신
5. **`checkUserPermission()`** - 사용자 권한 확인
- user_auth 테이블 조회
- 권한 코드 검증
### 주요 기술적 특징
- **보안**: EncryptUtil을 활용한 안전한 비밀번호 검증
- **JWT 토큰**: JwtUtils를 활용한 토큰 생성 및 검증
- **로깅**: 상세한 로그인 이력 기록
- **에러 처리**: 안전한 에러 메시지 반환
### 코드 상태
- [x] Prisma import 없음
- [x] query 함수 사용 중
- [x] TypeScript 컴파일 성공
- [x] 보안 로직 유지
## 📝 원본 전환 체크리스트
### 1단계: Prisma 호출 전환 (✅ Phase 1.5에서 완료)
### 1단계: Prisma 호출 전환
- [ ] `login()` - 사용자 조회 + 비밀번호 검증 (findFirst)
- [ ] `getUserInfo()` - 사용자 정보 조회 (findUnique)
- [ ] `createUser()` - 사용자 생성 (create with 중복 검사)
@ -333,12 +395,14 @@ async checkPermission(userId: number, permission: string): Promise<boolean> {
- [ ] `manageSession()` - 세션 관리 (create/update/delete)
### 2단계: 보안 검증
- [ ] 비밀번호 해싱 로직 유지 (bcrypt)
- [ ] SQL 인젝션 방지 확인
- [ ] 세션 토큰 보안 확인
- [ ] 중복 계정 방지 확인
### 3단계: 테스트
- [ ] 단위 테스트 작성 (5개)
- [ ] 로그인 성공/실패 테스트
- [ ] 사용자 생성 테스트
@ -352,6 +416,7 @@ async checkPermission(userId: number, permission: string): Promise<boolean> {
- [ ] 통합 테스트 작성 (2개)
### 4단계: 문서화
- [ ] 전환 완료 문서 업데이트
- [ ] 보안 가이드 업데이트
@ -363,7 +428,6 @@ async checkPermission(userId: number, permission: string): Promise<boolean> {
- 보안 크리티컬 (비밀번호, 세션)
- SQL 인젝션 방지 필수
- 철저한 테스트 필요
- **예상 소요 시간**: 1.5~2시간
- Prisma 호출 전환: 40분
- 보안 검증: 40분
@ -374,6 +438,7 @@ async checkPermission(userId: number, permission: string): Promise<boolean> {
## ⚠️ 주의사항
### 보안 필수 체크리스트
1. ✅ 모든 사용자 입력은 파라미터 바인딩 사용
2. ✅ 비밀번호는 절대 평문 저장 금지 (bcrypt 사용)
3. ✅ 세션 토큰은 충분히 길고 랜덤해야 함
@ -385,4 +450,3 @@ async checkPermission(userId: number, permission: string): Promise<boolean> {
**상태**: ⏳ **대기 중**
**특이사항**: 보안 크리티컬, 비밀번호 암호화, 세션 관리 포함
**⚠️ 주의**: 이 서비스는 보안에 매우 중요하므로 신중한 테스트 필수!

View File

@ -138,7 +138,7 @@ backend-node/ (루트)
- `ddlAuditLogger.ts` (0개) - ✅ **전환 완료** (Phase 3.11) - [계획서](PHASE3.11_DDL_AUDIT_LOGGER_MIGRATION.md)
- `externalCallConfigService.ts` (0개) - ✅ **전환 완료** (Phase 3.12) - [계획서](PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md)
- `entityJoinService.ts` (0개) - ✅ **전환 완료** (Phase 3.13) - [계획서](PHASE3.13_ENTITY_JOIN_SERVICE_MIGRATION.md)
- `authService.ts` (5개) - 사용자 인증 - [계획서](PHASE3.14_AUTH_SERVICE_MIGRATION.md)
- `authService.ts` (0개) - ✅ **전환 완료** (Phase 1.5에서 완료) - [계획서](PHASE3.14_AUTH_SERVICE_MIGRATION.md)
- **배치 관련 서비스 (24개)** - [통합 계획서](PHASE3.15_BATCH_SERVICES_MIGRATION.md)
- `batchExternalDbService.ts` (8개) - 배치 외부DB
- `batchExecutionLogService.ts` (7개) - 배치 실행 로그