๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Next.js

[๋‚ด๋ณด๋‚ด๋ฒˆ] Next.js docs - Authentication

๋‚ด๋ณด๋‚ด๋ฒˆ(๋‚ด๊ฐ€ ๋ณด๋ ค๊ณ  ๋‚ด๊ฐ€ ๋ฒˆ์—ญํ•œ...) Next.js docs

2021๋…„ 8์›” 2์ผ ๊ธฐ์ค€ Next.js ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๋ฒˆ์—ญํ–ˆ๋‹ค.

โ€ป ์˜์–ด ์ „๊ณต์ž๋„ ํ•ด์™ธ ์œ ํ•™ํŒŒ๋„ ์•„๋‹ˆ๊ธฐ์— ๋ฒˆ์—ญ์—๋Š” ์˜์—ญ, ์˜ค์—ญ, ๊ตฌ๊ธ€ ๋ฒˆ์—ญ์ด ๋ฌด์ˆ˜ํžˆ ๋งŽ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ˜ผ์ž ๊ณต์‹๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•ด๊ฐ€๋ฉฐ ๋ฒˆ์—ญํ•˜๋‹ค ๋ณด๋‹ˆ ์˜คํƒ€๋„ ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค. ์ •ํ™•ํ•œ ๋‚ด์šฉ์€ ๊ณต์‹๋ฌธ์„œ๋ฅผ ์ง์ ‘ ์‚ดํŽด๋ณด๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์ •๋ณด๋“ค์„ ๋” ์ฐพ์•„๋ณด๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

(ํ•˜์ง€๋งŒ ๋Œ“๊ธ€ ํ”ผ๋“œ๋ฐฑ๋„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค๐Ÿ˜ƒ )

Next.js ๊ณต์‹๋ฌธ์„œ ํ™•์ธํ•˜๊ธฐ>>

 

Authentication | Next.js

Learn about authentication patterns in Next.js apps and explore a few examples.

nextjs.org

 

Authentication verifies who a user is, while authorization controls what a user can access. Next.js supports multiple authentication patterns, each designed for different use cases. This page will go through each case so that you can choose based on your constraints.

Authentication(์ธ์ฆ)์€ ๋ˆ„๊ฐ€ ์‚ฌ์šฉ์ž์ธ์ง€๋ฅผ ์ฆ๋ช…ํ•˜๋Š” ๋ฐ˜๋ฉด authorization(๊ถŒํ•œ๋ถ€์—ฌ)์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌด์—‡์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ์ œ์–ดํ•œ๋‹ค. Next.js๋Š” ๊ฐ๊ฐ ๋‹ค๋ฅธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์œ„ํ•ด ์„ค๊ณ„๋œ ์—ฌ๋Ÿฌ ์ธ์ฆ ํŒจํ„ด์„ ์ œ๊ณตํ•œ๋‹ค. ์ด ํŽ˜์ด์ง€๋Š” ๋‹น์‹ ์ด ์ž์‹ ์˜ ์ œ์•ฝ์‚ฌํ•ญ์— ๊ทผ๊ฑฐํ•˜์—ฌ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐ ์‚ฌ๋ก€๋“ค์— ๋Œ€ํ•ด ์‚ดํŽด๋ณผ ๊ฒƒ์ด๋‹ค. 

Authentication pattern

The first step to identifying which authentication pattern you need is understanding the data-fetching strategy you want. We can then determine which authentication providers support this strategy. There are two main patterns:

  • Use static generation to server-render a loading state, followed by fetching user data client-side.
  • Fetch user data server-side to eliminate a flash of unauthenticated content.

์ž์‹ ์—๊ฒŒ ์–ด๋–ค ์ธ์ฆ ํŒจํ„ด์ด ํ•„์š”ํ•œ์ง€๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ๋‹น์‹ ์ด ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํŒจ์นญ ์ „๋žต์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋‹ค์Œ ์ด ์ „๋žต์„ ์ง€์›ํ•˜๋Š” ์ธ์ฆ ์ œ๊ณต์ž๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜๋Š” ๋‘ ๊ฐ€์ง€ ์ฃผ๋œ ํŒจํ„ด์ด๋‹ค: 

  • ์ •์  ์ƒ์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ์„œ๋ฒ„ ๋ Œ๋”๋ง ํ•˜๊ณ  ๋’ค์ด์–ด ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธ์ธ  ์ธก์—์„œ ๊ฐ€์ ธ์˜ด
  • ์ธ์ฆ๋˜์ง€ ์•Š์€ ์ปจํ…์ธ ์˜ ๊นœ๋ฐ•์ž„์„ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ์„œ๋ฒ„ ์ธก์—์„œ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด

 

Authenticating Statically Generated Pages

