Next.js로 페이지 라우팅 및 로그인 구현하기

이준석·2021년 10월 10일
6

Web

목록 보기
3/8
post-thumbnail

오랜만에 좋은 노래 하나 가져왔습니다 😉

서론

오늘은 각설하고 빠르게 Next.js 사용법 위주로 포스팅을 다뤄볼 예정이다.
페이지 라우팅 하는 방법에 대해서 알아보고, NextAuth.js 라이브러리를 이용한 로그인 로그아웃 구현에 대해서 살펴볼 예정이다.

바로 시작해보도록 하자!

본론

1. 페이지 정적 라우팅 하기

기존에 React 에서는 페이지 라우팅을 Route 를 이용해서 다음과 같이 코딩을 해주었다.

import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import { Home, About } from 'pages';


class App extends Component {
    render() {
        return (
            <div>
                <Route exact path="/" component={Home}/>
                <Route path="/about" component={About}/>
            </div>
        );
    }
}

export default App;

하지만 Next.js에서는 이런 부분도 귀찮다고 느껴졌는지 페이지 라우팅에 대해서 더욱 더 단순화시켰다. 바로 pages 폴더 밑에 파일만 생성하면 자동으로 라우팅을 설정해준다.

무슨소리인지 모르겠다면 바로 따라해보도록 하자. 먼저 저번 시간에 create-next-app 으로 생성한 프로젝트를 실행시켜보도록 하자.

그러면 기본적으로 index.tsx 파일이 하나 있는데 해당 파일은 그대로 두고 user.tsx 파일을 pages 폴더 하위에 생성해보도록 하자. 그러면 다음과 같이 파일이 되었을 것이다.

그리고 user.tsx 파일에는 다음과 같이 작성해보도록 하자.

const User = () => {
    return (
        <h2>유저 화면 입니다.</h2>
    )
}

export default User;

그리고는 npm run dev로 서버를 실행시켜본다. 서버가 정상적으로 실행되었으면 다음 URL로 접속해볼 수 있도록 하자.

https://localhost:3000/user

그러면 다음과 같이 화면이 출력 될 것이다.

따라서 다시 살펴보면 pages 하위에 파일을 생성하면 해당 파일의 이름으로 라우팅이 자동으로 설정된다. 그렇기 때문에 <Route/>를 일일히 생성해주지 않고 파일을 생성하는 것만으로도 라우팅이 설정되기 때문에 더욱 편하게 코드를 작성할 수 있다.

추가로 현재는 pages 폴더가 루트 디렉토리에 생성되어 있지만 src 폴더를 생성하고 하위에 pages 폴더를 생성해도 Next.js의 기능을 고스란히 사용할 수 있다. 링크 참고

그러면 URL 계층 구조를 조금 더 세분해서 가져가기 위해서 어떻게 해야되는가?
바로 디렉토리를 생성해주면 디렉토리명이 경로로 설정이 된다. 예를 들면 다음과 같다.

pages > my > name > is > junsugi.tsx

const Junsugi = () => {
    return (
        <h1>My name is Junsugi</h1>
    )
}
export default Junsugi;

이렇게 작성하면 URL 접근을 어떻게 하면 될까요? 바로 https://localhost:3000/my/name/is/junsugi 로 입력하면 다음 화면을 만나볼 수 있다.

그럼 정적 라우팅이 있으면 동적 라우팅도 있지 않을까? 동적 라우팅도 당연히 존재한다. 이 부분도 살펴보도록 하자.

2. 페이지 동적 라우팅 하기

동적 라우팅도 간략하게 폴더와 파일을 이용해서 진행하면 된다. 대신 하나 규칙이 존재하는데 파일명을 다음과 같이 작성해주어야 한다.

[파일명].tsx
ex) [name].tsx

이렇게 작성하면 URL을 동적으로 라우팅 할 수 있다. 백문이불여일견이다. 바로 사용해보도록 하자.

아까전에 생성한 my > name > is 폴더 밑에 junsugi.tsx 파일의 이름을 [name].tsx로 변경할 수 있도록 한다. 생성이 완료되면 다음과 같은 파일 구조가 된다.

