inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

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

34강 orphanRemoval 관련 질문입니다!

해결됨

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

orphanRemoval 을 걸지 않았을 경우 책6을 삭제했으나, userLoanHistories를 조회해보면 여전히 책6이 존재한다. orphanRemoval = true 을 걸었을 경우 클린 코드를 삭제했더니 조회시 사라졌다 어째서 orphanRemoval 을 걸어주지 않으면 데이터베이스에 반영이 되지 않는건가요? @Transactional 어노테이션으로 인해 트랜잭션이 시작될 때, 영속성 컨텍스트가 시작되고, 영속성 컨텍스트의 4대 특징 중 하나인 생성/수정 감지로 인해 user 객체의 userLoanHistories 의 값에 변경사항( removeOneHistory )이 발생하여 자동저장이 될거라고 생각했는데 말이죠.. 실제 데이터베이스상에선 userLoanHistories 는 user테이블의 필드가 아니기 때문에, 영속성 컨텍스트가 관리하는 field 에 포함이 되지않는데 orphanRemoval = true 를 걸어주면 비로소 자신이 관리하는 field로 인식하는걸까요? 원리가 너무 궁금해요.. 내용추가1) 바로 다음 강의인 책 대출 리팩토링에선 orphanRemoval 같은 옵션을 주지 않고도 new userLoanHistory 를 add한 내용대로 저장이 되는데, 어째서 userLoanHistory 를 remove하는것은 orphanRemoval 옵션이 없으면 데이터의 변경이 일어나지않는지 궁금합니다.. 제 생각에는 User 에서 userLoanHistories.add 를 하든 userLoanHistories.remove 를 하든 둘 다 User 와 UserLoanHistory 와의 연관관계를 이용한 데이터를 변경하기위한 접근같은데 .. add는 되는데 remove는 안되는게 살짝 이해하기 어렵습니다 ㅠ 내용추가2) returnBook 과 loanBook , removeOneHistory 의 차이점이 뭘까 고민해봤는데 returnBook 과 loanBook 은 UserLoanHistory 라는 Entity에 접근하는 과정 (loanBook은 Entity객체생성, returnBook은 Entity의 property 수정)이 존재하고, removeOneHistory 는 Entity에 직접 접근하는게 아니라 단순히 List에 대한 변경일뿐이고, Entity에 대한 직접적인 수정이나 생성이 이뤄진것이 아니므로 데이터베이스의 변경이 일어나지 않았다. 이렇게 이해했는데 제가 이해한 내용이 맞을까요? 생각을 정리하다보니 질문이 길어진 점 죄송합니다 ㅠ

  • java
  • spring
  • spring-boot
  • jpa
영후이 댓글 1 좋아요 1 조회수 383

Next.js

해결됨

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

안녕하세요 제가 급히 Next.js에 관련하여 업무에 필요한데, 어느 강의부터 수강하면 될까요? 😅

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

버전 3.2.2 테스트 오류 - 해결은 했지만 궁금한 점

미해결

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] id 'java' id 'org.springframework.boot' version '3.2.2' id 'io.spring.dependency-management' version '1.1.4' java { sourceCompatibility = '17' } 현재 쓰는 버전입니다. 애플리케이션 실행에는 문제가 없지만 테스트시에 아래와 같이 오류가 뜹니다. Execution failed for task ':test'. > There were failing tests. See the report at: file:///C:/Workspace/jpa_%EA%B0%95%EC%9D%98/jpashop/build/reports/tests/test/index.html * Try: > Run with --scan to get full insights. Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0. You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins. For more on this, please refer to https://docs.gradle.org/8.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation. BUILD FAILED in 1s 4 actionable tasks: 1 executed, 3 up-to-date 이에 대한 해결 방법을 찾아 보던 중 파일 - 설정 - 빌드,실행,배포 - gradle - 다음을 사용하여 테스트 실행 - IntelliJ IDEA 로 변경을 하여 해결하였습니다. 해결은 했지만 왜 이와같은 오류가 일어났었는지 IntelliJ IDEA 로 테스트를 실행하도록 했을 때 왜 동작하는지 앞으로 다른 문제가 발생하지는 않을지 궁금합니다.

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
은돌 댓글 1 좋아요 0 조회수 688

테스트를 실행해도 db에 반영이 안되는 것 같습니다.

미해결

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 처음에 db delete 안 해주고 실행했을 때도 체크 표시가 떴고 delete 해주고 실행, db에서 회원 목록 조회하니 목록에 아무도 없습니다. test가 db에 연결이 안된 걸까요?

  • java
  • spring
  • mvc
  • spring-boot
이서영 댓글 1 좋아요 0 조회수 611

accounts/url 질의

미해결

장고 설계철학으로 시작하는 파이썬 장고 입문

화면과같이 include 부분 강좌와 다르게 저절로 세팅이 되고 서버 실행하면 계속 오류가나는데 어떻게해야하나요ㅜㅜ

  • python
  • django
동휘김 댓글 2 좋아요 0 조회수 260

수정이라는 작업을 할 때 PUT을 더 사용하는 이유가 있을까요?

미해결

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

