그게 SWR이 아니라 get Server Side Propos 장면이면...

20838 단어 Next.jsSWRtech
Next.js 제작 전단 프로젝트에서 SWR을 가져올 때'SWR이나 get Server Side Propos에서 도대체 어느 방향으로 데이터를 얻는 것이 좋을까'라는 의견이 있어서 팀에서 방침을 정할 때 생각해 봤습니다.
전단의 구성에 대해 일반적인 구조는 후단의 REST API를 두드려서 데이터를 얻고 갱신하는 것이다.다만 세션의 유무를 보면서 페이지를 나누거나 API를 취득하는 형태로 사용자의 인증이 필요하다.인증 섹션은 AWS의 Cognito이며 클라이언트는 next-auth를 사용합니다.

데이터 취득 방침


데이터의 취득과 업데이트에 관하여 기본적으로 SWR을 채택하였다.SWR에 관해서는 잘 알려진 바와 같이 캐시 기구에서 데이터를 고속으로 표시할 수 있기 때문에 사용하지 않는 방법이 없다.
또한, 넥스트-auuthuseSession를 사용하여session(안에 포함된 token)의 유무를 검증한 후fetcher를 실행하여 API 호출을 진행하였기 때문에 SWR와 합칠 때 클라이언트 측에서 완성getServerSideProps할 수 있고,gudagda서를 사용하지 않고 데이터 취득 중과 후의 구성 요소의 분리를 진행할 수 있다.
그럼 모두 SWR로 갑시다!하지만...

SWR 안 어울리는 장면.


다음 인증 후 페이지의 분류는 클라이언트에서 처리하지 않는 것이 좋습니다getServerSideProps.
  • 사용자가 응용 프로그램/auth에서 로그인하여Cognito의 페이지로 인증
  • 어플리케이션으로 리디렉션/auth
  • 세션이 있고 사용자 프로필이 있는 경우/
  • 세션이 있고 프로필이 없는 경우/auth/signup
  • 이상의 절차에서 코그니토에서 온 리셋으로 다시 열기 /auth 때문에 다시 페이지를 읽습니다.
    여기서 다음과 같이 SWR을 통해 간단한 파일을 얻고 유무를 확인하여 방향을 바꾸면 한순간/auth 페이지가 나타나고 프로필을 얻지 못하고 리바이벌을 기다리기 전에 예상치 못한 UI를 표시하기 위해 방향을 바꾸면 달려온다.
    // 🙅‍♂️
    const AuthPage: NextPage = () => {
      const { data: session } = useSession();
      const router = useRouter();
      
      const { data: profile, error: profileError } = useSWR(['process.env.ENDPOINT_URL' + '/users/profile', session?.accessToken], fetcher);
      
      useEffect(() => {
        if (!profile) router.push('/auth/signup');
        if (session && profile) router.push('/')
      }, [session, profile, router]);
      
      // ~~~
    
    }
    
    따라서 다음과 같다getServerSideProps.또한 Redirect의 지점을 늘리는 것은 번거롭기 때문에 코그니토 페이지에서 온 Redirect 목적지/auth/signup로 변경되었습니다.
    // 🙆‍♂️
    const Signup: NextPage = () => {
      return <SignupPage />;
    };
    
    export default Signup;
    
    export const getServerSideProps: GetServerSideProps = async (context) => {
      const session = await getSession(context);
      if (!session) {
        return {
          props: {},
        };
      }
    
      const profile = await fetchProfile(
        process.env.ENDPOINT_URL + '/users/profile',
        session.accessToken
      );
    
      // プロフィールがある場合は / へ
      if (profile.status === 200) {
        return {
          redirect: {
            permanent: false,
            destination: '/',
          },
        };
      }
    
      return {
        props: {},
      };
    };
    
    !
    또한 넥스트-auth를 사용하는 경우 세션이 있는지 없는지를 미리 확인하지 않으면 정보가 유출될 수 있으니 주의해야 한다.( FYI )
    요약하면 모두 SWR로 먼저 쓰는 것이 아니라 리디렉션 등 HTML이 표시되면 좋지 않은 경우의 데이터 취득getServerSideProps으로, 표시된 취득을 SWR로 구분해 사용하도록 지침을 정했다면 길을 잃지 않았을 것이다.

    무료 - fetcher 디자인


    데이터를 취득할 때의 오류와 취득한 데이터의 내용이 오류라는 점에 따라 구분하고자 이런 디자인을 적용했다.
    응답은 스노크.케이스로 되돌아오기 때문에 camelcase-keystype-fest로 값과 유형을 해석합니다.
    export type ReturnFetchProfileType = {
      body: {
        id: number;
        cognito_user_id: string;
        user_name: string;
        age: number;
        gender: string;
        email: string;
        created_at: string;
        updated_at: string;
        profile_image: string;
        profile_description: string;
        following: number;
        followers: number;
      };
    } & Status;
    
    export const fetchProfile = async (
      url: string,
      jwtToken?: string
    ): Promise<CamelCasedPropertiesDeep<ReturnFetchProfileType>> => {
      if (!jwtToken) throw new NoJwtTokenError();
    
      const res = await getFetcher({ url, jwtToken }).catch((err) => {
        throw new ReadSchemaError(err);
      });
    
      const json = await res.json();
      return Promise.resolve({ status: res.status, body: camelcaseKeys(json) });
    };
    
    // getFetcher.ts
    type GetFetcherParams = {
      url: string;
      jwtToken: string;
    };
    
    const getFetcher = ({ url, jwtToken }: GetFetcherParams) => {
      return fetch(url, {
        headers: {
          Authentication: jwtToken,
        },
      });
    };
    
    useSWR로 호출data하면 status로 들어오기 때문에 되돌아오는 데이터가 정상적이거나 이상한지 판단할 수 있다.
    또한 오류도 종류Error에 따라 반을 extends로 만들면 편리하다.
    export class ReadSchemaError extends Error {
      public info: ExtendableObject;
      public status: number;
    
      constructor(...params: ErrorParamsTuple) {
        super(...params);
    
        this.info = {};
        this.status = 0;
      }
    }
    
    export class NoJwtTokenError extends Error {
      public info: ExtendableObject;
      public status: number;
    
      constructor(...params: ErrorParamsTuple) {
        super(...params);
    
        this.info = { message: 'No jwt token.' };
        this.status = 0;
      }
    }
    

    좋은 웹페이지 즐겨찾기