inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

172만명의 커뮤니티!! 함께 토론해봐요.

eslint를 추가하였지만 동작을 안합니다.

미해결

React 완벽 마스터: 기초 개념부터 린캔버스 프로젝트까지

'react/self-closing-comp': 'warn' 해당 문구를 추가했음에도 동작하지 않습니다. 재부팅도 해보았습니다만 동작하지 않습니다. 제가 잘못한 것이 있을까요?

  • react
  • React-Context
  • react-router
  • tailwindcss
  • react-query
  • eslint
조준희 댓글 3 좋아요 0 조회수 220

vite로 리액트 빌드한 후 깃허브에 배포하는 방법

미해결

만들면서 배우는 리액트 : 기초

강사님 강의 보면서 저는 vite 를 이용해서 했는데요, 그런 경우는 깃허브에 배포를 어떻게 해야 하나요? npm run build npm install gh-pages 그 다음에 package.json 파일도 아래처럼 수정을 했습니다. "homepage": " 깃허브주소 넣음 ", "deploy": "gh-pages -d dist" 그다음에 다시 npm run build npm run deploy 하면 깃허브에 gh-pages 가 생겨야 하는데 생기지를 않아서요.... 어디 부분을 잘못 한걸까요?

  • javascript
  • react
gangsugi 댓글 1 좋아요 0 조회수 365

빌드할때 dist 폴더가 만들어지는데요,

미해결

만들면서 배우는 리액트 : 기초

마지막에 빌드를 하려고 하는데요, 저는 vite를 이용해서 했구요, 깃허브에 페이지 올리고 pages까지 오픈을 했습니다. 그리고 나서 npm run build 를 하면 강사님하고 다르게 build 폴더가 아니고 dist폴더가 만들어지는데요, 혹시 그럴경우엔 깃허브에 배포할때 명령어가 혹시 강의내용과 다르게 해야 하는 부분이 있는지요? npm install gh-pages package.json 파일에서 소스 추가할때 "deploy": "gh-pages -d build" 위의 파일을 수정한 후 다시 npm run build npm run deploy 여기까지 해도 깃허브 저장소에서 gitpages가 생기기 않습니다...

  • javascript
  • react
gangsugi 댓글 1 좋아요 0 조회수 842

12.11) Home 페이지 구현하기 2. 기능

해결됨

한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지

