# User API 연동 가이드

## 개요

FSD(Feature-Sliced Design) 아키텍처를 기반으로 User Service API 연동을 구현했습니다.

## 디렉토리 구조

```
src/
├── shared/
│   └── api/
│       ├── client.ts          # Axios 클라이언트 설정
│       ├── types.ts           # 공통 API 타입
│       └── index.ts
├── entities/
│   └── user/
│       ├── model/
│       │   └── types.ts       # User 엔티티 타입
│       ├── api/
│       │   └── userApi.ts     # User API 함수
│       └── index.ts
└── features/
    ├── auth/
    │   ├── model/
    │   │   ├── useAuth.ts     # 인증 훅
    │   │   └── AuthProvider.tsx  # 인증 Context
    │   └── index.ts
    └── profile/
        ├── model/
        │   └── useProfile.ts  # 프로필 훅
        └── index.ts
```

## API 명세

- **Base URL**: `http://20.196.65.160:8081`
- **Endpoints**:
  - `POST /api/v1/users/login` - 로그인
  - `POST /api/v1/users/register` - 회원가입
  - `POST /api/v1/users/logout` - 로그아웃
  - `GET /api/v1/users/profile` - 프로필 조회
  - `PUT /api/v1/users/profile` - 프로필 수정
  - `PUT /api/v1/users/password` - 비밀번호 변경

## 사용 방법

### 1. AuthProvider 설정

루트 레이아웃에 AuthProvider를 추가합니다:

```tsx
// app/layout.tsx
import { AuthProvider } from '@/features/auth';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <AuthProvider>
          {children}
        </AuthProvider>
      </body>
    </html>
  );
}
```

### 2. 로그인 구현 예제

```tsx
'use client';

import { useAuthContext } from '@/features/auth';
import { useState } from 'react';

export default function LoginPage() {
  const { login, isLoading } = useAuthContext();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = async (e: React.FormEvent) => {
    e.preventDefault();

    const result = await login({ email, password });

    if (result.success) {
      // 로그인 성공
      console.log('로그인 성공:', result.user);
      // 페이지 이동 등
    } else {
      // 로그인 실패
      console.error('로그인 실패:', result.error);
    }
  };

  return (
    <form onSubmit={handleLogin}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="이메일"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="비밀번호"
      />
      <button type="submit" disabled={isLoading}>
        {isLoading ? '로그인 중...' : '로그인'}
      </button>
    </form>
  );
}
```

### 3. 회원가입 구현 예제

```tsx
'use client';

import { useAuthContext } from '@/features/auth';
import { useState } from 'react';
import type { RegisterRequest } from '@/entities/user';

export default function RegisterPage() {
  const { register, isLoading } = useAuthContext();
  const [formData, setFormData] = useState<RegisterRequest>({
    name: '',
    phoneNumber: '',
    email: '',
    password: '',
    storeName: '',
    industry: '',
    address: '',
    businessHours: '',
  });

  const handleRegister = async (e: React.FormEvent) => {
    e.preventDefault();

    const result = await register(formData);

    if (result.success) {
      console.log('회원가입 성공:', result.user);
    } else {
      console.error('회원가입 실패:', result.error);
    }
  };

  return (
    <form onSubmit={handleRegister}>
      {/* 폼 필드들... */}
      <button type="submit" disabled={isLoading}>
        {isLoading ? '가입 중...' : '회원가입'}
      </button>
    </form>
  );
}
```

### 4. 프로필 조회 및 수정 예제

```tsx
'use client';

import { useProfile } from '@/features/profile';
import { useEffect } from 'react';

export default function ProfilePage() {
  const {
    profile,
    isLoading,
    error,
    fetchProfile,
    updateProfile
  } = useProfile();

  useEffect(() => {
    fetchProfile();
  }, [fetchProfile]);

  const handleUpdate = async () => {
    const result = await updateProfile({
      name: '새로운 이름',
      storeName: '새로운 가게명',
    });

    if (result.success) {
      console.log('프로필 수정 성공:', result.data);
    }
  };

  if (isLoading) return <div>로딩 중...</div>;
  if (error) return <div>에러: {error}</div>;
  if (!profile) return <div>프로필 없음</div>;

  return (
    <div>
      <h1>{profile.userName}</h1>
      <p>이메일: {profile.email}</p>
      <p>가게명: {profile.storeName}</p>
      <button onClick={handleUpdate}>프로필 수정</button>
    </div>
  );
}
```

### 5. 인증 상태 확인 예제

```tsx
'use client';

import { useAuthContext } from '@/features/auth';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';

export default function ProtectedPage() {
  const { user, isAuthenticated, isLoading } = useAuthContext();
  const router = useRouter();

  useEffect(() => {
    if (!isLoading && !isAuthenticated) {
      router.push('/login');
    }
  }, [isAuthenticated, isLoading, router]);

  if (isLoading) return <div>로딩 중...</div>;
  if (!isAuthenticated) return null;

  return (
    <div>
      <h1>환영합니다, {user?.userName}님!</h1>
    </div>
  );
}
```

### 6. 로그아웃 구현 예제

```tsx
'use client';

import { useAuthContext } from '@/features/auth';
import { useRouter } from 'next/navigation';

export default function Header() {
  const { user, isAuthenticated, logout } = useAuthContext();
  const router = useRouter();

  const handleLogout = async () => {
    await logout();
    router.push('/login');
  };

  if (!isAuthenticated) return null;

  return (
    <header>
      <span>{user?.userName}</span>
      <button onClick={handleLogout}>로그아웃</button>
    </header>
  );
}
```

## 타입 정의

### User 타입

```typescript
interface User {
  userId: number;
  userName: string;
  email: string;
  role: string;
  phoneNumber?: string;
  storeId?: number;
  storeName?: string;
  industry?: string;
  address?: string;
  businessHours?: string;
}
```

### LoginRequest 타입

```typescript
interface LoginRequest {
  email: string;
  password: string;
}
```

### RegisterRequest 타입

```typescript
interface RegisterRequest {
  name: string;
  phoneNumber: string;      // 패턴: ^010\d{8}$
  email: string;
  password: string;          // 최소 8자
  storeName: string;
  industry?: string;
  address: string;
  businessHours?: string;
}
```

## API Client 설정

API 클라이언트는 다음 기능을 자동으로 처리합니다:

1. **JWT 토큰 자동 추가**: localStorage의 `accessToken`을 자동으로 헤더에 포함
2. **401 인증 오류 처리**: 인증 실패 시 자동으로 토큰 삭제 및 로그인 페이지로 리다이렉트
3. **Base URL 설정**: 환경 변수로 API 서버 URL 관리

## 환경 변수

`.env.local` 파일에 다음 환경 변수를 설정하세요:

```env
NEXT_PUBLIC_API_BASE_URL=http://20.196.65.160:8081
```

## 주의사항

1. **토큰 관리**: 토큰은 localStorage에 저장되며, 로그아웃 시 자동으로 삭제됩니다.
2. **인증 상태**: AuthProvider로 감싼 컴포넌트에서만 useAuthContext 사용 가능합니다.
3. **에러 처리**: 모든 API 함수는 try-catch로 에러를 처리하며, 결과 객체에 success와 error를 포함합니다.
4. **비밀번호 검증**: 회원가입 시 비밀번호는 최소 8자 이상이어야 합니다.
5. **전화번호 형식**: 010으로 시작하는 11자리 숫자만 허용됩니다.

## 빌드 및 실행

```bash
# 빌드
npm run build

# 개발 서버 실행 (사용자가 직접 수행)
npm run dev
```