HTTP 메서드에 처음 공부할 때 수정의 경우에는 PUT과 PATCH를 사용한다고 배웠는데요. PUT의 경우에는 통째로 갈아끼우는 방식의 갱신이고 PATCH의 경우에는 부분 수정이 가능하다고 배웠습니다. 이 강의에서는 USER의 정보중에 이름만받고 있어서(PUT은 전체 필드를 명시해주어야 한다고 배웠습니다.) PATCH가 더 적당한 방식이 아닌가라는 생각이 들었습니다. PATCH가 아닌 PUTMapping을 사용하신 이유가 있으실까요? 그리고 이와 관련된 블로그 글들이 많은데 저마다 내리는 결론이 달라서 조금 혼란스럽습니다. 강사님의 생각을 듣고 싶습니다. 좋은 강의 만들어주신 태현님을 존중하고 존경하며 이만 글 줄이겠습니다!

  • java
  • spring
  • aws
  • mysql
  • spring-boot
  • jpa
wisehero 댓글 1 좋아요 4 조회수 2465

"Error: This action with HTTP GET is not supported."

해결됨

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

안녕하세요. next-auth 로그인부분 수강중 "Error: This action with HTTP GET is not supported." 가 뜨고 있습니다. 다른분들 해결방법이 대부분 버전이슈였어서 버전을 맞췄는데도 해당 오류가 사라지지 않아서 질문드립니다.. // package.json { "name": "nadang-com", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "mock": "npx tsx watch ./src/mocks/http.ts" }, "dependencies": { "@auth/core": "^0.18.0", "@faker-js/faker": "^8.4.1", "classnames": "^2.5.1", "dayjs": "^1.11.10", "next": "14.1.0", "react": "^18", "next-auth": "^5.0.0-beta.3", "react-dom": "^18" }, "devDependencies": { "@mswjs/http-middleware": "^0.9.2", "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", "cors": "^2.8.5", "eslint": "^8", "eslint-config-next": "14.1.0", "express": "^4.18.2", "msw": "^2.1.7", "typescript": "^5" }, "msw": { "workerDirectory": "public" } } # 터미널오류 ○ Compiling /api/auth/[...nextauth] ... ✓ Compiled /api/auth/[...nextauth] in 894ms (494 modules) ########### http://localhost:9090 ########### http://localhost:9090 [auth][error] UnknownAction: Cannot parse action at /api/auth/providers .Read more at https://errors.authjs.dev#unknownaction at parseActionAndProviderId (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/utils/web.js:90:49) at toInternalRequest (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/utils/web.js:32:40) at Auth (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/index.js:82:103) ..중략 [auth][error] UnknownAction: Cannot parse action at /api/auth/error .Read more at https://errors.authjs.dev#unknownaction at parseActionAndProviderId (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/utils/web.js:90:49) at toInternalRequest (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/lib/utils/web.js:32:40) at Auth (webpack-internal:///(rsc)/./node_modules/next-auth/node_modules/@auth/core/index.js:82:103) at httpHandler (webpack-internal:///(rsc)/./node_modules/next-auth/index.js:139:80) at C:\Users\INA\Documents\workspace\next\nadang-sns\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:63815 ... at DevServer.renderToResponseWithComponentsImpl (C:\Users\INA\Documents\workspace\next\nadang-sns\node_modules\next\dist\server\base-server.js:1463:53) ○ Compiling /src/middleware ... ✓ Compiled /src/middleware in 1197ms (218 modules) //LoginModal.tsx "use client"; import style from "@/app/(beforeLogin)/_component/login.module.css"; import { signIn } from "next-auth/react"; import { useRouter } from "next/navigation"; import { ChangeEventHandler, FormEventHandler, useState } from "react"; export default function LoginModal() { const [id, setId] = useState(""); const [password, setPassword] = useState(""); const [message, setMessage] = useState(""); const router = useRouter(); const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => { e.preventDefault(); setMessage(""); let shouldRedirect = false; try { await signIn("credentials", { username: id, password, redirect: false, //true로 하면 서버에서 리다이렉트 }); shouldRedirect = true; } catch (error) { console.error(error); setMessage("아이디 또는 비밀번호가 일치하지 않습니다."); } if (shouldRedirect) { router.replace("/home"); } }; const onClickClose = () => { router.back(); }; const onChangeId: ChangeEventHandler<HTMLInputElement> = (e) => { setId(e.target.value); }; const onChangePassword: ChangeEventHandler<HTMLInputElement> = (e) => { setPassword(e.target.value); }; return ( <div className={style.modalBackground}> <div className={style.modal}> <div className={style.modalHeader}> <button className={style.closeButton} onClick={onClickClose}> <svg width={24} viewBox="0 0 24 24" aria-hidden="true" className="r-18jsvk2 r-4qtqp9 r-yyyyoo r-z80fyv r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-19wmn03" > <g> <path d="M10.59 12L4.54 5.96l1.42-1.42L12 10.59l6.04-6.05 1.42 1.42L13.41 12l6.05 6.04-1.42 1.42L12 13.41l-6.04 6.05-1.42-1.42L10.59 12z"></path> </g> </svg> </button> <div>로그인하세요.</div> </div> <form onSubmit={onSubmit}> <div className={style.modalBody}> <div className={style.inputDiv}> <label className={style.inputLabel} htmlFor="id"> 아이디 </label> <input id="id" className={style.input} value={id} onChange={onChangeId} type="text" placeholder="" /> </div> <div className={style.inputDiv}> <label className={style.inputLabel} htmlFor="password"> 비밀번호 </label> <input id="password" className={style.input} value={password} onChange={onChangePassword} type="password" placeholder="" /> </div> </div> <div className={style.message}>{message}</div> <div className={style.modalFooter}> <button className={style.actionButton} disabled={!id && !password}> 로그인하기 </button> </div> </form> </div> </div> ); } // route.ts export { GET, POST } from "@/auth"; // auth.ts import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; console.log("###########", process.env.AUTH_URL); export const { handlers: { GET, POST }, auth, } = NextAuth({ // 직접 만든 페이지는 따로 지정해줘야함 pages: { signIn: "/i/flow/login", newUser: "/i/flow/signup", }, providers: [ CredentialsProvider({ async authorize(credentials) { console.log("@#@#@#@#", credentials); const authResponse = await fetch(`${process.env.AUTH_URL}/api/login`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: credentials.username, password: credentials.password, }), }); if (!authResponse.ok) { return null; } const user = await authResponse.json(); return user; }, }), ], }); 혹시 제가 확인하다가 빠뜨린 부분이 있거나 잘못된 부분이 있다면 알려주시면 감사하겠습니다 ㅠㅠㅠ 계속 node_modules .next packge-lock.json 다 지우고 깔고 코드 하나하나 바꿔보고 하다보니까 이제 뭐가 어디서부터인지 보이지가 않습니다 ㅠㅠㅠㅠ

  • react
  • next.js
  • react-query
  • next-auth
  • msw
