# User API 연동 현황

## 📋 연동 완료 요약

User API는 **완전히 구현되어 있으며**, 로그인 및 회원가입 기능이 정상적으로 작동합니다.

### ✅ 구현 완료 항목

1. **API 클라이언트 설정**
   - Gateway를 통한 백엔드 직접 연동
   - 토큰 기반 인증 시스템
   - Request/Response 인터셉터

2. **타입 정의**
   - LoginRequest/Response
   - RegisterRequest/Response
   - ProfileResponse
   - User 및 AuthState 인터페이스

3. **인증 로직**
   - useAuth 커스텀 훅
   - AuthProvider Context
   - localStorage 기반 세션 관리

4. **UI 페이지**
   - 로그인 페이지 (/login)
   - 회원가입 페이지 (/register)
   - 3단계 회원가입 플로우

---

## 🏗️ 아키텍처 구조

```
프론트엔드                    Gateway                    백엔드
┌─────────────┐             ┌────────┐              ┌──────────┐
│             │   HTTP      │        │     HTTP     │          │
│   Browser   ├────────────>│Gateway ├─────────────>│ User API │
│             │<────────────┤        │<─────────────┤          │
└─────────────┘  JSON+JWT   └────────┘   JSON+JWT   └──────────┘
```

### API 클라이언트 설정

```typescript
// src/shared/api/client.ts
const GATEWAY_HOST = 'http://kt-event-marketing-api.20.214.196.128.nip.io';
const API_HOSTS = {
  user: GATEWAY_HOST,
  event: GATEWAY_HOST,
  content: GATEWAY_HOST,
  ai: GATEWAY_HOST,
  participation: GATEWAY_HOST,
  distribution: GATEWAY_HOST,
  analytics: GATEWAY_HOST,
};

// User API는 apiClient를 통해 직접 Gateway에 연결
export const apiClient: AxiosInstance = axios.create({
  baseURL: API_HOSTS.user,
  timeout: 90000,
  headers: {
    'Content-Type': 'application/json',
  },
});
```

**💡 프록시 라우트 불필요**: User API는 Next.js 프록시를 거치지 않고 브라우저에서 Gateway로 직접 요청합니다.

---

## 📡 User API 엔드포인트

### 1. 로그인
```http
POST /api/v1/users/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "password123"
}
```

**응답:**
```json
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "userId": "550e8400-e29b-41d4-a716-446655440000",
  "userName": "홍길동",
  "role": "USER",
  "email": "user@example.com"
}
```

### 2. 회원가입
```http
POST /api/v1/users/register
Content-Type: application/json

{
  "name": "홍길동",
  "phoneNumber": "01012345678",
  "email": "user@example.com",
  "password": "password123",
  "storeName": "홍길동 고깃집",
  "industry": "restaurant",
  "address": "서울특별시 강남구",
  "businessHours": "09:00-18:00"
}
```

**응답:**
```json
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "userId": "550e8400-e29b-41d4-a716-446655440000",
  "userName": "홍길동",
  "storeId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
  "storeName": "홍길동 고깃집"
}
```

### 3. 로그아웃
```http
POST /api/v1/users/logout
Authorization: Bearer {token}
```

**응답:**
```json
{
  "success": true,
  "message": "로그아웃되었습니다"
}
```

### 4. 프로필 조회
```http
GET /api/v1/users/profile
Authorization: Bearer {token}
```

**응답:**
```json
{
  "userId": "550e8400-e29b-41d4-a716-446655440000",
  "userName": "홍길동",
  "phoneNumber": "01012345678",
  "email": "user@example.com",
  "role": "USER",
  "storeId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
  "storeName": "홍길동 고깃집",
  "industry": "restaurant",
  "address": "서울특별시 강남구",
  "businessHours": "09:00-18:00",
  "createdAt": "2025-01-01T00:00:00",
  "lastLoginAt": "2025-01-10T12:00:00"
}
```

