티스토리 뷰
728x90
반응형
아래는 React와 TypeScript를 사용하여 로그인 후 인증 정보를 관리하는 예시 코드입니다. 이 예제에서는 Context API와 커스텀 훅을 사용해 전역 인증 상태를 관리하며, localStorage에 토큰을 저장해 새로고침 시에도 인증 정보를 유지할 수 있도록 합니다.
1. 인증 Context 및 Provider 생성
먼저, 인증 정보를 담을 Context와 Provider를 만듭니다.
파일: src/contexts/AuthContext.tsx
import React, { createContext, useState, useEffect, ReactNode } from 'react';
// 사용자 정보 타입 정의 (필요에 따라 확장 가능)
interface User {
id: number;
name: string;
email: string;
}
// AuthContext에서 사용할 인터페이스
interface AuthContextType {
user: User | null;
token: string | null;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
}
// Context 생성 (초기값은 undefined로 설정)
export const AuthContext = createContext<AuthContextType | undefined>(undefined);
interface AuthProviderProps {
children: ReactNode;
}
export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
const [user, setUser] = useState<User | null>(null);
const [token, setToken] = useState<string | null>(null);
// 컴포넌트가 마운트될 때 localStorage에서 토큰을 불러옵니다.
useEffect(() => {
const storedToken = localStorage.getItem('authToken');
if (storedToken) {
setToken(storedToken);
// 토큰으로 사용자 정보를 불러오는 API 호출을 할 수도 있습니다.
// 예: fetchUserInfo(storedToken).then(setUser).catch(() => logout());
}
}, []);
// 로그인 함수 (실제 프로젝트에서는 API 호출로 대체)
const login = async (email: string, password: string) => {
try {
// 실제 API 호출 대신 아래와 같이 가짜 API 함수를 사용합니다.
const response = await fakeLoginApi(email, password);
setToken(response.token);
setUser(response.user);
localStorage.setItem('authToken', response.token);
} catch (error) {
console.error('Login failed:', error);
throw error;
}
};
// 로그아웃 시 상태 초기화 및 localStorage 정리
const logout = () => {
setUser(null);
setToken(null);
localStorage.removeItem('authToken');
};
return (
<AuthContext.Provider value={{ user, token, login, logout }}>
{children}
</AuthContext.Provider>
);
};
// 가짜 API 함수 (실제 프로젝트에서는 백엔드 API와 연동)
interface FakeLoginResponse {
token: string;
user: User;
}
const fakeLoginApi = async (email: string, password: string): Promise<FakeLoginResponse> => {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 예시: 올바른 이메일과 비밀번호인지 확인
if (email === 'test@example.com' && password === 'password') {
resolve({
token: 'fake-token-123456',
user: { id: 1, name: 'Test User', email }
});
} else {
reject(new Error('Invalid credentials'));
}
}, 1000);
});
};
2. 인증 상태를 쉽게 사용하기 위한 커스텀 훅 생성
Context를 사용하기 쉽게 하기 위해 커스텀 훅을 만들어 줍니다.
파일: src/hooks/useAuth.ts
import { useContext } from 'react';
import { AuthContext } from '../contexts/AuthContext';
export const useAuth = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
3. 로그인 컴포넌트 생성
로그인 폼을 구현하여 사용자가 이메일과 비밀번호를 입력하면 login 함수를 호출합니다.
파일: src/components/Login.tsx
import React, { useState } from 'react';
import { useAuth } from '../hooks/useAuth';
const Login: React.FC = () => {
const { login } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
await login(email, password);
} catch (err: any) {
setError(err.message);
} finally {
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Email:</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div>
<label>Password:</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
{error && <p style={{ color: 'red' }}>{error}</p>}
<button type="submit" disabled={loading}>
{loading ? 'Logging in...' : 'Login'}
</button>
</form>
);
};
export default Login;
4. 인증된 사용자 전용 컴포넌트 (대시보드) 생성
로그인 상태에 따라 사용자 정보를 보여주고 로그아웃할 수 있도록 합니다.
파일: src/components/Dashboard.tsx
import React from 'react';
import { useAuth } from '../hooks/useAuth';
const Dashboard: React.FC = () => {
const { user, logout } = useAuth();
if (!user) {
return <p>Please log in.</p>;
}
return (
<div>
<h2>Dashboard</h2>
<p>Welcome, {user.name}!</p>
<button onClick={logout}>Logout</button>
</div>
);
};
export default Dashboard;
5. App 컴포넌트에서 AuthProvider로 전체 애플리케이션 감싸기
최상위 컴포넌트에서 AuthProvider로 애플리케이션을 감싸면, 자식 컴포넌트들이 언제든지 인증 정보를 사용할 수 있습니다.
파일: src/App.tsx
import React from 'react';
import { AuthProvider } from './contexts/AuthContext';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
const App: React.FC = () => {
return (
<AuthProvider>
<div>
<h1>My App</h1>
{/* 로그인 폼과 대시보드를 모두 렌더링 (상황에 따라 라우팅을 적용할 수 있음) */}
<Login />
<Dashboard />
</div>
</AuthProvider>
);
};
export default App;
요약
- AuthContext와 AuthProvider
- 인증 정보를 저장하고, 로그인/로그아웃 기능을 구현합니다.
- localStorage를 사용해 토큰을 보관하여 새로고침에도 인증 상태를 유지할 수 있습니다.
- 커스텀 훅 (useAuth)
- Context를 간편하게 사용할 수 있도록 도와줍니다.
- Login 컴포넌트
- 사용자의 입력을 받아 로그인 API(여기서는 가짜 API)를 호출하고, 인증 상태를 업데이트합니다.
- Dashboard 컴포넌트
- 인증된 사용자 정보를 보여주고 로그아웃 기능을 제공합니다.
- App 컴포넌트
- 애플리케이션 전체를 AuthProvider로 감싸 인증 정보에 전역적으로 접근할 수 있도록 합니다.
이 구조를 기반으로 실제 API 호출 및 라우팅 기능(예: react-router-dom의 PrivateRoute) 등을 추가하면 보다 완성도 있는 인증 시스템을 구현할 수 있습니다. 필요한 부분이나 추가 질문이 있으면 언제든지 말씀해주세요!
728x90
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- await
- React
- 스프링 프레임워크(spring framework)
- 진수 변환
- In App Purchase
- jstl(java standard tag library)-core
- REST API
- 표현 언어(expression language)
- jsp 오픈 소스
- java web-mvc
- error-java
- .submit()
- 람다식(lambda expression)
- docker
- MainActor
- 스프링 시큐리티(spring security)
- 스프링 프레임워크(spring framewordk)
- jstl(java standard tag library)
- java 키워드 정리
- 제품 등록
- java-개발 환경 설정하기
- java.sql
- 스프링 시큐리티(spring security)-http basic 인증
- 특정 문자를 기준으로 자르기
- 문자 자르기
- nl2br
- system.io
- 인텔리제이(intellij)
- 메이븐(maven)
- System.Diagnostics
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
글 보관함