해당 챕터에서 강의대로 진행했고 몇번을 다시 확인해봐도 차이점을 도통 찾지 못해서 문의드립니다. Home.jsx에서 데이터를 필터걸어도 걸리지않는 상황 DiaryList.jsx에서 DiaryItem으로 데이터를 보내도 받는쪽에서 받지 못하는 상황(개발자도구에서는 워닝으로 hook.js:608 Warning: Each child in a list should have a unique "key" prop) 발생 이하 소스첨부 드립니다. App.jsx import './App.css' import { useReducer, useRef, createContext } from 'react'; import { Routes, Route } from 'react-router-dom'; import Home from './pages/Home'; import Diary from './pages/Diary'; import New from './pages/new'; import Edit from './pages/Edit'; import Notfound from './pages/Notfound'; const mockData =[ { id : 1, createdDate : new Date("2024-12-6").getTime(), emotionId : 1, content : "1번 일기내용", }, { id : 2, createdDate : new Date("2024-12-5").getTime(), emotionId : 2, content : "2번 일기내용", }, { id : 3, createdDate : new Date("2024-11-15").getTime(), emotionId : 3, content : "3번 일기내용", }, ] function reducer(state, action){ switch(action.type){ case 'CREATE' : return [action.data, ...state] case 'UPDATE' : return state.map((item)=> String(item.id) === String(action.data.id) ? action.data : item) case 'DELETE' : return state.filter((item) => String(item.id) !== String(action.id)); default : return state; } } export const DiaryStateContext = createContext(); export const DiaryDispatchContext = createContext(); function App() { const [data, dispatch] = useReducer(reducer, [mockData]); const idRef = useRef(3); const onCreate =(createdDate, emotionId, content) => { dispatch({ type:"CREATE", data : { id : idRef.current++, createdDate, emotionId, content, }, }) } const onUpdate = (id,createdDate , emotionId, content) => { dispatch( { type : "UPDATE", data : { id, createdDate, emotionId, content, }, } ) } const onDelete = (id) => { dispatch( { type : "DELTE", data : { id, } } ) } return ( <> <DiaryStateContext.Provider value={data}> <DiaryDispatchContext.Provider value={{ onCreate, onUpdate, onDelete, }} > <Routes> <Route path="/" element={<Home />}></Route> <Route path="/new" element={<New />}></Route> <Route path="/diary/:id" element={<Diary />}></Route> <Route path="/edit/:id" element={<Edit />}></Route> <Route path="*" element={<Notfound />}></Route> </Routes> </DiaryDispatchContext.Provider> </DiaryStateContext.Provider> </> ); }; export default App Home.jsx import { useState, useContext } from "react"; import { DiaryStateContext } from "../App"; import Button from "../components/button"; import Header from "../components/Header" import DiaryList from "../components/DiaryList"; const getMonthlyData = (pivotDate, data) =>{ const beginTime = new Date( pivotDate.getFullYear(), pivotDate.getMonth(), 1, 0, 0, 0 ).getTime(); const endTime = new Date( pivotDate.getFullYear(), pivotDate.getMonth() + 1, 0, 23, 59, 59 ).getTime(); console.log('필터시작일자 : ' + beginTime + '필터종료일자' + endTime) return data.filter((item)=> beginTime <= item.createdDate <= endTime); } const Home = () => { const data = useContext(DiaryStateContext); const [pivotDate,setPivotDate] = useState(new Date()); const monthlyData = getMonthlyData(pivotDate, data); console.log(monthlyData); const onIncreaseMonth = () => { setPivotDate(new Date(pivotDate.getFullYear(), pivotDate.getMonth() + 1) ); }; const onDecreaseMonth = () => { setPivotDate(new Date(pivotDate.getFullYear(), pivotDate.getMonth() - 1) ); }; return <div> <Header title = {`${pivotDate.getFullYear()} 년 ${ pivotDate.getMonth()+ 1 }월`} leftChild={<Button onClick={onDecreaseMonth} text="<" />} rightChild={<Button onClick={onIncreaseMonth} text=">" />} /> <DiaryList data={monthlyData} /> </div>; } export default Home; DiaryList.jsx import './DiaryList.css' import Button from "./button"; import DiaryItem from './DiaryItem'; import { useNavigate } from 'react-router-dom'; import { useState } from 'react'; const DiaryList = ({data}) => { const nav = useNavigate(); const [sortType, setSortType] = useState("latest"); const onChangeSortType = (e) => { setSortType(e.target.value); }; const getSortedDate = () => { return data.toSorted((a, b) => { if(sortType ==='oldest'){ return Number(a.createdDate) - Number(b.createdDate); } else { return Number(b.createdDate) - Number(a.createdDate); } }); } const sortedData = getSortedDate(); return ( <div className="DiaryList"> <div className="menu_bar"> <select> <option value={"latest"}>최신순</option> <option value={"oldest"}>오래된순</option> </select> <Button onClick = {() => nav("/new")} text={"새 일기 쓰기"} type={"POSITIVE"} /> </div> <div className="list_wrapper"> {sortedData.map((item)=><DiaryItem key={item.id} {...item}/>)} </div> </div> ); }; export default DiaryList; DiaryItem.jsx import getEmotionImage from "../util/get-emotion-image" import Button from "./button"; import "./DiaryItem.css"; import { useNavigate } from "react-router-dom"; const DiaryItem = ({id, emotionId, createdDate, content}) => { const nav = useNavigate(); return ( <div className="DiaryItem"> <div onClick={()=>nav(`/diary/${id}`)} className={`img_section img_section_${emotionId}`} > <img src={getEmotionImage(1)} /> </div> <div onClick={()=>nav(`/diary/${id}`)} className="info_section"> <div className="created_date"> {new Date(createdDate).toLocaleDateString()} </div> <div className="content">{content}</div> </div> <div className="button_section"> <Button onClick={()=>nav(`/edit/${id}`)} text={"수정하기"} /> </div> </div> ) }; export default DiaryItem;

  • javascript
  • react
  • node.js