### 5. 프로필 수정
```http
PUT /api/v1/users/profile
Authorization: Bearer {token}
Content-Type: application/json

{
  "name": "홍길동",
  "phoneNumber": "01012345678",
  "storeName": "홍길동 고깃집",
  "industry": "restaurant",
  "address": "서울특별시 강남구",
  "businessHours": "09:00-18:00"
}
```

### 6. 비밀번호 변경
```http
PUT /api/v1/users/password
Authorization: Bearer {token}
Content-Type: application/json

{
  "currentPassword": "oldpassword",
  "newPassword": "newpassword123"
}
```

---

## 🔐 인증 플로우

### 로그인 플로우
```
1. 사용자가 이메일/비밀번호 입력
2. userApi.login() 호출
3. 서버에서 JWT 토큰 발급
4. localStorage에 토큰 저장
5. userApi.getProfile() 호출 (storeId 포함된 전체 정보 획득)
6. localStorage에 User 정보 저장
7. AuthContext 상태 업데이트
8. 메인 페이지로 리디렉션
```

### 회원가입 플로우
```
1. 3단계 폼 작성
   - Step 1: 계정 정보 (이메일, 비밀번호)
   - Step 2: 개인 정보 (이름, 전화번호)
   - Step 3: 사업장 정보 (상호명, 업종, 주소 등)
2. userApi.register() 호출
3. 서버에서 사용자 생성 및 JWT 토큰 발급
4. localStorage에 토큰 및 User 정보 저장
5. AuthContext 상태 업데이트
6. 회원가입 완료 다이얼로그 표시
7. 메인 페이지로 리디렉션
```

### 로그아웃 플로우
```
1. userApi.logout() 호출
2. 서버에서 세션 무효화 (실패해도 계속 진행)
3. localStorage에서 토큰 및 User 정보 삭제
4. AuthContext 상태 초기화
5. 로그인 페이지로 리디렉션
```

---

## 📂 파일 구조

### API Layer
```
src/entities/user/
├── api/
│   └── userApi.ts              # User API 서비스 함수
├── model/
│   └── types.ts                # TypeScript 타입 정의
└── index.ts                    # Public exports
```

### Features Layer
```
src/features/auth/
├── model/
│   ├── useAuth.ts              # 인증 커스텀 훅
│   └── AuthProvider.tsx        # Context Provider
└── index.ts                    # Public exports
```

### Pages
```
src/app/(auth)/
├── login/
│   └── page.tsx                # 로그인 페이지
└── register/
    └── page.tsx                # 회원가입 페이지 (3단계 플로우)
```

### Shared
```
src/shared/api/
├── client.ts                   # Axios 클라이언트 설정
└── index.ts                    # Public exports

src/stores/
└── authStore.ts               # Zustand 인증 스토어 (참고용)
```

---

## 🔑 주요 코드 구조

### 1. User API Service

**src/entities/user/api/userApi.ts:**
```typescript
const USER_API_BASE = '/api/v1/users';

export const userApi = {
  login: async (data: LoginRequest): Promise<LoginResponse> => {...},
  register: async (data: RegisterRequest): Promise<RegisterResponse> => {...},
  logout: async (): Promise<LogoutResponse> => {...},
  getProfile: async (): Promise<ProfileResponse> => {...},
  updateProfile: async (data: UpdateProfileRequest): Promise<ProfileResponse> => {...},
  changePassword: async (data: ChangePasswordRequest): Promise<void> => {...},
};
```

### 2. useAuth Hook