그리고 동일한 주소로 접속해도록 하자. (http://localhost:3000/my/name/is/junsugi)

위의 GIF를 보면 신기하게 뒤에 어떤 값을 작성하든지 동일한 페이지에 접속이 된다.

여기서 동적 라우팅의 강력한 기능이 들어나게 되는데, 정적 라우팅은 하나의 URL로 하나의 화면만 볼 수 있는 반면 동적 라우팅을 이용하면 하나의 화면으로 다양한 값을 보여줄 수 있다.

GIF를 보면 동일한 화면만 나오는데 무슨 소리인지 모르겠다? 바로 따라서 코딩을 해보자.
먼저 들어가기 전에 useRouter 라는 Hook(훅)을 이용하면 된다.

[name].tsx 파일을 열어서 다음과 같이 코드를 수정한다.

import {useRouter} from "next/router";

const Name = () => {
    
    // 추가된 내용
    const router = useRouter();
    const { name } = router.query;
    
    return (
        <h1>My name is {name}</h1>
    )
}

export default Name;

그리고 GIF와 동일하게 URL 주소를 변경하면서 화면을 볼 수 있도록 하자.

이제 설명을 덧붙이자면 useRouter 라는 훅은 라우터에 접근할 수 있는 Object를 반환해주면서 동적으로 바뀌는 URL의 쿼리 값을 받아 볼 수 있도록 도와준다. (자세한 내용은 링크 참고)

따라서 파일명을 [name] 이라고 해주었는데 query에서 값의 key값이 name으로 저장되어있다. 그렇기 때문에 name으로 값을 받을 수 있도록 해준 것이다. 그리고 두가지 방식으로 값을 받을 수 있다.

1. const { name } = router.query;
2. const anyValueName = router.query.name;

그러므로 보통 동적 라우팅에 회원 ID 값을 받아서 하나의 페이지로 다양한 회원의 정보를 받아 볼 수 있도록 할 수 있다. (동적 라우팅이 없으면 라우팅 방식으로 화면을 보여주고자 한다면 회원이 추가될 때 마다 파일도 하나씩 추가되어야 하는 단점이 있다.)

이런 방식을 사용하면 일단 페이지 생성하고 라우팅 하는건 문제 없이 할 수 있을 것이다.

2. NextAuth.js 를 이용한 로그인 구현

NextAuth Npm 홈페이지
NextAuth 공식 홈페이지
(우선 NPM 홈페이지에서 간략하게 정보를 보고 필요에 따라 공식 문서 보는 것을 권해드리겠습니다.)

두번째로 로그인을 구현하고자 하는데 물론 jsonwebtoken 이나 jwt와 같은 모듈을 다운로드 받아서 로그인을 수동으로 구현할 수도 있지만 Next.js에서 로그인을 편리하게 할 수 있도록 지원하는 라이브러리가 있어서 소개하고자 가져와보았다.

로그인이 어떤 방식으로 인증이 이루어지는지는 뒤에 포스팅에서 기회가되면 설명해도록 하고 지금은 NextAuth.js 사용법에 대해서 소개를 해보겠다.

우선 NextAuth.js 를 사용하기 위해서 패키지를 다운로드 받아야 하는데 명령은 다음과 같다.

npm install --save next-auth
npm install -D @types/next-auth	// typescript 에서도 사용할 수 있도록 지원해주는 모듈

패키지 다운로드가 끝나면 로그인 인증을 처리할 파일을 생성해야 되는데 아래와 같이 디렉토리와 파일을 생성할 수 있도록 한다.

pages > api > auth > [...nextauth].ts

파일을 생성하면 다음과 같은 디렉토리 구조가 만들어진다.

해당 디렉토리 명과 파일명은 고정으로 가져갈 수 있도록 한다. 변경되면 NextAuth 모듈에서 인식하지 못해 정상적으로 사용 할 수 없다..!! (api 폴더에 대해서눈 추후 설명)

우리는 우선 이메일과 패스워드를 입력하면 사용자 인증하는 방식에 대해서 알아보도록 하자.
(NextAuth에서 제공하는 로그인 리스트는 다음 링크를 참고)

공식홈페이지 Docs에 보면 Provider라는 카테고리가 있다. 해당 부분에 현재 지원하는 로그인 방식이 있는데 우리는 Credential을 이용해서 Form에 입력된 텍스트를 가지고 인증하는 방식을 해 볼예정이다.

[...nextauth].ts 을 열고 다음과 같이 작성할 수 있도록 한다.

import NextAuth from "next-auth"
import Providers from "next-auth/providers"
import {NextApiRequest} from "next";

export default NextAuth({
    // 로그인 인증 방식 설정하기
    providers: [
        // 이메일과 패스워드 입력으로 인증하겠다.
        Providers.Credentials({
            // 해당 인증 방식의 이름은 " " 이다.
            name: "email-password-credential",
            // nextAuth에서 자동으로 Form을 만들어주는데
            // 해당 Form에 들어갈 내용을 입력한다. (이따가 화면을 보면 이해된다.)
            credentials: {
                email: { label: "Email", type: "email", placeholder: "test@test.com" },
                password: { label: "Password", type: "password" }
            },
            // Sign up 버튼을 누르면 들어오는 함수
            // 해당 부분에서 들어온 데이터를 가지고 인증을 진행하면 된다.
            // (지금은 무조건 인증되는 방식으로 처리되어있음)
            async authorize(credentials: Record<any, any>, req: NextApiRequest){
                return credentials;
            }
        })
    ],
})

주석으로 설명을 대체하도록 하고 NextAuth에 대한 설정은 90프로 하였다. 이제는 로그인 화면을 만들어보도록 하겠다. 로그인 화면은 index.tsx 에 만들어 보겠다.

index.tsx 파일을 열고 다음과 같이 화면을 채워준다.

import { useSession, signIn, signOut } from "next-auth/client"

const Login = () => {
    const [session, loading] = useSession();
    if (session) {
        return (
            <>
                Signed in as {session.user.email} <br />
                <button onClick={() => signOut()}>Sign out</button>
            </>
        )
    }
    return (
        <>
            Not signed in <br />
            <button onClick={() => signIn()}>Sign in</button>
        </>
    )
}

export default Login;

위의 코드를 간략하게 설명하면 NextAuth 에서 제공해주는 useSession을 이용해서 세션이 있는지 (로그인 되었는지) 확인을 하고 로그인 되었으면 로그인된 이메일을과 로그아웃 버튼을 보여주고, 세션이 없으면 (로그인이 안되어있으면) 로그인 안되었다는 텍스트와 로그인 버튼을 보여주는 코드입니다.

session.user.email 코드에서 빨간줄 에러가 나는데 그 이유는 session 객체가 undefined 일 수도 있는데 코드를 사용하기 때문에 나는 에러입니다. 일단은 무시하고 진행하셔도 됩니다.

(if문으로 session 존재 여부 체크를 진행해주었는데도 발생하는데, 해당 문제는 해결되면 추가하도록 하겠습니다. 저도 아직 typescript는 초보라..😅)


++ 추가내용 : tsconfig.json 에서 strict 모드를 false로 바꿔주면 빨간줄은 해결됩니다..^^ 일단은 임시방편으로 이렇게 해줍시다..😅

그리고 http://localhost:3000 으로 접속해보면 다음과 같은 화면이 뜹니다.

지금 npm run dev로 실행했기 때문에 저장 버튼을 누르면 코드가 자동으로 반영됩니다.

Sign in 버튼을 클릭하면 Form 화면이 나오는데 아까 [...nextauth].ts 에서 Form을 자동으로 생성해준다는 말이 바로 이 말이다. 따라서 아까 credentials 에 정의한 내용대로 Form이 생성되는 것이다.

그럼 간단하게 위에 아무 이메일과 패스워드를 입력하고 Sign in 버튼을 눌러볼 수 있도록 한다.

그러면 다음과 같이 로그인에 사용한 이메일 정보로 업데이트가 되고 Sign out 버튼으로 바뀌게 된다. (로그아웃은 따로 구현이 없고 해당 버튼을 누르면 자동으로 로그아웃이 된다! 너무 간편하다~!)

우선은 이정도로만 넘어가고 다음 포스팅에서 NextAuth 사용에 대해서 조금 더 자세하게 다뤄보도록 하자.

결론

Next.js를 사용하기 위한 첫걸음을 오늘 딛뎌보았는데, 확실히 React 만을 이용해서 개발할 때 보다는 개발자가 해줘야하는 설정들이 적다는 것을 느꼈다. 물론 이 부분이 단점으로 다가올 수도 있지만 현재까지는 크게 어려움을 느껴본 적은 없다.

다음 포스팅에서는 NextAuth에 대해서 조금 더 알아보도록 하고, 이제는 본격적으로 Next.js를 사용하는 이유인 SSR 렌더링을 사용할 수 있는 코드들에 대해서 알아보도록 하겠다.

길고 두서 없는 글 읽어 주셔서 감사하고 빠른 시일내에 포스팅 할 수 있도록 하겠습니다.

감사합니다.

profile
호주 워홀중

0개의 댓글