function aaa(){
console.log("저는 aaa에요")
return function bbb(){
console.log("저는 bbb에요")
}
}
위 코드의 결과는 콘솔에 "저는 aaa에요"만 출력이 되고 반환값으로 bbb함수가 있을 것이다.
"저는 bbb에요"를 출력하려면 bbb함수를 호출을 해주어야 콘솔에서 확인할 수 있다. bbb까지도 실행하는 방법은 aaa()()로 적어주면 된다.
이렇게 실행하면 콘솔에 aaa,bbb 모두 출력된 것을 볼 수 있다.
이를 조금 더 자세히 알아보면
function aaa(){
const apple = 10
return function bbb(){
const banana = 5
console.log(banana)
console.log(apple)
}
}
aaa()()
// 실행 결과
// 5
// 6
위의 함수는 파라미터를사용하여 조금 더 간경하게 바꿀 수 있다.
// 함수 선언식
function aaa(apple){
return function bbb(banana){
console.log(banana)
console.log(apple)
}
}
aaa(2)(3)
// 실행 결과
// 2 => aaa에 넣은 인자값
// 3 => bbb에 넣은 인자값
이렇게 각 변수를 함수의 파라미터로 넘기게 되면, 실행 시 넘겨준 인자값으로 콘솔이 출력된다.
bbbdp apple이 없음에도 불구하고 받아오는 이유는 클로저 때문이다.
위의 함수는 아래와 같이 화살표 함수로도 표현이 가능하다.
// 화살표 함수로 변경
const aaa = (apple)=>{
return (banana)=>{
console.log(apple)
console.log(banana)
}
}
aaa(2)(3)
이렇게 화살표 함수로 바꿔줄 수 있고, 여기서 중괄호와 리턴 사이에 아무것도 없다면 중괄호를 생략해서 적을 수 있다.
최종적으로는 아래와 같은 모양으로 된다.
// 중괄호 생략
const aaa = (apple)=>(banana)=>{
console.log(apple)
console.log(banana)
}
aaa(2)(3)
HOC는 Higher Order Component로 권한분기에서 배운 클로저로부터 확장된 개념이다.
HOC는 상위에 있는 컴포넌트로 다른 컴포넌트보다 먼저 실행되는 컴포넌트라고 생각하면 된다.
Aaa컴포넌트의 HOC(Bbb)({qqq:"철수"})를 보면 HOF에서 배웠던 함수를 리턴하는 함수의 호출방법과 비슷하다.
즉, Bbb
부분에는 apple
이 들어왔고, {qqq:"철수"}
부분에는 banana
가 들어와있었다. 그리고 이를 참고하여 먼저 실행할 컴포넌트를 보면
HOC 함수의 매개변수(parameter) 부분에 component가 들어와 있다.
component 파라미터
에 들어올 컴포넌트는 Bbb컴포넌트
가 된다.
그리고 HOC함수에서 리턴되고 있는 함수를 보면, 리턴 함수의 매개변수
로 props가 들어가 있고 해당 props
에는 함수 호출 시 넣어준 인자값인 {qqq:"철수"}
가 들어오게 된다.
밑으로 내려와 익명함수의 리턴값을 보면 내부에 컴포넌트가 없음에도 불구하고 컴포넌트를 리턴하고 있다. 이는 클로저로 외부의 컴포넌트를 가지고 올 수 있기 때문에 사용이 가능하다.
위에서 배운 HOC 원리를 바탕으로 권한을 체크하는 HOC를 직접 만들 수 있다. 권한을 체크하는 컴포넌트는 어디든 사용될 수 있기 때문에 필요에 따라 따로 분리하여 관리해주면 편하다. (우리는 commons에 만들기로..)
// src/components/commons/hoc/withAuth.tsx 파일
export const withAuth = (Component:any)=>(props:any)=>{
const router = useRouter()
//loginCheckSuccess 파일에 있는 useEffect를 가지고 오시면 됩니다.
useEffect(()=>{
if(!localStorage.getItem("accessToken")){
alert("로그인을 먼저 해주세요")
void router.push("/로그인 페이지")
}
},[])
return <Component {...props} />
}
🚀 HOC를 만들었는데 에러가 나요!
→ eslint 문제일 가능성이 큽니다!
eslint로 가서 rules에 “react/display-name”: “off” 이렇게 써주면 대부분의 문제가 해결이 된다.🚀 이렇게 꺼도 Component와 props부분의 에러는 해결 되지 않아요!
→ Component와 props부분은 generic을 배워야 해결되는거니 지금은 잠시 넘어가기!
위와 같이 권한체크 HOC를 만들었다면 아래처럼 적용하고 싶은 페이지에 적용해주면 된다.
// loginSuccessPage -> withAuth 적용하기
const LoginSuccessPage = ()=>{
const {data} = useQuery(FETCH_USER_LOGGED_IN)
return <div>{data?.fetchUserLoggedIn.name}님 환영합니다.</div>
}
export default withAuth(LoginSuccessPage)
적용하는 방법은 위와같이 필요한 컴포넌트에 withAuth를 감싸서 export를 해주시면 된다.
이렇게 권한을 체크하는 Hoc를 만들어주고 필요한곳에 사용해주면 해당 컴포넌트가 실행되기 이전에 권한체크 컴포넌트가 먼저 실행된다.