-
Notifications
You must be signed in to change notification settings - Fork 2
✨Feat: 로그인/회원가입 로직 구현 #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
792d1d4
✨feat: 사용자 및 인증 관련 타입 정의
Insung-Jo 09a8bdf
✨feat: 인증 상태 관리용 zustand store 구현
Insung-Jo 1375491
✨feat: axios 인스턴스 및 인증 토큰 인터셉터 적용
Insung-Jo b730197
📁chore: 폴더 경로 수정
Insung-Jo d6f14be
🫧modify: axios 인스턴스 네이밍을 api로 변경
Insung-Jo 2e4fcd0
✨feat: 엔드포인트 상수 분리
Insung-Jo bb45d72
🫧modify: 경로 하드코딩 제거 및 엔드포인트 상수 적용
Insung-Jo 1b60403
✨feat: 로그인 및 회원가입 API 모듈 작성
Insung-Jo d2da14f
🫧modify: 파일명 컨벤션에 맞게 변경
Insung-Jo 21bc020
✨feat: API 응답 타입 분리 및 타입 정의 개선
Insung-Jo 2d49679
🫧modify: clearAuthState로 이름 변경 및 타입 정리
Insung-Jo c96b2cd
Merge branch 'develop' into feature/auth
Insung-Jo c715ea4
✨ Feat: useAuth 훅 구현
Insung-Jo 9b428bc
Merge branch 'develop' into feature/auth
Insung-Jo e3368f5
🗑️remove: 겹치는 파일 제거
Insung-Jo 3b50240
🫧modify: 커스텀 훅 일부 수정
Insung-Jo 8a9cd00
🫧modify: 파일명 변경 및 적용
Insung-Jo 22b6149
🐛fix: 코드래빗 수정사항 반영
Insung-Jo 51b6910
🫧modify: 누락된 타입 반영
Insung-Jo 105f8ac
🫧modify: 조건문 일부 수정
Insung-Jo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import api from '@/app/shared/lib/axios' | ||
| import { AUTH_ENDPOINT } from './authEndpoint' | ||
| import { LoginRequest, SignupRequest, LoginResponse } from '../types/auth.type' | ||
| import { User as SignupResponse } from '@/app/shared/types/user.type' | ||
|
|
||
| export const login = (data: LoginRequest) => { | ||
| return api.post<LoginResponse>(AUTH_ENDPOINT.LOGIN, data) | ||
| } | ||
|
|
||
| export const signup = (data: SignupRequest) => { | ||
| return api.post<SignupResponse>(AUTH_ENDPOINT.SIGNUP, data) | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Insung-Jo marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| export const AUTH_ENDPOINT = { | ||
| LOGIN: '/15-2/auth/login', | ||
| SIGNUP: '/15-2/users', | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { useAuthStore } from '../store/useAuthStore' | ||
| import { login as loginApi, signup as signupApi } from '../api/authApi' | ||
| import { LoginRequest, SignupRequest } from '../types/auth.type' | ||
|
|
||
| export function useAuth() { | ||
| const { setAccessToken, setUser, clearAuthState } = useAuthStore() | ||
|
|
||
| async function login(data: LoginRequest) { | ||
| const response = await loginApi(data) | ||
| const token = response.data.accessToken | ||
| const user = response.data.user | ||
|
|
||
| if (token && user) { | ||
| setAccessToken(token) | ||
| setUser(user) | ||
| } else { | ||
| throw new Error('유효하지 않은 응답입니다.') | ||
| } | ||
| } | ||
Insung-Jo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| async function signup(data: SignupRequest) { | ||
| await signupApi(data) | ||
| } | ||
|
|
||
| function logout() { | ||
| clearAuthState() | ||
| } | ||
|
|
||
| return { | ||
| login, | ||
| signup, | ||
| logout, | ||
| } | ||
| } | ||
Insung-Jo marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { create } from 'zustand' | ||
| import { persist } from 'zustand/middleware' | ||
| import { AuthState } from '../types/auth.type' | ||
|
|
||
| export const useAuthStore = create<AuthState>()( | ||
| persist( | ||
| (set) => ({ | ||
| accessToken: null, | ||
| user: null, | ||
| isLoggedIn: false, | ||
| setAccessToken: (token) => set({ accessToken: token, isLoggedIn: true }), | ||
| setUser: (user) => set({ user: user }), | ||
| clearAuthState: () => | ||
| set({ accessToken: null, user: null, isLoggedIn: false }), | ||
| }), | ||
| { | ||
| name: 'auth-storage', | ||
| }, | ||
| ), | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import { User } from '@/app/shared/types/user.type' | ||
|
|
||
| export interface LoginRequest { | ||
| email: string | ||
| password: string | ||
| } | ||
|
|
||
| export interface LoginResponse { | ||
| accessToken: string | ||
| user: User | ||
| } | ||
|
|
||
| export interface SignupRequest { | ||
| nickname: string | ||
| email: string | ||
| password: string | ||
| } | ||
|
|
||
| export interface AuthState { | ||
| accessToken: string | null | ||
| user: User | null | ||
| isLoggedIn: boolean | ||
| setAccessToken: (token: string) => void | ||
| setUser: (user: User) => void | ||
| clearAuthState: () => void | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import axios from 'axios' | ||
| import { useAuthStore } from '@/app/features/auth/store/useAuthStore' | ||
| import { AUTH_ENDPOINT } from '@/app/features/auth/api/authEndpoint' | ||
|
|
||
| const api = axios.create({ | ||
| baseURL: process.env.NEXT_PUBLIC_API_URL, | ||
| }) | ||
|
|
||
| api.interceptors.request.use( | ||
| (config) => { | ||
| const token = useAuthStore.getState().accessToken | ||
| const publicPaths = [AUTH_ENDPOINT.LOGIN, AUTH_ENDPOINT.SIGNUP] | ||
|
|
||
| if (!publicPaths.includes(config.url || '') && token) { | ||
Insung-Jo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| config.headers.Authorization = `Bearer ${token}` | ||
| } | ||
| return config | ||
| }, | ||
| (error) => { | ||
| return Promise.reject(error) | ||
| }, | ||
| ) | ||
|
|
||
| export default api | ||
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,8 @@ | ||
| export interface User { | ||
| id: number | ||
| name: string | ||
| email: string | ||
| avatarUrl?: string // optional | ||
| role?: 'user' | 'admin' // optional 예시 | ||
| createdAt?: string // optional ISO date string | ||
| updatedAt?: string // optional ISO date string | ||
| nickname: string | ||
| profileImageUrl: string | null | ||
| createdAt?: string | ||
| updatedAt?: string | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.