**src/features/auth/model/useAuth.ts:**
```typescript
export const useAuth = () => {
  const [authState, setAuthState] = useState<AuthState>({
    user: null,
    token: null,
    isAuthenticated: false,
    isLoading: true,
  });

  // 초기 인증 상태 확인 (localStorage 기반)
  useEffect(() => {
    const token = localStorage.getItem(TOKEN_KEY);
    const userStr = localStorage.getItem(USER_KEY);
    if (token && userStr) {
      const user = JSON.parse(userStr) as User;
      setAuthState({
        user,
        token,
        isAuthenticated: true,
        isLoading: false,
      });
    }
  }, []);

  // 로그인 함수
  const login = async (credentials: LoginRequest) => {
    const response = await userApi.login(credentials);
    localStorage.setItem(TOKEN_KEY, response.token);
    const profile = await userApi.getProfile();
    localStorage.setItem(USER_KEY, JSON.stringify(user));
    setAuthState({...});
    return { success: true, user };
  };

  // 회원가입, 로그아웃, 프로필 새로고침 함수들...

  return {
    ...authState,
    login,
    register,
    logout,
    refreshProfile,
  };
};
```

### 3. AuthProvider Context

**src/features/auth/model/AuthProvider.tsx:**
```typescript
const AuthContext = createContext<AuthContextType | null>(null);

export const AuthProvider = ({ children }: { children: ReactNode }) => {
  const auth = useAuth();
  return <AuthContext.Provider value={auth}>{children}</AuthContext.Provider>;
};

export const useAuthContext = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuthContext must be used within AuthProvider');
  }
  return context;
};
```

### 4. RootLayout 적용

**src/app/layout.tsx:**
```typescript
export default function RootLayout({ children }) {
  return (
    <html lang="ko">
      <body>
        <MUIThemeProvider>
          <ReactQueryProvider>
            <AuthProvider>
              {children}
            </AuthProvider>
          </ReactQueryProvider>
        </MUIThemeProvider>
      </body>
    </html>
  );
}
```

---

## 🧪 테스트 방법

### 1. 회원가입 테스트

1. 개발 서버 실행
   ```bash
   npm run dev
   ```

2. 브라우저에서 `/register` 접속

3. 3단계 폼 작성:
   - **Step 1**: 이메일 및 비밀번호 입력
   - **Step 2**: 이름 및 전화번호 입력 (010-1234-5678 형식)
   - **Step 3**: 사업장 정보 입력 및 약관 동의

4. "가입완료" 버튼 클릭

5. 성공 시:
   - 회원가입 완료 다이얼로그 표시
   - localStorage에 토큰 및 사용자 정보 저장
   - 메인 페이지로 리디렉션

### 2. 로그인 테스트

1. 브라우저에서 `/login` 접속

2. 이메일 및 비밀번호 입력

3. "로그인" 버튼 클릭

4. 성공 시:
   - localStorage에 토큰 및 사용자 정보 저장
   - 메인 페이지로 리디렉션
   - 헤더에 사용자 정보 표시

### 3. 로그아웃 테스트

1. 로그인된 상태에서 프로필 페이지 또는 헤더 메뉴 접근

2. "로그아웃" 버튼 클릭

3. 성공 시:
   - localStorage에서 토큰 및 사용자 정보 삭제
   - 로그인 페이지로 리디렉션

### 4. 디버깅

브라우저 개발자 도구 Console에서 다음 로그 확인:

```
📞 전화번호 변환: 010-1234-5678 -> 01012345678
📦 회원가입 요청 데이터: {...}
🚀 registerUser 함수 호출
📥 registerUser 결과: {...}
✅ 회원가입 성공: {...}
💾 localStorage에 토큰과 사용자 정보 저장 완료
```

---

## 🚨 주의사항

### 1. 전화번호 형식 변환
- **UI 입력**: `010-1234-5678` (하이픈 포함)
- **API 전송**: `01012345678` (하이픈 제거)
- 회원가입 페이지에서 자동 변환 처리됨

### 2. 토큰 관리
- Access Token은 localStorage에 `accessToken` 키로 저장
- User 정보는 localStorage에 `user` 키로 저장
- 401 응답 시 자동으로 로그인 페이지로 리디렉션

### 3. 프록시 라우트 없음
- User API는 Next.js 프록시를 사용하지 않음
- 브라우저에서 Gateway로 직접 요청
- CORS 설정이 Gateway에서 처리되어야 함