horlove86 댓글 1 좋아요 0 조회수 150

fetch() 사용 관련 질문입니다.

해결됨

한 입 크기로 잘라먹는 Next.js

안녕하세요. 강의를 전부 수강한 수강생입니다. 강사님의 강의를 보다가 궁금한 것이 있어서 질문 남깁니다. 강의에서는 API 요청 방식을 fetch를 사용하여 전부 Next 서버에서 요청을 보내는 방식이던데 클라이언트 컴포넌트에서 fetch를 사용하여 브라우저를 통해 요청하는 방법과 강의와 같이 사용하는 방법, API Route(Handle) 방식을 사용하는 방법의 차이를 알 수 있을까요?? 또한 Next 서버의 부하는 괜찮은지 궁금합니다.

  • react
  • typescript
  • next.js
dalgonkim 댓글 1 좋아요 0 조회수 141

데이터베이스 초기화(npx prisma db push) 이슈입니다.

해결됨

한 입 크기로 잘라먹는 Next.js

npm install 해서 의존성 설치후에 npx prisma db push를 했는데 $ npx prisma db push Environment variables loaded from .env Prisma schema loaded from prisma\schema.prisma Datasource "db": PostgreSQL database "postgres", schema "public" at " aws-0-ap-northeast-2.pooler.supabase.com:5432 " Error: P1001: Can't reach database server at aws-0-ap-northeast-2.pooler.supabase.com : 5432 Please make sure your database server is running at aws-0-ap-northeast-2.pooler.supabase.com : 5432 . 이렇게 나옵니다. 챗지피티랑 스택 오버플로우 이런거 봐도 잘 안돼서 질문드립니다.

  • react
  • typescript
  • next.js
한태현 댓글 2 좋아요 0 조회수 830

CSR, SSR 렌더링 방식 문의

해결됨

한 입 크기로 잘라먹는 Next.js

안녕하세요~ 설명해주신 CSR, SSR 렌더링 강의보고 CSR, SSR 렌더링 방식에 대해 궁금한점 두가지 남겨봅니다! (유사한 질문이 있는지 찾아봤는데 글이 많아서 찾질 못해서 중복 감안하고 올려봅니다🙏🏻) 질문1 CSR은 bundle js 다운로드 레이턴시 만큼 FCP가 느리고 반대로 SSR은 bundle js 다운로드 레이턴시만큼 CSR보다 FCP가 빠르다고 이해했는데요. TTI 기준으로 보면 결국 CSR, SSR모두 차이가 없는게 맞을까요? (gzip압축 해제, js parse, hydration등의 처리에서 드는 비용의 차이가 있겠지만 이런 부분들은 크게 영향을 주진 않을거라고 생각하여 문의드립니다. 혹시 두 방식에 영향을 미치는 큰 요소가 있다면 그 부분도 고려해서 알려주시면 감사하겠습니다.) 질문2 CSR의 장점으로 초기 렌더링이 느리고 이후에 페이지 이동시 빠르게 화면을 그릴 수 있다고 하셨는데요, CSR에서 초기 렌더링의 속도를 높이기 위해 코드 스플리팅 전략을 취할 수 있을거 같습니다. 이렇게 CSR에서 코드 스플리팅 방식을 취한 경우 페이지 이동시 결국 bundle js 다운르드 레이턴시가 또 발생할거 같은데요. prefetch, preload같은 전략을 취하지 않고 코드스플리팅만 적용한 CSR방식은 단점만 남는 렌더링 전략이 맞을까요? 유일한 장점은 CSR이지만 코드 스플리팅을 했기 때문에 초기 FCP가 조금 빠르다정도일거 같은데 이해한게 맞는지 문의드려봅니다.

  • react
  • next.js
슈퍼장 댓글 2 좋아요 1 조회수 189

