Thumbnail
BEST
개발 · 프로그래밍 프론트엔드

Next + React Query로 SNS 서비스 만들기 대시보드

(4.6)
34개의 수강평 ∙  2,201명의 수강생

69,300원

지식공유자: 조현영
총 75개 수업 (14시간 46분)
수강기한: 
무제한
수료증: 발급
난이도: 
입문
-
초급
-
중급이상
지식공유자 답변이 제공되는 강의입니다
폴더에 추가 공유
조현영 프로필
10기 타임어택 시작합니다!
조현영 23일 전 (23일 전 수정됨)

벌써 타임어택을 9번이나 진행했네요. 이번에는 타임어택 프로그램 10기 진행합니다! 10기는 4월 22일부터 시작합니다.

강좌는 구매했는데 매번 끝까지 못 보시는 분들을 위한 프로그램입니다. 무료로 참가하실 수 있으며 의지력이 많이 부족한 분들을 위해 따로 보증금 제도도 운영하고 있습니다. 이전 기수 분들이나 같은 기수 분들의 정리 노트를 보면서 공부하실 수도 있고, 저나 다른 분들에게 질문을 할 수도 있습니다.

타임어택을 참여하신 분들의 완강률이 훨씬 높았습니다. 진짜 꼭 강의를 완강해야겠다고 다짐하셨다면 참여하시면 도움이 많이 될 것입니다!

  • 참고로 강의는 인프런에서 저를 검색해서 구매하시기보다는 https://zerocho.com/lecture 의 링크 눌러서 구매해주시면 제가 내는 수수료가 많이 줄어듭니다. 부탁드려요 ㅎㅎ

     

완주하시면 강좌 쿠폰(35~60%)이나 만나서 식사권을 드리고 있습니다!

저도 현재 매 기수 적자를 보면서 진행하고 있습니다. 벌써 9기수째 적자... 그럼에도 진행하는 이유는 제 강좌가 실질적으로 여러분들한테 도움이 되기를 바라기 때문입니다. 강좌를 사놓기만 하고 안 들으시는 분이 많은데 정해진 진도와 함께 끝까지 들으시고 여러분의 개발 실력이 향상되었으면 해서 매번 진행 중입니다. 저는 제 강좌가 도움이 되었다는 말을 들을 때 가장 뿌듯하거든요. 타임어택에서 나오는 강좌 피드백을 바탕으로 강좌를 조금씩 수정하고도 있어 저에게도 도움이 되고요.

슬랙에서 진행하기 때문에 슬랙 방 참가해주셔야 합니다. 아래 슬랙 링크로 들어오세요.

https://zerocho.com/slack

들어오시면 공지 채널에 10기 참여 설문 조사(구글 폼)가 있습니다. 작성하시면 됩니다. 링크도 따로 같이 올려드립니다.

https://forms.gle/Qu5XZ7uNoCyUnugp6

설문 조사를 작성하지 않으셨더라도 저한테 DM을 보내서 알려주시면 참가하실 수 있습니다.

타임어택 프로그램에 참여하지 않으시더라도 슬랙 방에 참여하시면 긱뉴스 등의 정보 공유도 하고 프로그래밍 질문 고민 상담도 하고 여러 모로 도움되실 거에요. 벌써 3000분 정도 들어계십니다!

감사합니다.

조현영 프로필
next-auth 서버 에러 받기 & session에 커스텀 데이터 넣기 & 권한에 따라 페이지 접근하기
조현영 1달 전 (1달 전 수정됨)

안녕하세요. 제로초입니다.

많은 분들이 next-auth에서 한 번 고통을 겪어보셨을 것 같은데요. 아직 베타라서 그동안 좀 불안정한 게 많았으나 이제야 좀 잡혀가는 듯합니다. 그래서 강의에서는 아직 기능이 없어 다루지 못했다가 추가된 것들 세 가지를 소개해드리겠습니다.

signIn시 프론트에서 서버 에러 받기