### 4. 로그아웃 에러 처리
- 로그아웃 API 실패해도 로컬 상태는 정리됨
- 서버 에러 발생 시에도 사용자는 정상적으로 로그아웃됨

---

## 📝 타입 정의 요약

```typescript
// 로그인
interface LoginRequest {
  email: string;
  password: string;
}

interface LoginResponse {
  token: string;
  userId: string; // UUID format
  userName: string;
  role: string;
  email: string;
}

// 회원가입
interface RegisterRequest {
  name: string;
  phoneNumber: string;        // "01012345678" 형식
  email: string;
  password: string;
  storeName: string;
  industry?: string;
  address: string;
  businessHours?: string;
}

interface RegisterResponse {
  token: string;
  userId: string; // UUID format
  userName: string;
  storeId: string; // UUID format
  storeName: string;
}

// 프로필
interface ProfileResponse {
  userId: string; // UUID format
  userName: string;
  phoneNumber: string;
  email: string;
  role: string;
  storeId: string; // UUID format
  storeName: string;
  industry: string;
  address: string;
  businessHours: string;
  createdAt: string;
  lastLoginAt: string;
}

// User 상태
interface User {
  userId: string; // UUID format
  userName: string;
  email: string;
  role: string;
  phoneNumber?: string;
  storeId?: string; // UUID format
  storeName?: string;
  industry?: string;
  address?: string;
  businessHours?: string;
}

// 인증 상태
interface AuthState {
  user: User | null;
  token: string | null;
  isAuthenticated: boolean;
  isLoading: boolean;
}
```

---

## ✅ 체크리스트

- [x] API 클라이언트 설정 완료
- [x] TypeScript 타입 정의 완료
- [x] useAuth Hook 구현 완료
- [x] AuthProvider Context 구현 완료
- [x] 로그인 페이지 구현 완료
- [x] 회원가입 페이지 (3단계) 구현 완료
- [x] localStorage 세션 관리 완료
- [x] Request/Response 인터셉터 설정 완료
- [x] 401 에러 핸들링 완료
- [x] RootLayout에 AuthProvider 적용 완료
- [x] 빌드 테스트 통과 ✅
- [ ] 개발 서버 실행 및 실제 API 테스트 (사용자가 수행)

---

## 📚 관련 파일

### 핵심 파일
- `src/entities/user/api/userApi.ts` - User API 서비스
- `src/entities/user/model/types.ts` - TypeScript 타입 정의
- `src/features/auth/model/useAuth.ts` - 인증 Hook
- `src/features/auth/model/AuthProvider.tsx` - Context Provider
- `src/app/(auth)/login/page.tsx` - 로그인 페이지
- `src/app/(auth)/register/page.tsx` - 회원가입 페이지
- `src/shared/api/client.ts` - Axios 클라이언트 설정

### 참고 파일
- `src/stores/authStore.ts` - Zustand 인증 스토어 (참고용, 현재 미사용)
- `src/app/layout.tsx` - RootLayout with AuthProvider

---

## 🎯 다음 단계

User API 연동은 완료되었으므로 다음 작업을 진행할 수 있습니다:

1. **개발 서버 테스트**: `npm run dev` 실행 후 실제 회원가입/로그인 테스트
2. **프로필 페이지 개선**: 사용자 정보 수정 기능 강화
3. **비밀번호 찾기**: 비밀번호 재설정 플로우 구현 (현재 미구현)
4. **소셜 로그인**: 카카오톡, 네이버 소셜 로그인 구현 (현재 준비 중)
5. **권한 관리**: Role 기반 접근 제어 (ADMIN, USER) 구현
6. **세션 갱신**: Refresh Token 로직 추가 (필요시)

---

## 📞 문의

User API 관련 문제나 개선사항은 프로젝트 팀에 문의하세요.

**문서 작성일**: 2025-01-30
**마지막 업데이트**: 2025-01-30