Next-Auth 관련해서 질문이 있습니다.

미해결

Next + React Query로 SNS 서비스 만들기

백엔드 취준생인데 프론트를 좀 할 일이 있어서 강의 듣고 있는데 Next-Auth 부분이 이해가 쉽지 않네요... 몇 가지 질문 드리고자 합니다. 1. session 객체에 어떤게 담기는건지 잘 모르겠습니다. export default async function Home() { const session = await auth() if (session?.user) { redirect('/home') return null } return ( <Main/> ); } export const { handlers: { GET, POST }, auth, signIn, } = NextAuth({ // 개발자가 직접 만든 화면에서 로그인 하도록 진행 pages: { signIn: '/i/flow/login', // 로그인 newUser: '/i/flow/signup' // 회원가입 }, providers: [ CredentialsProvider({ async authorize(credentials) { const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, { method: 'POST', headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: credentials.usename, password: credentials.password, }) }) if (!authResponse.ok) { return null } const user = await authResponse.json() return { email: user.id, name: user.nickname, image: user.image, ...user } } }) ], }) Home 에서 auth() 를 통해 불러온 session 객체에 CredentialsProvider 가 리턴한 객체가 담기는건가요? 그런데 그렇다고 하기엔 객체에 user 라는 속성이 없어서 아닌 것 같기도 해서 아닌 거 같다는 생각도 듭니다. export default function Login() { const router = useRouter() const { data: session } = useSession(); if (session?.user) { router.replace('/home') return null } router.replace("/i/flow/login") return ( <Main /> ) } 마찬가지로 여기서도 session 에 어떤게 담기는지 잘 모르겠습니다 ㅠㅠ auth() 로 리턴한 세션과 같은 객체가 담기는 것 같긴 한데 도대체 session 에 뭐가 담기는지 파악이 쉽지 않네요 ㅋㅋㅋ 그래서 session 객체의 user 를 클릭해서 들어가보니 다음과 같은 interface 가 나오네요. export interface DefaultSession { user?: User expires: ISODateString } auth/core 에 있는 인터페이스인 것 같은데 이 인터페이스가 어느 시점에 등장(?) 하는 건지 잘 모르겠습니다. 2. 지금 진행하는 로그인 방식은 백엔드에 로그인 관련 API 가 있다고 가정하고 진행하는 것으로 저는 이해를 했는데요 export const handlers = [ http.post(`${baseUrl}/api/login`, () => { console.log('로그인'); return HttpResponse.json(User[1], { headers: { 'Set-Cookie': 'connect.sid=msw-cookie;HttpOnly;Path=/' }, }) }), http.post(`${baseUrl}/api/logout`, () => { console.log('로그아웃'); return new HttpResponse(null, { headers: { 'Set-Cookie': 'connect.sid=;HttpOnly;Path=/;Max-Age=0' } }) }), http.post(`${baseUrl}/api/users`, async ({ request }) => { console.log('회원가입'); // return HttpResponse.text(JSON.stringify('user_exists'), { // status: 403 // }) return HttpResponse.text(JSON.stringify('ok'), { headers: { 'Set-Cookie': 'connect.sid=msw-cookie;HttpOnly;Path=/' }, }); }) ]; 이게 지금 api 를 mocking 한 건데 여기에 요청을 보내고 있으니까요. 그러면 이 API 에서 리턴한 유저(User[1]) 가 세션에 담기는 것인지 궁금하네요. (이것도 1번 질문하고 좀 연관이 되네요) 그러면 만약에 백엔드 API 가 로그인 성공했을 때 http body 에 별도의 객체를 리턴하지 않으면 어떻게 되나? 이런 궁금증도 생깁니다. 3. 그리고 로그아웃을 할 때는 왜 로그아웃 API 에 따로 요청을 보내지 않고 signOut 함수만 사용하는지 궁금합니다. 이것만 사용해도 쿠키가 삭제가 돼서 그런 것인가요? 그러면 백엔드 서버에 별도의 로그아웃 API 를 만들지 않아도 되는 것인지 궁금합니다. 장문의 질문글이 된 거 같은데, 뭔가 Next-Auth 를 처음 접하다보니 사용법이 좀 익숙치가 않네요. AI 에 물어보거나 구글링을 해 봐도 좀 파악이 쉽지 않아 여기에 질문 남겨봅니다. 감사합니다.

  • react
  • next.js
  • react-query
  • next-auth
  • msw
비가싫어요 댓글 1 좋아요 0 조회수 203

filter return 문제

해결됨

한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지

todos.filter을 사용할 때 내부의 화살표함수에서 return 을 명시하지 않으면 값이 정상적으로 반환되지 않습니다. 강의에서는 return 을 별도로 작성하지 않았는데 값이 정상적으로 반환되는것 같네요 리액트 버전의 문제일까요..?

  • javascript
  • react
  • node.js
박선우 댓글 2 좋아요 0 조회수 219

ES Lint 9에서의 rule 설정

해결됨

한 입 크기로 잘라먹는 Next.js

ES Lint 설정 안녕하세요. 현재 Next.js 15.1 버전에서 ESLint가 9버전으로 업데이트 되면서 형식이 많이 바뀌었는데 기존의 8 버전에서는 { "extends": ["next/core-web-vitals", "next/typescript"], "rules": { "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-explicit-any": "off" } } 하지만 9 버전에서는 형식이 많이 바뀌었는데 no-unused-vars나 on-explicit-any 같은 설정은 어떻게 해야 하나요? 일단은 이렇게 코드를 쓰기는 했는데 적용이 잘 안되는 것 같습니다.(eslint.config.mjs) import { dirname } from "path"; import { fileURLToPath } from "url"; import { FlatCompat } from "@eslint/eslintrc"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const compat = new FlatCompat({ baseDirectory: __dirname, }); export default [ ...compat.extends("next/core-web-vitals", "next/typescript"), { files: ["**/*.ts", "**/*.tsx"], rules: { "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-explicit-any": "warn", // 경고로 설정 }, }, ];

  • react
  • typescript
  • next.js
피곤한개발자 댓글 1 좋아요 0 조회수 547

노션 링크가 없다고 나와요

미해결

코딩 몰라도 OK! CursorAI로 시작하는 개발 생활 (웹/초급)

커서 및 vscode 설치 방법 다운로드를 받지 않으신 분들은 차분히 다운로드를 받으신 다음 아래의 Node.JS를 설치 해주세요 해당 노드 링크 클릭하면 The page you are looking for cannot be found! Please ask the owner of the page for an updated link. 로 나옵니다!

  • react
  • 웹-디자인
  • firebase
  • no-code
  • cursor
  • vercel
tldos97 댓글 2 좋아요 0 조회수 478

클라이언트 컴포넌트의 사전 렌더링 질문

해결됨

한 입 크기로 잘라먹는 Next.js

안녕하세요, 우선 강의 너무 잘 들었습니다. 사전 렌더링에 대한 부분에서 궁금중이 있어 문의를 남깁니다. 클라이언트 컴포넌트 또한 서버에서 JS 실행을 통해 서버 측에서 사전 렌더링이 된다는 것을 알고 있습니다. 다만, 서버에서 실행되는 사전 사이드 렌더링의 경우 useEffect, useState 등과 같은 훅은 어떤 식으로 실행이 되는지 궁금 합니다. 왜냐하면 서버 클라이언트에서는 훅 사용이 불가능한 것으로 알고 있는데, 이는 곧 서버에서 훅을 사용하지 못한다는 뜻으로 이해하고 있어서요. 만약 해당 훅 들이 서버에서 실행되지 않고, 컴포넌트에 마운트 된 이후에 실행 되는 것이라면, 컴포넌트 return 문 안에 있는 State나 로직들은 undefined 인 상태에서 렌더링 되어 Client에 HTML 형태로 전달 되는 것일까요? 또한 비슷한 질문인데, 사전 렌더링에서 local storage, DOM 조작 등과 같이 Client에서만 접근 가능한 API에서는 어떤 식으로 사전 렌더링이 진행 되는지, 그리고 초기 HTML을 그릴 때는 해당 값들을 어떻게 처리 하는 지 궁금합니다. 좋은 강의 감사합니다!

  • react
  • typescript
  • next.js
itjustbong 댓글 2 좋아요 0 조회수 117

서버 액션을 트리거하는 방법

해결됨

한 입 크기로 잘라먹는 Next.js

안녕하세요. 지금까지 서버 액션을 트리거 하실때 form 태그를 이용해서, 제출형식으로 트리거 하셨는데, next 에서 서버 액션을 트리거 할때 단순한 작업이라면 form태그가 아닌 버튼형식으로 하는것도 괜찮은지 궁금해서 여쭤봅니다. 버튼으로 하는것도 가능은 하지만 권장되지 않는 방식인것인가요? 이를테면 각각의 북페이지에 유저가 좋아요와 싫어요를 누를 수 있는 기능이 있다고 가정했을때, 좋아요와 싫어요는 단순한 기능이라고 생각이 되는데, 이런 경우에는 버튼으로 서버 액션을 트리거하는 방법도 괜찮은것인지 궁금합니다!. 감사합니다.

  • react
  • typescript
  • next.js
gjgusqls123 댓글 1 좋아요 0 조회수 217

/boards/224/ 403 이 뜨네요.

해결됨

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

next.config.mjs /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, trailingSlash: true, generateBuildId: () => "tranme24", // 아래 주소들만 out 폴더에 만들기 exportPathMap: () => ({ "/": {page: "/"}, "/boards": {page: "/boards"}, "/404": {page: "/404"}, }) }; export default nextConfig; 위와같이 설정 경로에서 아래의 이미지와 같이 파일들이 동일한걸 확인했습니다. 왜 안되는걸까요.

  • react
  • node.js
  • seo
  • graphql
  • next.js
gkdlsb1234 댓글 2 좋아요 0 조회수 80

안녕하세요! next-auth 로그인하기 부분 질문입니다.

미해결

Next + React Query로 SNS 서비스 만들기

지금 강의에서 보여주신게 아직 업데이트가 안 된 것인지 궁금합니다! Auth.js 홈페이지에 있는 문서와 코드가 조금 다른 것 같아서요. next.js 15 버전으로 강의 따라가고 있고 auth.js 설치할 때 auth@5 하니까 설치가 안 돼서 auth@beta 이렇게 설치하고 진행 중 입니다! 제가 본 페이지는 다음과 같습니다. https://authjs.dev/getting-started/authentication/credentials 추가 일단 제로초님이 하신 방법으로 CredentialsProvider 직접 import 하니까 되는 것 같습니다!

  • react
  • next.js
  • react-query
  • next-auth
  • msw
비가싫어요 댓글 2 좋아요 0 조회수 287

사용중인 Theme 문의

해결됨

한 입 크기로 잘라먹는 Next.js

안녕하세요, 강사님. 강의 너무 잘 듣고 있습니다. 혹시 사용중이신 Theme과 어떻게 설정하고 있는지 공유 부탁드려도 될까요? 가독성이 좋아서 저도 동일하게 적용하고 싶습니다. 감사합니다.

  • react
  • typescript
  • next.js
정지현 댓글 1 좋아요 0 조회수 196

input 안에 value를 넣어주는 이유가 궁금합니다!

미해결

한 입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지

<input value={name} onChange={onChangeButton} placeholder={"이름"} /> 안녕하세요! 이번 강의 내용에서 return되는 부분에서 텍스트 박스를 형성하는 부분에 있는 위에 코드 부분에 대한 질문입니다! value={name}이 들어가는 이유는 무엇인가요?? 이 부분이 없어도 지장이 없는 것 같아 여쭤봅니다!

  • javascript
  • react
  • node.js
황서영 댓글 3 좋아요 0 조회수 317

react-toastify 를 storybook에 출력 시키기

해결됨

실무에 바로 적용하는 스토리북과 UI 테스트

react-toastify를 사용하시는 경우 storybook에서 출력하는데 곤란함을 겪는 분들이 계실 거 같아 자문자답 올려둡니다! package.json "react-toastify": "^10.0.4" "@types/react": "^18.3.12", "@storybook/react": "^8.3.0", .storybook/preview.tsx ( ts가 아닌 tsx ) 17버전 이상이라 import React from 'react'가 안되서 아래와 같이 @jsxImportSource 추가 /** @jsxImportSource react */ import type { Preview } from '@storybook/react'; // react-toastify 관련 import import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; Modal.setAppElement('#storybook-root'); const preview: Preview = { parameters: { actions: { argTypesRegex: '^on[A-Z].*' }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/i, }, }, }, decorators: [ Story => ( <> <Story /> <ToastContainer position="bottom-right" autoClose={3000} hideProgressBar={false} newestOnTop={false} closeOnClick rtl={false} pauseOnFocusLoss draggable pauseOnHover theme="light" /> </> ), ], }; export default preview; tsconfig.json { "compilerOptions": { "jsx": "react-jsx", } }

  • react
  • typescript
  • tailwindcss
  • storybook
  • ui-testing
  • react-toastify
배찬 댓글 1 좋아요 0 조회수 201

useEffect로 사용을 해도 되나요?

미해결

따라하며 배우는 리액트 A-Z[19버전 반영]

useEffect(() => { localStorage.setItem('todoData', JSON.stringify(todoData)); }, [todoData]); 이렇게 작성을 하고, 나머지는 다 주석을 처리했는데도 정상 작동하는 것 같더라구요. 하지만 의문인게 setTodoData((prev) => [...prev, newTodo]); localStorage.setItem('todoData', JSON.stringify([...todoData, newTodo])); 여기도 주석처리를 했는데, 여기는 조금 작성하는 게 다르 지 않나요? handleRemoveClick = () => { setTodoData([]) } 여기도 그렇구요. 그런데 그냥 다 정상 작동 하네요?

  • react
  • redux
  • tdd
  • typescript
  • next.js
  • 소프트웨어-테스트
gusn9719 댓글 1 좋아요 0 조회수 218

로그인 방식 관련해서 질문드립니다!!

미해결

Next + React Query로 SNS 서비스 만들기

로그인 방식을 구현하면서, 쿠키로만 개발할 경우 완전히 백엔드에 의존하게 되어 로컬로, 동시에 키고 개발을 하지 않는이상, 도메인간 불일치를 해결 할 방법이 없어, msw를 사용해야 한다고, 이전에 말씀해주셨습니다!! 보통, 회사나, 개인 소프트웨어를 만들 때 어떤 방식으로 로그인을 주로 만드시는지 조금 알고 싶어 궁금하여 질문을 남깁니다!! 로그인 방식 고찰 로그인 성공시, accessToken을 body로 받고, refreshToken은, httpOnly 쿠키로 받는 경우 (서버에서, DB or Redis를 통해 refreshToken 관리) → 인증 필요 요청 (Bearer accessToken), 리프레시 필요 요청 (refreshToken 심긴 쿠키를 바탕으로 요청) - DB에서 관리하는 것 보다, redis를 통해 관리했을 떄 읽기 속도가 빠름을 확인! 응답: accessToken과 refreshToken 모두 body로 클라이언트에게 전달. 인증 필요 요청과, 리프레시 토큰 재발급 요청 모두 헤더의 Bearer에 accessToken이나, refreshToken을 넣어서 전달.) 현재 방식: accessToken, refreshToken 모두 쿠키로 응답받고, 요청또한, 쿠키를 포함하여 전달. 제로초님은, Next.js를 활용하여, 웹 사이트를 만드실 떄, 어떠한 방식으로 로그인을 구현하시는지 궁금하고, 많은 회사에서 사용하는 방식은 보통 어떤 방식인지도 알고싶습니다!

  • react
  • next.js
  • react-query
  • next-auth
  • msw
김용민 댓글 2 좋아요 0 조회수 243

인기 태그

인프런 TOP Writers

주간 인기글