Next.js automatically determines that a page is static if there are no blocking data requirements. This means the absence of getServerSideProps and getInitialProps in the page. Instead, your page can render a loading state from the server, followed by fetching the user client-side.

Next.js๋Š” ํŽ˜์ด์ง€์— ์ค‘๊ฐ„์— ๊ฐ€๋กœ๋ง‰๋Š” ๋ฐ์ดํ„ฐ ์š”๊ตฌ์‚ฌํ•ญ์ด ์—†์œผ๋ฉด ์ •์ ์ด๋ผ๊ณ  ์ž๋™์œผ๋กœ ํŒ๋‹จํ•œ๋‹ค. ์ด๊ฒƒ์€ ํŽ˜์ด์ง€์— getServerSideProps์™€ getInitialProps ๊ฐ€ ์—†๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ๋Œ€์‹ ์— ํŽ˜์ด์ง€๊ฐ€ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ๋ Œ๋”๋งํ•˜๊ณ  ๋‚˜์„œ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

One advantage of this pattern is it allows pages to be served from a global CDN and preloaded using next/link. In practice, this results in a faster TTI (Time to Interactive).

์ด ํŒจํ„ด์˜ ์žฅ์  ํ•œ ๊ฐ€์ง€๋Š” ํŽ˜์ด์ง€๋“ค์ด ๊ธ€๋กœ๋ฒŒ CDN์œผ๋กœ๋ถ€ํ„ฐ ์ œ๊ณต๋˜๊ณ  next/link๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ฆฌ๋กœ๋“œ ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ์‹ค์ œ๋กœ ๋” ๋น ๋ฅธ TTI(Time to Interactive)๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. 

Let's look at an example for a profile page. This will initially render a loading skeleton. Once the request for a user has finished, it will show the user's name:

ํ”„๋กœํ•„ ํŽ˜์ด์ง€ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด์ž. ์ด ํŽ˜์ด์ง€๋Š” ์ฒ˜์Œ์— ๋กœ๋”ฉ ์Šค์ผˆ๋ ˆํ†ค์„ ๋ Œ๋”ํ•œ๋‹ค. ์‚ฌ์šฉ์ž์— ๋Œ€ํ•œ ์š”์ฒญ์ด ๋๋‚˜๋ฉด ์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„์„ ๋ณด์—ฌ์ค€๋‹ค. 

// pages/profile.js

import useUser from '../lib/useUser'
import Layout from '../components/Layout'

const Profile = () => {
  // Fetch the user client-side
  const { user } = useUser({ redirectTo: '/login' })

  // Server-render loading state
  if (!user || user.isLoggedIn === false) {
    return <Layout>Loading...</Layout>
  }

  // Once the user request finishes, show the user
  return (
    <Layout>
      <h1>Your Profile</h1>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </Layout>
  )
}

export default Profile

You can view this example in action. Check out the with-iron-session example to see how it works. 

์ด ์˜ˆ์ œ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€๋ฅผ ๋ณด๋ ค๋ฉด with-iron-session ์˜ˆ์ œ๋ฅผ ํ™•์ธํ•ด๋ณด๋ผ. 

 

Authenticating Server-Rendered Pages

If you export an async function called getServerSideProps from a page, Next.js will pre-render this page on each request using the data returned by getServerSideProps.

ํŽ˜์ด์ง€์—์„œ getServerSideProps๋ผ๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ exportํ•œ๋‹ค๋ฉด, Next.js๋Š” ์ด ํŽ˜์ด์ง€๋ฅผ ๊ฐ ์š”์ฒญ๋งˆ๋‹ค getServerSideProps์—์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ฆฌ๋ Œ๋” ํ•œ๋‹ค. 

export async function getServerSideProps(context) {
  return {
    props: {}, // Will be passed to the page component as props
  }
}

Let's transform the profile example to use server-side rendering. If there's a session, return user as a prop to the Profile component in the page. Notice there is not a loading skeleton in this example.

ํ”„๋กœํ•„ ์˜ˆ์ œ๋ฅผ ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์œผ๋กœ ๋ฐ”๊ฟ”๋ณด์ž. ์„ธ์…˜์ด ์žˆ๋‹ค๋ฉด ํŽ˜์ด์ง€์˜ Profile ์ปดํฌ๋„ŒํŠธ์— ์‚ฌ์šฉ์ž๋ฅผ prop์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋ผ. ์ด ์˜ˆ์ œ์—์„œ๋Š” ๋กœ๋”ฉ ์Šค์ผˆ๋ ˆํ†ค์ด ์—†๋‹ค๋Š” ๊ฒƒ์— ์œ ์˜ํ•˜๋ผ. 

// pages/profile.js

import withSession from '../lib/session'
import Layout from '../components/Layout'