로그인 시 서버에서는 다양한 에러를 줄 수 있습니다. 예를 들어 1. 유저가 없는 경우 2. 비밀번호가 틀린 경우 3. 기타 등등. 그런데 이런 걸 프론트에 넘겨야 상황에 맞는 메시지를 표시할 것 아니겠습니까? 근데 이 기본적인 기능이 지금까지 없다가 이제야 추가되었습니다.

auth.ts에서 다음과 같이 수정합니다.

import NextAuth, {CredentialsSignin} from "next-auth"
...
providers: [
  CredentialsProvider({
    async authorize(credentials) {
      const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, {
        ...
      })
      // 여기 주목!!! 서버에서 에러가 발생할 때 그 에러 내용이 서버에 담겨 있을 겁니다.
      console.log(authResponse.status, authResponse.statusText)
      if (!authResponse.ok) {
        const credentialsSignin = new CredentialsSignin();
        if (authResponse.status === 404) {
          credentialsSignin.code = 'no_user';
        } else if (authResponse.status === 401) {
          credentialsSignin.code = 'wrong_password';
        }
        throw credentialsSignin;
      }

      const user = await authResponse.json()
      console.log('user', user);
      // id, name, image, email만 허용
      return {
        id: user.id,
        name: user.nickname,
        image: user.image,
      }
    },
  }),
]

이제 return null 하지말고 CredentialsSignin 에러를 throw 하면 됩니다. 에러의 속성인 code에 에러 메시지를 적으면 되는데 여기의 코드를 프론트에서 받으려면 signIn 부분을 redirect: true로 만들어주어야 합니다. redirect: false면 무조건 response.ok가 true면서 에러 정보는 없습니다.

const response = await signIn("credentials", {
  username: id,
  password,
  redirect: true, // true!!!
})

이렇게 바꾸면 이제 로그인 실패 시 페이지가 리다이렉트되면서 쿼리스트링으로 에러 코드가 같이 나오게 됩니다.

image새로고침이라 불편하긴 하지만 next.js에는 useSearchParams()라는 쿼리스트링 조회 훅이 있으므로 code 값을 가져올 수 있고 화면에 code에 따른 메시지를 표시할 수 있습니다. redirect가 된다는 불편함은 있지만 어쨌든 구현은 가능하게 됩니다.

session 객체에 커스텀 데이터 넣기

공식 문서에 따르면 현재 authorize 함수의 return에는 id, email, name, image만 넣을 수 있습니다. 이것만 해도 제한이 큰데 id는 넣을 수 있다고 하면서도 넣으면 useSession()의 데이터에서는 사라져버립니다.

  1. 그럼 id는 어디로 갔냐?

  2. 다른 커스텀 데이터는 어떻게 넣냐?

    하실 수 있는데 다음과 같이 session을 직접 만드실 수 있습니다.

auth.ts