ina9377 댓글 1 좋아요 1 조회수 925

SignupModal showMessage 함수 파라미터 타입 질문입니다.

미해결

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

SignupModal 만드는 과정에서 질문이 있습니다. useFormState 훅을 사용할 때 계속 에러가 나서 signup.ts 파일을 커뮤니티를 참고해서 수정해줬습니다. return {message: null } 을 추가해주는 식으로요. 그러고나서 showMessage 함수를 만드는데, 강의에서는 showMessage 함수의 파라미터의 타입이 string 이라고 하는데 제 꺼에선 실제로 들어가는 값이 string | null 이라고 나오면서 에러가 발생합니다. 초기 state 도 { message: null } 이고, signup.ts 에서도 { message: null } 을 리턴하는 경우가 있어서 이런 것 같은데 제로초님은 강의에서 showMessage 함수의 파라미터 타입을 그냥 string으로 해도 에러가 나지 않는 것이 신기하여 질문 남겨봅니다.

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

이미지 업로드에 관해 질문이 있습니다.

미해결

[리뉴얼] React로 NodeBird SNS 만들기

제가 지금 블로그에서 에디터로 이미지를 합해서 백에다가 데이터를 보내고 잇는데 제로초님이 말씀하신데로 해봣는데 이미지의 소스는 imges라는 테이블에 정상적으로 들어가는데 문제는 post에 <p>이미지 </p><p><img src= ">"http://localhost:3065/KakaoTalk_20240122_212009014_01_1707401883946.jpg"></p > 이런식으로 이미지가 들어가게 되는데 에디터라서 이렇게 들어가게 되는게 맞는지 아닌지 궁금합니다... 용량이 걱정이 되서요 ㅠㅠ 이미지로 보여드리면 이런데 원래 에디터안에 들어가는 이미지 같은경우는 텍스트랑 같이 db에 저장시키는게 맞는지 궁금합니다.

  • react
  • redux
  • node.js
  • express
  • next.js
GI P 댓글 1 좋아요 0 조회수 257

카카오로그인 실패 및 질문

미해결

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

카카오 로그인을 next-auth로 구현해보고자 강의에서 말씀하신것 처럼 KakaoProvider 추가하고, LoginModal.tsx에서 'credentials' 대신 'kakao'로 바꿔 진행해보았는데 우선 등록하지 않은 Redirect URI를 사용해 인가 코드를 요청했습니다 사용한 Redirect URI: h ttp://localhost:9090/api/auth/callback/kakao. 라는 에러가 발생하였습니다. (참고로 현재 카카오 developers에 저장해둔 Redirect URI는 http://localhost:3001/api/auth/callback/kakao 입니다) 이후 혹시나 해서 Redirect URI의 설정을 9090으로 바꾸고 다시 진행해보았더니 이처럼 진행이 되었고, 계속하기 눌렀더니 Cannot GET /api/auth/callback/kakao 이러한 에러가 발생하였습니다. 어떤부분이 잘못되었는지 잘 모르겠어서 질문글 올립니다ㅠ

  • react
  • next.js
  • react-query
  • next-auth
  • msw
화랑 댓글 1 좋아요 0 조회수 698

새로 고침 시 로그인이 유지되지 않는 버그가 발생합니다!(쿠키 존재O)

해결됨

[리뉴얼] React로 NodeBird SNS 만들기