export const getServerSideProps = withSession(async function ({ req, res }) {
  // Get the user's session based on the request
  const user = req.session.get('user')

  if (!user) {
    return {
      redirect: {
        destination: '/login',
        permanent: false,
      },
    }
  }

  return {
    props: { user },
  }
})

const Profile = ({ user }) => {
  // Show the user. No loading state is required
  return (
    <Layout>
      <h1>Your Profile</h1>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </Layout>
  )
}

export default Profile

An advantage of this pattern is preventing a flash of unauthenticated content before redirecting. It's important to note fetching user data in getServerSideProps will block rendering until the request to your authentication provider resolves. To prevent creating a bottleneck and decreasing your TTFB (Time to First Byte), you should ensure your authentication lookup is fast. Otherwise, consider static generation.

์ด ํŒจํ„ด์˜ ์žฅ์ ์€ ๋ฆฌ๋‹ค์ด๋ ‰ํŒ… ์ „์— ์ธ์ฆ๋˜์ง€ ์•Š์€ ์ปจํ…์ธ ์˜ ๊นœ๋ฐ•์ž„์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. getServerSideProps์—์„œ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์€ ์ธ์ฆ ์ œ๊ณต์ž์— ๋Œ€ํ•œ ์š”์ฒญ์ด ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ๋ Œ๋”๋ง์ด ์ฐจ๋‹จ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„๋‘๋Š” ๊ฒƒ์€ ์ค‘์š”ํ•˜๋‹ค. ๋ณ‘๋ชฉ๊ตฌ๊ฐ„์ด ์ƒ๊ธฐ๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ณ  TTFB๋ฅผ ์ค„์ด์ง€ ์œ„ํ•ด์„œ๋Š” ์ธ์ฆ ์กฐํšŒ๊ฐ€ ๋น ๋ฅธ์ง€ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์ •์  ์ƒ์„ฑ์„ ๊ณ ๋ คํ•ด๋ณด๋ผ. 

 

Authentication Providers

Now that we've discussed authentication patterns, let's look at specific providers and explore how they're used with Next.js.

์ง€๊ธˆ๊นŒ์ง€ ์ธ์ฆ ํŒจํ„ด์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐ ๋‚˜๋ˆ„์–ด๋ดค๋‹ค. ์ด์ œ ํŠน์ • ์ œ๊ณต์ž์— ๋Œ€ํ•ด์„œ Next.js์™€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž. 

Bring Your Own Database

Examples

If you have an existing database with user data, you'll likely want to utilize an open-source solution that's provider agnostic.

  • If you want a low-level, encrypted, and stateless session utility use next-iron-session.
  • If you want a full-featured authentication system with built-in providers (Google, Facebook, GitHub…), JWT, JWE, email/password, magic links and more… use next-auth.

์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด ๊ณต๊ธ‰์ž์— ๊ตฌ์• ๋ฐ›์ง€ ์•Š๋Š” ์˜คํ”ˆ์†Œ์Šค ์†”๋ฃจ์…˜์„ ํ™œ์šฉํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ด๋‹ค.

  • low-level, ์•”ํ˜ธํ™”๋˜์–ด์žˆ๊ณ , ๋ฌด์ƒํƒœ์„ฑ ์„ธ์…˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์›ํ•œ๋‹ค๋ฉด next-iron-session์„ ์‚ฌ์šฉํ•˜๋ผ. 
  • ๋‚ด์žฅ๋œ ์ œ๊ณต์ž(๊ตฌ๊ธ€, ํŽ˜์ด์Šค๋ถ, ๊นƒํ—™...), JWT, JWE, ์ด๋ฉ”์ผ/์•”ํ˜ธ, ๋งค์ง ๋งํฌ์™€ ๊ทธ ๋ฐ–์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ์ธ์ฆ ์‹œ์Šคํ…œ์„ ์›ํ•œ๋‹ค๋ฉด next-auth๋ฅผ ์‚ฌ์šฉํ•˜๋ผ. 

Both of these libraries support either authentication pattern. If you're interested in Passport, we also have examples for it using secure and encrypted cookies:

๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋‘ ์œ„์—์„œ ์‚ดํŽด๋ณธ ๋‘ ๊ฐ€์ง€ ์ธ์ฆ ํŒจํ„ด์„ ์ œ๊ณตํ•œ๋‹ค. Passport์— ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด secure, ์•”ํ˜ธํ™”๋œ ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ œ๋„ ์žˆ๋‹ค. 

Other Providers

To see examples with other authentication providers, check out the examples folder.

๋‹ค๋ฅธ ์ธ์ฆ ์ œ๊ณต์ž๋“ค์˜ ์˜ˆ์ œ๋“ค์„ ์‚ดํŽด๋ณด๋ ค๋ฉด examples ํด๋”๋ฅผ ํ™•์ธํ•ด๋ณด๋ผ. 

Examples