export const {
  handlers: { GET, POST },
  auth,
  signIn,
} = NextAuth({
  pages: {
    signIn: '/i/flow/login',
    newUser: '/i/flow/signup',
  },
  callbacks: {
    async session({ session, token }) {
      console.log('session callback', session, token);
      const authResponse = await fetch(내정보를 가져오는 서버 API);
      const userData = await authResponse.json();
      (session as any).userData = userData;
      return session;
    }
  },
  providers: [
    CredentialsProvider({
      async authorize(credentials) {
        ...
        // id, name, image, email만 허용
        return {
          id: user.id,
          name: user.nickname,
          image: user.image,
        }

이렇게 callbacks 속성에 async session 메서드를 작성하시면 됩니다. 여기 안에서 내 정보를 서버로부터 한 번 더 불러오면 됩니다. 그리고 그 응답값을 session 객체에 넣어서 반환하는 겁니다.

  1. 아까 사라졌던 id는 이 메서드의 token.sub에 들어 있습니다.

  2. 여기서 return하는 값이 auth()나 useSession()의 데이터가 됩니다. authorize에서 return한 값이 최종 값이 아니라 여기서 한 번 더 수정되는 것입니다.

이렇게 하면 auth()나 useSession()에서 user.userData를 확인하실 수 있습니다.

권한에 따라 페이지 접근하기

이제 session 객체에 커스텀 데이터를 넣을 수 있게 되었으므로 권한에 따라 페이지를 접근할 수 있습니다. callbacks.session async 함수에서 role 같은 것을 서버로부터 받아서 넣어주면 됩니다. session.userData.role에 admin 또는 normal 권한이 있다고 칩시다. 그리고 role이 admin인 경우 어드민 페이지(/admin)에 접속 가능하고 normal이면 안 된다고 해봅시다. 이걸 어떻게 구현할 수 있을까요?

현재 middleware.ts는 다음과 같이 되어있는데, 이러면 config에 적은 라우트에서만 실행되므로 config를 전부 제거합니다.

import { auth } from "./auth"
import {NextResponse} from "next/server";

export async function middleware() {
  const session = await auth();
  if (!session) {
    return NextResponse.redirect('http://localhost:3000/i/flow/login');
  }
}

// See "Matching Paths" below to learn more
export const config = {
  matcher: ['/compose/tweet', '/home', '/explore', '/messages', '/search'],
} 

그리고 middleware 함수 내부에 수동으로 작성하면 됩니다. request.nextUrl.pathname에 현재 접근하고자 하는 pathname이 들어있습니다.

import { auth } from "./auth"
import {NextResponse} from "next/server";

export async function middleware() {
  const session = await auth();
  if (['/compose/tweet', '/home', '/explore', '/messages', '/search'].includes(request.nextUrl.pathname) && !session) {
    return NextResponse.redirect('http://localhost:3000/i/flow/login');
  }
}

이렇게 수정한 후 저희는 auth()의 session에서 session.userData.role로 권한에 접근할 수 있으므로 다음과 같이 검사 후 리다이렉트 시키면 됩니다.

import { auth } from "./auth"
import {NextResponse} from "next/server";

export async function middleware() {
  const session = await auth();
  if (['/compose/tweet', '/home', '/explore', '/messages', '/search'].includes(request.nextUrl.pathname) && !session) {
    return NextResponse.redirect('http://localhost:3000/i/flow/login');
  }
  if (request.nextUrl.pathname.startsWith('/admin') && session?.userData.role !== 'admin') {
    return NextResponse.redirect('http://localhost:3000/권한없음_알리는_모달_주소');
  }
}

이렇게 부족한 next-auth를 어떻게서든 활용해볼 수 있습니다.

다음에 또 업데이트 되는 사항이 있으면 알려드리겠습니다. 감사합니다!

다른 댓글 보기(1)
조현영 프로필
라이브러리 버그 관련 문제 해결책 안내
조현영 2달 전 (1달 전 수정됨)

안녕하세요. 제로초입니다.

Next14에 버그가 하도 많다보니 저와 여러분의 속을 썩히고 있습니다. 그나마 다행인 건 시간이 지날수록 조금씩 해결되는 기미가 보입니다. 에러가 날 때마다 어떻게 해야 하는지 AS는 확실하게 해드리겠습니다. 물론 저도 해결 못 하는 에러가 나오면 멘붕에 빠지긴 하지만요.

not-found.tsx 적용문제

https://www.inflearn.com/questions/1192614/not-found-tsx%EB%A1%9C-%EC%9D%B4%EB%8F%99%EC%9D%84-%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94%EB%AC%B8%EC%A0%9C?re_comment_id=321453

not-found.tsx는 커스텀 404 페이지를 담당하는 컴포넌트인데요. not-found.tsx가 적용되지 않는 분들은 [...not-found]/page.tsx를 대신 만들어보시면 됩니다. [...not-found]는 폴더입니다.

msw 한글 응답 문제

https://www.inflearn.com/questions/1181768/%EA%B0%95%EC%9D%98%EC%A4%91%EC%97%90-%EC%A0%95%EB%A7%90-%EA%B6%81%EA%B8%88%ED%95%9C%EA%B2%8C-%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4-mock-data%EC%97%90-%ED%95%9C%EA%B8%80%EC%9D%B4-%EC%9E%85%EB%A0%A5%EB%90%A0-%EA%B2%BD%EC%9A%B0-msw%EC%97%90%EC%84%9C-%EA%B0%92%EC%9D%84-%EB%AA%BB-%EB%B3%B4%EB%83%85%EB%8B%88%EB%8B%A4

이 문제는 msw 2.2.0~2.2.1에서 한글 응답이 안 되는 문제였습니다. msw 2.2.2에서 해결되었습니다. 제가 직접 msw를 수정해서 해결했기 때문에 오픈소스에 기여하는 법 영상도 같이 공유드립니다.

https://www.youtube.com/watch?v=7uxCmXAA5Zw

 

authorize 에러 응답 고정 문제

마지막으로 아직 해결되지 않은 문제도 있습니다.

https://www.inflearn.com/questions/1186659/credentials-provider-%EC%97%90%EC%84%9C-%EC%84%9C%EB%B2%84%EB%A1%9C-%EB%B6%80%ED%84%B0-%EB%B0%9B%EC%95%84%EC%98%A8-error-message%EA%B0%80-%EB%B0%98%ED%99%98%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EA%B2%BD%EC%9A%B0

이 질문인데요. authorize함수에서 무슨 에러를 throw하든 항상 CallbackRouteError만 나는 문제입니다. 이건 버그가 아니라 next-auth에서 그렇게 만들어 둔 것이라 지금 https://github.com/nextauthjs/next-auth/pull/9871 여기에서 논의중인 것으로 보입니다. 이 기능이 통과되어야 커스텀 에러를 throw할 수 있게 됩니다.

해결 되었습니다. 다음 새소식 참고하시면 됩니다.

다른 에러 이슈가 있을 때 또 새소식으로 문제와 해결책 알려드리도록 하겠습니다.

감사합니다.
조현영 드림

조현영 프로필
Next 관련 라이브러리 버그 및 버전 안내
조현영 2달 전 (2달 전 수정됨)

안녕하세요. 수강생 여러분,

msw와 next-auth 도입부터는 버그 때문에 고통받고 계실 것 같습니다. 저도 해결법을 몰라서 고통받고 있습니다. 지금은 버전을 낮추는 방법 뿐입니다.

현재 @auth/core next-auth msw에는 버그가 있기에 버전을 다음과 같이 고정해주세요.

1번 방법

npm i @auth/core@0.19 next-auth@5.0.0-beta.3 msw@2.1

 

2번 방법(더 최신 버전을 쓰고 싶다면)

npm i @auth/core@0.27 next-auth@5.0.0-beta.11 msw@2.1

이렇게 설치하고 .env에서 AUTH_URL을 지웁니다. 그리고 auth.ts에서 NEXT_PUBLIC_BASE_URL을 대신 씁니다. .env에 AUTH_URL을 쓰지 않는 게 핵심입니다.

const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, {

 

아직 msw@2.2의 버그는 해결하지 못했습니다.

https://github.com/mswjs/msw/issues/1658#issuecomment-1953599080

이런 식으로 버그 제기를 하고는 있으나 언제 고쳐질 지는 모르겠습니다. 해결되는대로 다시 공유드리겠습니다. next app router 실무에서는 시기상조라서 올해 초까지는 묵혀두라고 말씀드렸는데요. 6개월 정도 더 묵혀두셔야겠습... 크헉

감사합니다.
조현영 드림.

조현영 프로필
2024년 첫 타임어택 시작합니다!!
조현영 3달 전 (3달 전 수정됨)

먼저 다들 새해 복 많이 받으세요~~

2024년 첫 강좌 타임어택 프로그램 9기 진행합니다!

강좌는 구매했는데 매번 끝까지 못 보시는 분들을 위한 프로그램입니다. 무료로 참가하실 수도 있으며 의지력이 많이 부족한 분들을 위해 따로 보증금 제도도 운영하고 있습니다. 이전 기수 분들이나 같은 기수 분들의 정리 노트를 보면서 공부하실 수도 있고, 저나 다른 분들에게 질문을 할 수도 있습니다.

  • 참고로 강의는 인프런에서 저를 검색해서 구매하시기보다는 https://zerocho.com/lecture에 있는 링크 눌러서 구매해주시면 제가 내는 수수료가 많이 줄어듭니다. 부탁드려요 ㅎㅎ

     

완주하시면 강좌 쿠폰(35~60%)이나 만나서 식사권을 드리고 있습니다!

저도 현재 매 기수 적자를 보면서 진행하고 있습니다.그럼에도 진행하는 이유는 제 강좌가 실질적으로 여러분들한테 도움이 되기를 바라기 때문입니다. 강좌를 사놓기만 하고 안 들으시는 분이 많은데 정해진 진도와 함께 끝까지 들으시고 여러분의 개발 실력이 향상되었으면 해서 매번 진행 중입니다. 저는 제 강좌가 도움이 되었다는 말을 들을 때 가장 뿌듯하거든요. 타임어택에서 나오는 강좌 피드백을 바탕으로 강좌를 조금씩 수정하고도 있어 저에게도 도움이 되고요.

슬랙에서 진행하기 때문에 슬랙 방 참가해주셔야 합니다. 아래 슬랙 링크로 들어오세요.

https://zerocho.com/slack

들어오시면 공지 채널에 9기 참여 설문 조사(구글 폼)가 있습니다. 작성하시면 됩니다. 링크도 따로 같이 올려드립니다.

https://forms.gle/2FEFKqdHqL4k7jEW9

설문 조사를 작성하지 않으셨더라도 저한테 DM을 보내서 알려주시면 참가하실 수 있습니다.

타임어택 프로그램에 참여하지 않으시더라도 슬랙 방에 참여하시면 긱뉴스 등의 정보 공유도 하고 프로그래밍 질문고민 상담도 하고 여러 모로 도움되실 거에요. 벌써 3000분 정도 들어계십니다!

감사합니다.

조현영 프로필
VanillaExtract 보너스 강의 업로드 & 수강생 정리노트 공개
조현영 3달 전 (3달 전 수정됨)

안녕하세요. 제로초입니다.

CES2024 참여한다고 라스베가스 가느라, 샌프란시스코에서 독감 걸려서 고생하느라 바닐라익스트랙트 보너스 영상이 조금 늦었습니다. 방금 업로드해두었습니다. 강의 코드는 https://github.com/ZeroCho/next-app-router-z/tree/master/lecture 폴더에 있습니다.

타임어택 참여하신 수강생 3분께서 강의를 수강하면서 정리하신 노트도 공개합니다. 너무 정리를 잘 해주셔서 강의와 함께 보시면 도움이 많이 될 것 같습니다.
https://zerocho.notion.site/Next-js14-7ff657dc0ec544759d0fc2e6e28da057?pvs=4

추가로 강의 교안 및 영상을 계속 보완하고 있습니다. 영상에서 따라하기 헷갈린다거나 막히는 부분은 언제든지 적극적으로 제보해주세요. 틈틈이 수정하고 있습니다.

섹션 0 수업 4에 이 강의를 효율적으로 듣는 방법 영상도 추가하였습니다. 제가 의도한 강의 수강법은 그렇다는 것 참고해주세요~

감사합니다.
제로초 드림.

 

다른 댓글 보기(1)
조현영 프로필
React Query + Suspense 추가 내용
조현영 4달 전 (4달 전 수정됨)

안녕하세요. 제로초입니다.

벌써 600분 넘게 구매해주셨네요. 감사합니다!!

이번 내용은 지난 번 보너스 영상의 보너스같은 것이라고 생각해주시면 됩니다.

React Query는 클라이언트쪽 라이브러리라서 Suspense로 감싸도 인식이 안 되고, 따로 isLoading이나 isPending, isError일 때 처리를 해주어야 한다고 말씀드렸는데요.

useQuery -> useSuspenseQuery, useInfiniteQuery -> useSuspenseInfiniteQuery로 변경하신다면(import도 필수!) Suspense fallback(또는 loading.tsx)에서 로딩, ErrorBoundary(또는 error.tsx)에서 에러 처리 가능합니다.

코드 중복 없이 이렇게 처리하는 게 깔끔할 것 같습니다. 보너스 영상 뒷 부분에 붙여넣어서 다시 올렸습니다.

감사합니다! Vanilla Extract 영상도 제작 중입니다! 따뜻한 연말 보내시길 바라요~

다른 댓글 보기(2)
조현영 프로필
Suspense 최적화 강좌 추가
조현영 4달 전 (4달 전 수정됨)

안녕하세요. 제로초입니다.

벌써 500분 가까이 구매해주셔서 감사합니다. 수강 후기도 잘 남겨주시면 감사드리겠습니다.

보너스 강좌로 SuspenseStreaming하여 Next.js 로딩 속도 개선하는 강좌 오늘 11시 정도에 올라갑니다(loading.tsx, error.tsx 설명과 함께요). 섹션 3 마지막 강의로 올라갈 예정입니다.

소스 코드는 ch3-2에 있습니다.

https://github.com/ZeroCho/next-app-router-z/tree/master/ch3-2/src/app/(afterLogin)/home

다음 보너스 강좌는 css module 대신 최신 css 시스템 쓰는 법입니다. 지금 vanilla extract와 tailwind-variants, styleX 중에서 엄청 고민하고 있습니다.

또 보너스 강좌로 원하시는 점 있으시면(의견이 많이 나온다면) 제작해서 올려드리겠습니다.

감사합니다.

제로초 드림.

다른 댓글 보기(12)
조현영 프로필
신규 강좌 첫 타임어택 진행해봅니다!
조현영 5달 전 (5달 전 수정됨)

next-app-router 강좌 첫 타임어택 진행합니다!

강좌는 구매했는데 매번 끝까지 못 보시는 분들을 위한 프로그램입니다.무료로 참가하실 수도 있으며 의지력이 많이 부족한 분들을 위해 따로 보증금 제도도 운영하고 있습니다. 이전 기수 분들이나 같은 기수 분들의 정리 노트를 보면서 공부하실 수도 있고, 저나 다른 분들에게 질문을 할 수도 있습니다.

완주하시면 강좌 쿠폰(35~60%)이나 만나서 식사권을 드리고 있습니다!

저도 현재 매 기수 적자를 보면서 진행하고 있습니다.그럼에도 진행하는 이유는 제 강좌가 실질적으로 여러분들한테 도움이 되기를 바라기 때문입니다. 강좌를 사놓기만 하고 안 들으시는 분이 많은데 정해진 진도와 함께 끝까지 들으시고 여러분의 개발 실력이 향상되었으면 해서 매번 진행 중입니다.저는 제 강좌가 도움이 되었다는 말을 들을 때 가장 뿌듯하거든요.타임어택에서 나오는 강좌 피드백을 바탕으로 강좌를 조금씩 수정하고도 있어 저에게도 도움이 되고요.

슬랙에서 진행하기 때문에 슬랙 방 참가해주셔야 합니다. 아래 슬랙 링크로 들어오세요.

https://zerocho.com/slack

들어오셔서 8기-next-app-router 채널과 8기-진도체크방 채널에 들어오시면 됩니다. 보증금 참여하실거면 저한테 DM을 보내서 알려주시면 참가하실 수 있습니다.

  • 참고로 제 강의는 인프런에서 저를 검색해서 구매하시기보다는https://zerocho.com/lecture에 있는 링크 눌러서 구매해주시면 제가 내는 수수료가 많이 줄어듭니다. 부탁드려요 ㅎㅎ

     

     

타임어택 프로그램에 참여하지 않으시더라도 슬랙 방에 참여하시면 긱뉴스 등의 정보 공유도 하고 프로그래밍 질문 고민 상담도 하고 여러 모로 도움되실 거에요. 벌써 2900분 정도 들어계십니다!

감사합니다.