안녕하세요 제로초님! AWS에 배포하기 및 카카오톡 공유하기 강의까지 끝마친 수강생 입니다! 저는 윈도우 10, 크롬 브라우저, VSCode, MySQL 8버전을 사용하고 있습니다. 로그인 후 새로 고침을 하면 로그인이 유지되지 않고 풀려 버리는 버그가 발생 하여 질문을 올리게 되었습니다! 이 문제는 쿠키가 있음에도 발생 합니다! 이 버그로 인해 총 2가지 상태에 이릅니다. 1. 완전히 로그인을 한 상태에서 새로 고침을 하면 쿠키는 남아있으나 로그인이 유지되지 않습니다. 2. 완전히 로그인이 된 상태에서 프로필 페이지로 이동하면 로그인이 풀리며 홈페이지로 돌아옵니다. 새로 고침 후 로그인이 풀리는 문제가 발생한 시점에서 다시 로그인을 하려고 하면 로그인 유무 검사(로그인하지 않은 사용자만 접근 가능) 메시지가 뜹니다. 로그인 후 로그아웃을 하면 해당 문제가 발생하지 않습니다. 해당 에러를 임시로 해결하는 방법을 찾았습니다. 프론트 페이지와 백엔드 페이지 애플리케이션 탭에서 쿠키를 지우면 다시 로그인을 진행할 수 있습니다. 하지만 말 그대로 임시로 해결하는 것 뿐이라 로그인 후 새로 고침을 하면 아까와 똑같이 로그인이 풀려버립니다. 문제를 해결하기 위해 페이지에서 콘솔 탭과 네트워크 탭, 애플리케이션 탭의 쿠키 쪽을 확인하였습니다. 프론트 콘솔 탭 확인 해당 에러 주소로 들어가 보았지만 외계어로 적혀있어 다른 곳을 먼저 확인해보기로 했습니다. 프론트 네트워크 탭 확인 401 Unauthorized 에러를 네트워크 탭에서 확인 했습니다. Headers 탭에 적힌 쿠키와 Cookies 탭에 적힌 쿠키는 똑같았습니다! 프론트 쿠키 존재 확인 로그인 후 로그아웃을 진행하면 쿠키가 남아있습니다. 백엔드 쿠키 존재 확인 백엔드 페이지도 프론트 쪽과 똑같이 쿠키가 잘 들어가 있음을 확인하였습니다. 페이지 쪽을 전부 확인한 뒤, 우분투 백엔드 pm2 monit을 확인해보니 사용자 로그인 쪽에서 401 에러가 나고 있었습니다. sudo npx pm2 logs --err --lines 200 명령어로 에러 로그를 확인하였으나 관련 에러는 찾지 못하였습니다. 문제를 해결하기 위해 잘못 적은 코드가 있는지 검사하였습니다. 아래는 가장 의심되는 코드들 입니다! 리듀서, 사가, 라우터, 로그인 검사, 서버사이드 렌더링 순으로 작성하였습니다. front/reducers/user.js 나의 사용자 정보 불러오기 리듀서 const reducer = (state = initialState, action) => { return produce(state, (draft) => { switch (action.type) { /* 나의 사용자 정보 불러오기 요청 리듀서 */ case LOAD_MY_INFO_REQUEST: draft.loadMyInfoLoading = true; draft.loadMyInfoError = null; draft.loadMyInfoDone = false; break; /* 나의 사용자 정보 불러오기 성공 리듀서 */ case LOAD_MY_INFO_SUCCESS: draft.loadMyInfoLoading = false; draft.me = action.data; draft.loadMyInfoDone = true; break; /* 나의 사용자 정보 불러오기 실패 리듀서 */ case LOAD_MY_INFO_FAILURE: draft.loadMyInfoLoading = false; draft.loadMyInfoError = action.error; break; 로그인 리듀서 . . . /* 로그인 요청 리듀서 */ case LOG_IN_REQUEST: draft.logInLoading = true; draft.logInError = null; draft.logInDone = false; break; /* 로그인 성공 리듀서 */ case LOG_IN_SUCCESS: draft.logInLoading = false; draft.me = action.data; // 로그인 성공 시 실제 사용자 데이터 draft.logInDone = true; break; /* 로그인 실패 리듀서 */ case LOG_IN_FAILURE: draft.logInLoading = false; draft.logInError = action.error; break; front/sagas/user.js 나의 사용자 정보 불러오기 사가 // loadMyInfo 실행 시 서버에 loadMyInfoAPI 요청 function loadMyInfoAPI() { return axios.get('/user'); } // LOAD_MY_INFO 액션이 실행되면 loadMyInfo 함수 실행 function* loadMyInfo(action) { /* 요청 성공 시 LOAD_MY_INFO_SUCCESS 액션 디스패치 */ try { const result = yield call(loadMyInfoAPI, action.data); yield put({ type: LOAD_MY_INFO_SUCCESS, data: result.data, }); /* 요청 실패 시 LOAD_MY_INFO_FAILURE 액션 디스패치 */ } catch (err) { console.error(err); yield put({ type: LOAD_MY_INFO_FAILURE, error: err.response.data, // 실패 결과 }); } } 로그인 사가 // logIn 실행 시 서버에 logInAPI 요청 function logInAPI(data) { return axios.post('/user/login', data); } // LOG_IN_REQUEST 액션이 실행되면 logIn 함수 실행 function* logIn(action) { /* 요청 성공 시 LOG_IN_SUCCESS 액션 디스패치 */ try { const result = yield call(logInAPI, action.data); yield put({ type: LOG_IN_SUCCESS, data: result.data, // 성공 결과 : 서버로부터 사용자 정보를 받아옴 }); /* 요청 실패 시 LOG_IN_FAILURE 액션 디스패치 */ } catch (err) { console.error(err); yield put({ type: LOG_IN_FAILURE, error: err.response.data, // 실패 결과 }); } } back/routes/user.js 브라우저 새로 고침 시 나의 사용자 정보를 복구하는 라우터 나의 사용자 정보를 복구하는 라우터는 user 라우터들 중에서 제일 위에 위치합니다! // 브라우저 새로고침 시 나의 사용자 정보를 복구하는 라우터 router.get('/', async (req, res, next) => { // GET /user // req.headers 안에 쿠키가 들어있다. console.log(req.headers, "req.headers 안에는 쿠키가 들어있다."); try { /* (로그인해서) 사용자 정보가 있다면 */ if (req.user) { /* (비밀번호를 제외한) 모든 사용자 정보를 가져오는 함수 */ const fullUserWithoutPassword = await User.findOne({ where: { id: req.user.id }, attributes: { exclude: ['password'] }, // 모델 가져오기 include: [{ /* 나의 게시글 */ model: Post, attributes: ['id'], // id 데이터만 가져오기 }, { /* 나의 팔로잉 */ model: User, as: 'Followings', attributes: ['id'], }, { /* 나의 팔로워 */ model: User, as: 'Followers', attributes: ['id'], }] }); // 200번대 에러 출력 res.status(200).json(fullUserWithoutPassword); /* (로그아웃해서) 사용자 정보가 없다면 */ } else { // 아무것도 보내지 않기 res.status(200).json(null); } /* 에러 캐치 */ } catch (error) { console.error(error); next(error); } }); 로그인 라우터 // 로그인 라우터 : 사용자 로그인 전략 실행 router.post('/login', isNotLoggedIn, (req, res, next) => { /* '로컬', (서버 에러, 성공 객체, 클라이언트 에러)가 전달 */ passport.authenticate('local', (err, user, info) => { // done에서 넣은 값들이 순서대로 전달되는 곳 /* 서버 에러 */ if (err) { console.error(err); // 콘솔 창을 통한 에러 메시지 출력 return next(err); // 에러 처리 미들웨어로 이동 } /* 클라이언트 에러 : 로그인하다 에러가 나면 클라이언트로 응답 보내기 */ if (info) { return res.status(401).send(info.reason); } /* 로그인 성공 객체 */ return req.login(user, async (loginErr) => { // 서비스 로그인이 끝난 후 패스포트 로그인 할 때 에러발생 시 처리 if (loginErr) { console.error(loginErr); return next(loginErr); } /* (비밀번호를 제외한) 모든 사용자 정보를 가져오는 함수 */ const fullUserWithoutPassword = await User.findOne({ where: { id: user.id }, attributes: { exclude: ['password'] }, // 전체 데이터에서 비밀번호만 제외 // 모델 가져오기 include: [{ /* 나의 게시글 */ model: Post, attributes: ['id'], // id 데이터만 가져오기 }, { /* 나의 팔로잉 */ model: User, as: 'Followings', attributes: ['id'], }, { /* 나의 팔로워 */ model: User, as: 'Followers', attributes: ['id'], }] }); /* (비밀번호를 제외한) 모든 사용자 정보를 프론트로 넘기기 */ return res.status(200).json(fullUserWithoutPassword); }); })(req, res, next); // 미들웨어 커스터마이징 }); back/routes/middlewares.js 로그인 검사 // (로그인 안했을 때) 로그인 유무 검사 exports.isNotLoggedIn = (req, res, next) => { if (!req.isAuthenticated()) { next(); } else { res.status(401).send('로그인하지 않은 사용자만 접근 가능합니다.'); } }; 문제 해결을 위해 노드버드 커뮤니티에서 저와 비슷한 에러가 발생한 수강생 분이 계셨습니다! https://www.inflearn.com/questions/368573/%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%A7%88%EB%AC%B8-%EB%A1%9C%EA%B7%B8%EC%9D%B8%ED%95%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EC%82%AC%EC%9A%A9%EC%9E%90%EB%A7%8C-%EC%A0%91%EA%B7%BC%EC%9D%B4-%EA%B0%80%EB%8A%A5%ED%95%A9%EB%8B%88%EB%8B%A4 해당 글에서 제로초님은 쿠키가 있는 걸로 봐서 이미 로그인이 된 상태인데 프론트에서 자신이 로그인 되었다는 것을 인식하지 못하고 있으며, 해당 getServerSideProps 쪽에 문제가 있다고 힌트를 주셨습니다! 제로초님의 노드버드Ch7 user/[id].js https://github.com/ZeroCho/react-nodebird/blob/master/ch7/front/pages/user/[id].js front/pages/user/[id].js 강의를 진행하며 깃허브와 약간은 다른 코드가 있습니다. // 서버사이드 렌더링(SSR) : getServerSideProps 사용 /* 사용자 컴포넌트보다 먼저 실행, 매개변수 context 안에 store가 들어있다. */ export const getServerSideProps = wrapper.getServerSideProps(async (context) => { /* 변수 cookie에 모든 cookie 정보 저장 */ const cookie = context.req ? context.req.headers.cookie : ''; /* 쿠키를 안 써서 요청 보낼 때는 서버에서 공유하고 있는 쿠키를 제거하기 */ axios.defaults.headers.Cookie = ''; /* 서버일 때, 그리고 쿠키가 있을 때만 서버로 쿠키 전달하기 */ if (context.req && cookie) { // 실제로 쿠키를 써서 요청을 보낼 때만 잠깐 쿠키를 넣어 놓는다. axios.defaults.headers.Cookie = cookie; } /* 처음에 화면을 로딩하면 특정 사용자의 게시글 불러오기 요청 액션 객체 디스패치 */ context.store.dispatch({ type: LOAD_USER_POSTS_REQUEST, data: context.params.id, // 또는 context.query.id로 useRouter에 접근 가능 }); /* 처음에 화면을 로딩하면 나의 사용자 정보 불러오기 요청 액션 객체 디스패치 */ context.store.dispatch({ type: LOAD_MY_INFO_REQUEST, }); /* 처음에 화면을 로딩하면 다른 사용자 정보 불러오기 요청 액션 객체 디스패치 */ context.store.dispatch({ type: LOAD_USER_REQUEST, data: context.params.id, // 또는 context.query.id로 useRouter에 접근 가능 }); /* 나의 사용자 정보, 다른 사용자 정보 불러오기, 여러 게시글 불러오기 요청(REQUEST)이 성공(SUCCESS)으로 바뀔 때까지 기다리기 */ context.store.dispatch(END); await context.store.sagaTask.toPromise(); console.log('getState', context.store.getState().post.mainPosts); return { props: {} }; }); 리듀서, 사가, 그리고 해당 서버사이드 렌더링 쪽을 점검해보았으나 잘못된 점을 찾지 못하여 질문 남깁니다.. 어떻게 하면 사용자(나)의 로그인이 유지되게 할 수 있을까요? 혹시 힌트 키워드라도 주실 수 있을까요? 긴 질문 글 읽어주셔서 감사합니다 제로초님 항상 강의 잘 보고 있습니다!

  • react
  • redux
  • node.js
  • express
  • next.js
이가은 댓글 3 좋아요 1 조회수 2616

포트폴리오 리뷰라는게

해결됨

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

제가 만든 코드랑 다르다면 깃허브에 있는 코드로 수정해야되나요 아니면 깃허브에 있는 코드를 가져와서 강의 시청만 하는건가요?

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

test 수업에서 eslint 오류

해결됨

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

이런 오류가 뜨는데 무엇때문인가요?

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

게시글 업로드 성공시 setQueryData 질문

해결됨

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

안녕하세요!! 궁금한 점이 하나 있습니다. 강사님은 게시글 업로드 성공시 setQueryData로 응답값을 넣어주셨는데 혹시 invalidateQueries로 데이터를 다시 불러오는 것은 어떻게 생각하시나요?

  • react
  • next.js
  • react-query
  • next-auth
  • msw
sjh-98 댓글 1 좋아요 0 조회수 374

@ManyToOne 매핑 질문입니다.

미해결

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

게시글과 댓글을 매핑 하려고 하는데 게시글에 어떤 댓글이 달렸는지 조회 하기 위해 게시글 -> 댓글 OneToMany 단방향 매핑을 하려고 했더니, @OneToMany는 지양하라고 해서 댓글에 @ManyToOne 매핑을 하려고 했는데요. 이러면 댓글->게시글 단방향이 되는 것 아닌가요? 게시글에 어떤 댓글이 있는지 확인을 하고 싶을 뿐인데 ManyToOne을 지양하는 이럴 땐 어떻게 해야하는지 궁금합니다 .. 매핑이 아니라 차라리 int communitySeq 를 멤버 변수로 갖도록 하고 jpql에서 join문을 통해 데이터를 가져오는 것이 맞을까요??

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
댓글 1 좋아요 0 조회수 300

OpenJDK 64-bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended경고가 뜹니다.

미해결

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) A. 네 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) A. 아니요 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) A. 네 [질문 내용] 테스트 코드 실행을 하면 OpenJDK 64-bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended 이 경고가 계속 뜹니다. https://www.inflearn.com/questions/917150/openjdk-64-bit-server-vm-warning 찾아보면서 이 답변을 따라해도 로그가 뜨지 않고 경고가 뜨는데 어떻게 해야하나요?

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
jaemoon 댓글 4 좋아요 0 조회수 13564

접근 제어자 문제 풀이

해결됨

김영한의 실전 자바 - 기본편

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 문제 풀이를 다음 날 새로 만들어서 풀어보니까 조금 다른 부분이 생겼는데 1. 본인 2. 강의 각 배열의 총 가격 값만 더하는 거라면 1번처럼 하는 게 좋아 보이는데 Item item = items[i];를 추가하신 이유와 어떤 차이점이 있는지 궁금해요

  • java
  • 객체지향
ᄒᄉ 댓글 1 좋아요 1 조회수 272

로그인 버튼 클릭시 500에러 발생

미해결

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

아이디, 비밀번호를 입력하고 로그인 버튼을 누르면 500에러가 발생합니다. 9090 서버 포트는 잘 켜져있다고 뜨고, 코드 올리겠습니다. <auth.ts> import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import KakaoProvider from "next-auth/providers/kakao"; export const { handlers: { GET, POST }, auth, signIn, } = NextAuth({ pages: { signIn: "/i/flow/login", newUser: "i/flow/signup", }, providers: [ CredentialsProvider({ async authorize(credentials) { // credentials 안에 id창에서 입력하는 정보다 담겨있음 const authResponse = await fetch(`${process.env.AUTH_URL}/api/login`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: credentials.username, password: credentials.password, //next-auth의 credentials에는 username, password로 고정되어 있어서 이를 바꿔줌 }), }); //로그인 실패시 if (!authResponse.ok) { return null; } const user = await authResponse.json(); return user; }, }), //kakao로그인을 사용할때 // KakaoProvider(), ], }); <LoginModal.tsx> "use client"; import style from "@/app/(beforeLogin)/_component/login.module.css"; import { signIn } from "next-auth/react"; import { useRouter } from "next/navigation"; import { ChangeEventHandler, FormEventHandler, useState } from "react"; export default function LoginModal() { const [id, setId] = useState(""); const [password, setPassword] = useState(""); const [message, setMessage] = useState(""); const router = useRouter(); const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => { e.preventDefault(); setMessage(""); try { await signIn("credentials", { username: id, password, redirect: false, }); //kakao, naver로 바꿀 수 있음 //client 일때는 next-auth/react의 signIn을 사용 //server 일때는 @/auth의 signIn을 사용 router.replace("/home"); } catch (error) { console.log(error); setMessage("아이디와 비밀번호가 일치하지 않습니다."); } }; const onClickClose = () => { router.back(); }; const onChangeId: ChangeEventHandler<HTMLInputElement> = (e) => { setId(e.target.value); }; const onChangePassword: ChangeEventHandler<HTMLInputElement> = (e) => { setPassword(e.target.value); }; return ( <div className={style.modalBackground}> <div className={style.modal}> <div className={style.modalHeader}> <button className={style.closeButton} onClick={onClickClose}> <svg width={24} viewBox="0 0 24 24" aria-hidden="true" className="r-18jsvk2 r-4qtqp9 r-yyyyoo r-z80fyv r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-19wmn03" > <g> <path d="M10.59 12L4.54 5.96l1.42-1.42L12 10.59l6.04-6.05 1.42 1.42L13.41 12l6.05 6.04-1.42 1.42L12 13.41l-6.04 6.05-1.42-1.42L10.59 12z"></path> </g> </svg> </button> <div>로그인하세요.</div> </div> <form onSubmit={onSubmit}> <div className={style.modalBody}> <div className={style.inputDiv}> <label className={style.inputLabel} htmlFor="id"> 아이디 </label> <input id="id" className={style.input} value={id} onChange={onChangeId} type="text" placeholder="" /> </div> <div className={style.inputDiv}> <label className={style.inputLabel} htmlFor="password"> 비밀번호 </label> <input id="password" className={style.input} value={password} onChange={onChangePassword} type="password" placeholder="" /> </div> </div> <div className={style.message}>{message}</div> <div className={style.modalFooter}> <button className={style.actionButton} disabled={!id && !password}> 로그인하기 </button> </div> </form> </div> </div> ); } <middleware.ts> export { auth as middleware } from "./auth"; export const config = { matcher: ["/compose/tweet", "/home", "/explore", "/messages", "/search"], }; <route.ts> export { GET, POST } from "@/auth"; 에러 내용 : TypeError: next_dist_server_web_exports_next_request__WEBPACK_IMPORTED_MODULE_0__ is not a constructor at reqWithEnvURL (webpack-internal:///(rsc)/./node_modules/next-auth/lib/env.js:15:12) at httpHandler (webpack-internal:///(rsc)/./node_modules/next-auth/index.js:139:139) at /Users/imhwarang/projects/zerocho/z-com/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:63815 at /Users/imhwarang/projects/zerocho/z-com/node_modules/next/dist/server/lib/trace/tracer.js:133:36 at NoopContextManager.with (/Users/imhwarang/projects/zerocho/z-com/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:7062) 너무 길어서 다 올릴수는 없네요 에러내용을

  • react
  • next.js
  • react-query
  • next-auth
  • msw
화랑 댓글 3 좋아요 0 조회수 1237

[CallbackRouter Error] 회원가입->DB입력 성공-> 자동로그인 안됨

미해결

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

회원가입 성공 status: 201전달받고, 회원가입 성공하면 전달받는 리턴객체도 잘 전달받았는데, signIn이 동작하지 않는거 같습니다. PostgreSQL 디비들어가서 보면 User테이블에 신규가입된 정보잘 입력되어있습니다. packge.json "dependencies": { "@auth/core": "^0.18.0", "@faker-js/faker": "^8.3.1", "@tanstack/react-query": "^5.17.10", "@tanstack/react-query-devtools": "^5.17.10", "classnames": "^2.4.0", "dayjs": "^1.11.10", "next": "^14.0.4", "next-auth": "^5.0.0-beta.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-intersection-observer": "^9.5.3" }, "devDependencies": { "@mswjs/http-middleware": "^0.9.2", "@types/cors": "^2.8.17", "@types/express": "^4.17.21", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", "cors": "^2.8.5", "eslint": "^8", "eslint-config-next": "^14.0.4", "express": "^4.18.2", "msw": "^2.0.12", "typescript": "^5" }, "msw": { "workerDirectory": "public" } } [auth][error] CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror [auth][cause]: TypeError: fetch failed at node:internal/deps/undici/undici:12344:11 [auth][details]: { "name": "HeadersTimeoutError", "code": "UND_ERR_HEADERS_TIMEOUT", "message": "Headers Timeout Error", "provider": "credentials" } CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror at Module.callback (webpack-internal:///(action-browser)/./node_modules/@auth/core/lib/actions/callback/index.js:307:23) at async AuthInternal (webpack-internal:///(action-browser)/./node_modules/@auth/core/lib/index.js:65:24) at async Auth (webpack-internal:///(action-browser)/./node_modules/@auth/core/index.js:123:29) at async signIn (webpack-internal:///(action-browser)/./node_modules/next-auth/lib/actions.js:55:17) at async onSubmit (webpack-internal:///(action-browser)/./src/app/(beforeLogin)/_lib/signup.ts:53:9) at async /Users/jungjuyoung/dev/x-clone/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:39:406 at async t0 (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:38:5773) at async rh (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:39:23636) at async doRender (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/server/base-server.js:1391:30) at async cacheEntry.responseCache.get.routeKind (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/server/base-server.js:1552:28) at async DevServer.renderToResponseWithComponentsImpl (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/server/base-server.js:1460:28) at async DevServer.renderPageComponent (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/server/base-server.js:1843:24) at async DevServer.renderToResponseImpl (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/server/base-server.js:1881:32) at async DevServer.pipeImpl (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/server/base-server.js:909:25) at async NextNodeServer.handleCatchallRenderRequest (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/server/next-server.js:266:17) at async DevServer.handleRequestImpl (/Users/jungjuyoung/dev/x-clone/node_modules/next/dist/server/base-server.js:805:17) { type: 'CallbackRouteError', kind: 'error', [cause]: { err: TypeError: fetch failed at node:internal/deps/undici/undici:12344:11 { cause: [HeadersTimeoutError] }, name: 'HeadersTimeoutError', code: 'UND_ERR_HEADERS_TIMEOUT', message: 'Headers Timeout Error', provider: 'credentials' } }

  • react
  • next.js
  • react-query
  • next-auth
  • msw
라푼젤 댓글 4 좋아요 0 조회수 1167

안녕하세요 Next-auth 질문을 올려봅니다.

미해결

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

next-auth로 로그인하기의 강의를 듣던 도중 오류가 생겨 게시판에 글을 남겨봅니다. 문제는 Login 모달에서 로그인을 하였을 때 http://localhost:3000/api/auth/error 로 페이지가 이동 되어집니다. next-auth "next-auth": "^5.0.0-beta.3", .env .env.local 에 AUTH_URL=http://localhost:9090 를 넣어 두었고 route.ts export { GET, POST } from "@/auth"; handlers.ts import { http, HttpResponse, StrictResponse } from "msw"; import { faker } from "@faker-js/faker"; const User = [ { id: "zeroCho", nickName: "zero", image: "/yRsRRjGO.jpg" }, ]; export const handlers = [ // 로그인 http.post("/api/login", () => { console.log("로그인"); return HttpResponse.json(User[1], { headers: { "Set-Cookie": "connect.sid=msw-cookie;HttpOnly;Path=/", // Http cookie 넣어주기 }, }); }), // 로그아웃 http.post("/api/logout", () => { console.log("로그아웃"); return new HttpResponse(null, { headers: { "Set-Cookie": "connect.sid=;HttpOnly;Path=/;Max-Age=0", }, }); }), // 회원 가입 http.post("/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=/;Max-Age=0", }, }); }), ]; auth.ts import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; 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.AUTH_URL}/api/login`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id: credentials.username, password: credentials.password, }), }); if (!authResponse.ok) { return null; } const user = await authResponse.json(); return { email: user.id, name: user.nickname, image: user.image, ...user, }; }, }), ], }); LoginModal.tsx "use client"; import React, { ChangeEventHandler, FormEventHandler, useState } from "react"; import styles from "./loginModal.module.css"; import { redirect, useRouter } from "next/navigation"; // client import { signIn } from "next-auth/react"; export function LoginModal() { const [id, setId] = useState<string>(""); const [password, setPassword] = useState<string>(""); const [message, setMessage] = useState<string>(""); const router = useRouter(); const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => { e.preventDefault(); setMessage(""); try { await signIn("credentials", { username: id, password, redirect: false, }); router.replace("/home"); } catch (err) { console.error(err); setMessage("아이디와 비밀번호가 일치하지 않습니다."); } }; const onClickClose = () => { router.back(); }; const onChangeId: ChangeEventHandler<HTMLInputElement> = (e) => { setId(e.target.value); }; const onChangePassword: ChangeEventHandler<HTMLInputElement> = (e) => { setPassword(e.target.value); }; return ( <div className={styles.modalBackground}> <div className={styles.modal}> <div className={styles.modalHeader}> <button className={styles.closeButton} onClick={onClickClose}> <svg width={24} viewBox="0 0 24 24" aria-hidden="true" className="r-18jsvk2 r-4qtqp9 r-yyyyoo r-z80fyv r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-19wmn03" > <g> <path d="M10.59 12L4.54 5.96l1.42-1.42L12 10.59l6.04-6.05 1.42 1.42L13.41 12l6.05 6.04-1.42 1.42L12 13.41l-6.04 6.05-1.42-1.42L10.59 12z"></path> </g> </svg> </button> <div>로그인하세요.</div> </div> <form onSubmit={onSubmit}> <div className={styles.modalBody}> <div className={styles.inputDiv}> <label className={styles.inputLabel} htmlFor="id"> 아이디 </label> <input id="id" className={styles.input} value={id} onChange={onChangeId} type="text" placeholder="" /> </div> <div className={styles.inputDiv}> <label className={styles.inputLabel} htmlFor="password"> 비밀번호 </label> <input id="password" className={styles.input} value={password} onChange={onChangePassword} type="password" placeholder="" /> </div> </div> <div className={styles.message}>{message}</div> <div className={styles.modalFooter}> <button className={styles.actionButton} disabled={!id && !password}> 로그인하기 </button> </div> </form> </div> </div> ); } 혹시 같은 문제를 겪으신 분이 있었을까요? 아니면 겪으신 분 중에 해결 하신 분이 있으면 도움 부탁드립니다.

  • react
  • next.js
  • react-query
  • next-auth
  • msw
jaeyong Kim 댓글 3 좋아요 3 조회수 1421

인기 태그

인프런 TOP Writers

주간 인기글