Authorization은 직역하면 권한 부여 정도가 되는데, 인증(authentication)과는 조금 다른 개념이다. 로그인이 인증이라면, 사용자 (ex. 관리자 / 유저 / 게스트(로그인 x))에 따라 접근할 수 있는 페이지를 다르게 하는 것이 Authorization이라고 할 수 있다.
어떤 페이지에 Authorization을 적용한 것을 pseudo-code로 표현하자면 이렇다.
const UserPage = () => {
const 유저레벨 = 유저정보가져오기();
if (유저레벨 === 게스트) {
// 로그인 페이지
return;
}
if (유저레벨 === 관리자) {
// 관리자 전용 유저 페이지
return;
}
// 일반 유저 페이지
return;
}
유저정보가져오기()는 주로 전역 상태 또는 사용자 정보를 요청하는 hook일 가능이 높다. 따라서 유저레벨이 아직 확인되지 않은 initial value로 컴포넌트가 마운트되는 경우가 생긴다.
ex) 페이지 새로고침 / URL 직접 입력해서 접근할 경우
유저레벨에 따라 다른 화면을 보여주는 방식이 다양할 수 있다. 이를테면 컴포넌트를 리턴할 수도 있고, url을 변경하여 사용자를 강제로 이동시킬 수도 있다. 각각의 방법에는 문제가 뒤따른다.
ex) 페이지 컴포넌트 리턴 -> 주소와 실제 보여지는 컴포넌트가 다름 / 강제 이동 -> UX 좋지 않음
위 로직을 권한이 필요한 페이지마다 추가해줘야 한다. 그리고 페이지마다 필요한 권한이 다를 수 있다.
아예 권한이 없음을 보여주는 페이지를 따로 만들어 이동시킨 뒤, 해당 페이지에 홈이나 로그인 페이지로의 링크를 넣는 것도 대안이 될 수 있다.
a higher-order component is a function that takes a component and returns a new component
여기서는 컴포넌트를 인자로 받아서 검증 로직을 적용시켜 리턴한다. 컨벤션상 withAuthorization이라고 이름을 붙여보았다.
단순화한 withAuthorization 코드이다.
import type { ComponentType } from "react";
import type { AccessLevel } from "src/types";
// 기타 import 생략
const withAuthorization = <P extends object>(
WrappedComponent: ComponentType<P>, // 감쌀 컴포넌트
pageAccessLevel: AccessLevel, // 그 외 파라미터들
) => {
// 새로운 컴포넌트를 정의함
const WithAuth = (props: P) => {
// isInitialized: 유저 초기화 여부
const { accessLevel, isInitialized } = useUser();
const router = useRouter();
useEffect(() => {
if (!isInitialized) {
// 유저 초기화(전역 상태 업데이트)
return;
}
}, [isInitialized]);
if (!isInitialized) { // 유저 미확인
return null; // 또는 로딩 중 표시
}
if (accessLevel === 0) { // 게스트
router.push("/login");
return null;
}
if (accessLevel < pageAccessLevel) { // 권한 없음
router.replace("/");
return null;
}
return <WrappedComponent {...props} />;
}
// 위에서 인자로 받은 컴포넌트에 인증 로직을 적용했고,
// 그 새로운 컴포넌트를 리턴한다.
return WithAuth;
}
페이지 컴포넌트에서 이렇게 적용할 수 있다.
import { withAuthorization } from "src/hocs";
import { PageAccess } from "src/config";
// 마이페이지
const MyPage = (props: MyPageProps) => {
// ...
}
export default withAuthorization(MyPage, PageAccess.User);
nextjs에서는 물론 그냥 react에서도 같은 방식으로 Authorization을 구현할 수 있다.