세션을 상태에 추가하기
세션을 상태에 추가하기
로그인 과정을 완료하려면 사용자가 로그인했음을 반영하기 위해 앱 상태를 세션으로 업데이트해야 합니다.
앱 상태 업데이트
먼저 사용자가 로그인했음을 나타내도록 애플리케이션 상태를 업데이트합니다. 이 상태를 Login
컨테이너에 저장하고 싶을 수 있지만, 이 상태를 여러 곳에서 사용할 것이므로 상태를 상위로 끌어올리는 것이 합리적입니다. 가장 논리적인 위치는 App
컴포넌트입니다.
사용자의 로그인 상태를 저장하기 위해 src/App.tsx
에 useState
훅을 추가합니다.
App
컴포넌트 함수 상단에 다음을 추가합니다.
const [isAuthenticated, userHasAuthenticated] = useState(false);
그리고 이를 임포트합니다.
import { useState } from "react";
이 코드는 isAuthenticated
상태 변수를 false
로 초기화합니다. 즉, 사용자가 로그인하지 않은 상태입니다. userHasAuthenticated
를 호출하면 이 상태를 업데이트할 수 있습니다. 하지만 Login
컨테이너가 이 메서드를 호출하려면 이 메서드의 참조를 전달해야 합니다.
세션을 Context에 저장하기
세션 관련 정보를 모든 컨테이너에 전달해야 합니다. 이를 prop으로 전달하면 각 컴포넌트마다 수동으로 전달해야 하기 때문에 번거로울 수 있습니다. 대신 React Context를 사용해 보겠습니다.
우리 앱 전체에서 사용할 컨텍스트를 만들겠습니다.
packages/frontend/
React 디렉토리 안에 src/lib/
디렉토리를 생성합니다.
$ mkdir src/lib/
이 디렉토리는 모든 공통 코드를 저장하는 데 사용됩니다.
src/lib/contextLib.ts
파일을 생성하고 아래 내용을 추가합니다.
import { createContext, useContext } from "react";
export interface AppContextType {
isAuthenticated: boolean;
userHasAuthenticated: React.Dispatch<React.SetStateAction<boolean>>;
}
export const AppContext = createContext<AppContextType>({
isAuthenticated: false,
userHasAuthenticated: useAppContext,
});
export function useAppContext() {
return useContext(AppContext);
}
이 간단한 코드는 두 가지를 생성하고 내보냅니다:
createContext
API를 사용해 앱의 새로운 컨텍스트를 생성합니다.useContext
React Hook을 사용해 컨텍스트에 접근합니다.
컨텍스트가 어떻게 동작하는지 잘 모르더라도 걱정하지 마세요. 사용해 보면 더 이해가 될 것입니다.
src/App.tsx
파일의 헤더 부분에 새로운 앱 컨텍스트를 임포트합니다.
import { AppContext, AppContextType } from "./lib/contextLib";
이제 세션을 컨텍스트에 추가하고 컨테이너에 전달해 보겠습니다:
src/App.tsx
의 return
문에서 Routes
컴포넌트를 감싸줍니다.
<Routes />
이렇게 변경합니다.
<AppContext.Provider
value={{ isAuthenticated, userHasAuthenticated } as AppContextType}
>
<Routes />
</AppContext.Provider>
React Context는 두 부분으로 구성됩니다. 첫 번째는 Provider입니다. 이는 React에게 Context Provider 안에 있는 모든 자식 컴포넌트가 우리가 넣은 것에 접근할 수 있어야 한다고 알려줍니다. 이 경우 우리는 다음 객체를 넣습니다:
{
isAuthenticated, userHasAuthenticated;
}
Context를 사용하여 상태 업데이트하기
Context API의 두 번째 부분은 컨슈머(consumer)입니다. 이를 src/containers/Login.tsx
의 Login 컨테이너에 추가하겠습니다.
export default function Login() {
줄 아래에 훅을 추가합니다.
const { userHasAuthenticated } = useAppContext();
그리고 src/containers/Login.tsx
의 헤더 부분에서 이를 임포트합니다.
import { useAppContext } from "../lib/contextLib";
이 코드는 React에게 여기서 앱 컨텍스트를 사용하고 싶으며, userHasAuthenticated
함수를 사용할 수 있게 해달라고 알려줍니다.
마지막으로, src/containers/Login.tsx
에서 alert('Logged in');
줄을 다음 코드로 대체합니다.
userHasAuthenticated(true);
로그아웃 버튼 만들기
이제 사용자가 로그인하면 로그아웃 버튼을 표시할 수 있습니다. src/App.tsx
에서 다음 부분을 찾아보세요.
<LinkContainer to="/signup">
<Nav.Link>Signup</Nav.Link>
</LinkContainer>
<LinkContainer to="/login">
<Nav.Link>Login</Nav.Link>
</LinkContainer>
그리고 이를 다음 코드로 대체하세요:
{isAuthenticated ? (
<Nav.Link onClick={handleLogout}>Logout</Nav.Link>
) : (
<>
<LinkContainer to="/signup">
<Nav.Link>Signup</Nav.Link>
</LinkContainer>
<LinkContainer to="/login">
<Nav.Link>Login</Nav.Link>
</LinkContainer>
</>
)}
<>
또는 프래그먼트 컴포넌트는 플레이스홀더 컴포넌트로 생각할 수 있습니다. 사용자가 로그인하지 않은 경우 두 개의 링크를 렌더링하려면 이를 단일 컴포넌트(예: div
)로 감싸야 합니다. 하지만 프래그먼트 컴포넌트를 사용하면 두 링크가 이 컴포넌트 안에 있지만 추가 HTML을 렌더링하지 않도록 React에 알립니다.
그리고 src/App.tsx
의 return
문 위에 handleLogout
메서드를 추가하세요.
function handleLogout() {
userHasAuthenticated(false);
}
이제 브라우저로 이동하여 Secure Our Serverless APIs 챕터에서 생성한 관리자 자격 증명으로 로그인해 보세요. 로그아웃 버튼이 즉시 나타나는 것을 확인할 수 있습니다.
이제 페이지를 새로고침하면 다시 로그아웃 상태가 됩니다. 이는 브라우저 세션에서 상태를 초기화하지 않기 때문입니다. 다음으로 이를 어떻게 처리하는지 살펴보겠습니다.
For help and discussion
Comments on this chapter