inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

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

refreshToken 저장의 문제

해결됨

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

아래에 질문이 있으나 해결안이 없어 다시 문의드립니다. refreshToken, 쿠키는 정상적으로 전달되고 있습니다. setCookie도 나옵니다. 그러나, Application에 나타나지 않습니다. 그리고 조금 기다렸다가 acessToken을 재발급하려고 클릭하면 아래와 같은 메시지가 나타납니다. 크롬에서 써드파티 쿠키를 다 accept하도록 설정이 되어있고, 시크릿 모드에서도 진행해봤고 사파리에서도 동일합니다. 클릭하여 나타난 통신기록을 총 3번입니다. 첫번째 통신은 accessToken만료로 발생한 것으로 보입니다. 네트워크 통신기록을 살펴보면 UNAUTHENTICATED가 발생된 것을 알수 있습니다. 두번째 통신은 restoreAccessToken의 뮤테이션입니다. 헤더와 페이로드는 아래와 같습니다. jwt가 첨부되지 않았다는 부분입니다. 3번째 통신의 Header와 payload, response입니다. 이 부분은 주어진 조건으로 사용자 정보를 불러오는 query같습니다. 사용자에 관련된 정보가 없이 시도되어 _id null이 표시된것 같습니다. 인터넷에 검색해보았지만 잘 모르겠습니다. axios통신으로 refreshToken을 직접 저장해주는 코드를 보긴 했는데, graphql은 설정만 바꾼다고 하셔서 refreshToken을 어떻게 처리하는지 잘 모르겠습니다. 관련해서 검색을 통해 https로 환경을 바꾸면 될거다 하여, localhost:3000을 mkcert로 https로 환경을 바꾸려고 해봤는데 설치만 하고 아래의 글을 발견해서 잠깐 멈추었습니다. https://shingy.tistory.com/46 _id null의 문제가 local에 받아온 쿠키를 저장하지 못하는 문제인것 같은데, 어떻게 처리할수있는 방법이 있나 싶어서 여쭤봅니다. 코드 getAccessToken의 코드 import { GraphQLClient, gql } from "graphql-request"; import { IMutation } from "../../../commons/types/generated/types"; const RESTORE_ACCESS_TOKEN = gql` mutation { restoreAccessToken { accessToken } } `; export const getAccessToken = async (): Promise<string | undefined> => { try { const graphQLClient = new GraphQLClient( "https://backend-practice.codebootcamp.co.kr/graphql", { credentials: "include" }, ); const result = await graphQLClient.request<Pick<IMutation, "restoreAccessToken">>( RESTORE_ACCESS_TOKEN, ); const newAccessToken = result.restoreAccessToken.accessToken; return newAccessToken; } catch (error) { if (error instanceof Error) console.log(error); } }; 아폴로 클라이언트 코드 import { ApolloClient, InMemoryCache, ApolloProvider, ApolloLink, fromPromise, } from "@apollo/client"; import { createUploadLink } from "apollo-upload-client"; import { useRecoilState } from "recoil"; import { accessTokenState } from "../../../commons/store"; import { useEffect } from "react"; import { ErrorResponse, onError } from "@apollo/client/link/error"; import { getAccessToken } from "../libraries/getAccessToken"; const GLOBAL_STATE = new InMemoryCache(); interface IApolloSettingProps { children: JSX.Element; } export default function ApolloSetting(props: IApolloSettingProps) { const [accessToken, setAccessToken] = useRecoilState(accessTokenState); useEffect(() => { const result = localStorage.getItem("accessToken"); console.log(result); console.log("현재는 브라우저입니다"); setAccessToken(result ?? ""); }, []); const errorLink = onError(({ graphQLErrors, operation, forward }) => { //1-1.에러캐치 if (typeof graphQLErrors !== "undefined") { for (const err of graphQLErrors) { //1-2.토큰 만료에러인지 체크 if (err.extensions?.code === "UNAUTHENTICATED") { return fromPromise( getAccessToken() .then((newAccessToken) => { setAccessToken(newAccessToken ?? ""); operation.setContext({ headers: { ...operation.getContext().headers, Authorization: `Bearer ${newAccessToken}`, }, }); }) .catch((err) => { console.log("오류입니다"); }), ).flatMap(() => forward(operation)); } } } }); const uploadLink = createUploadLink({ uri: "https://backend-practice.codebootcamp.co.kr/graphql", headers: { Authorization: `Bearer ${accessToken}`, credentials: "include", }, }); const client = new ApolloClient({ link: ApolloLink.from([errorLink, uploadLink]), uri: "http://backend-practice.codebootcamp.co.kr/graphql", cache: GLOBAL_STATE, }); return <ApolloProvider client={client}>{props.children}</ApolloProvider>; } 로그인 success의 코드 import { gql, useApolloClient, useQuery } from "@apollo/client"; import type { IQuery } from "../../../src/commons/types/generated/types"; import { wrapAsync } from "../../../src/components/commons/libraries/asyncFunt"; const FETCH_USER_LOGGED_IN = gql` query fetchUserLoggedIn { fetchUserLoggedIn { email name } } `; export default function LoginPage() { const client = useApolloClient(); const onClickButton = async (): Promise<void> => { const result = await client.query({ query: FETCH_USER_LOGGED_IN, }); console.log(result); }; return ( <> {/* <div>{data?.fetchUserLoggedIn.name}님, 환영합니다.</div> */} <div>환영</div> <button onClick={wrapAsync(onClickButton)}>클릭하세요</button> </> ); }

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

멀티모듈 구성 강의에 대해 질문이 있습니다.

해결됨

서버개발자 과제전형 완벽가이드 - 1편

멀티모듈 구성 강의에 대해 질문잉 이씁니다. 해당 강의에서 모듈 만들 때 아래처럼 파일 디렉토리가 되어있는데요. search-api ├── src │ ├── main │ │ ├── java │ │ ├── resources │ ├── test ├── build.gradle 제가 만들때는 아래 처럼 됩니다. 저는 왜 선생님 처럼 java로 모듈을 만들면 src 폴더에 아래 파일이 안생기고 lib 폴더만 생기는 이유가 뭘까요? │ ├── java │ │ ├── resources │ ├── test ├── build.gradle 저는 모듈 구성할 때 아래와 같은 창이 나오는데요. 아래에서 grovy를 체크(아래 사진에서 파란색바탕부분임. 아래사진은 안되어있지만 체크함.)했는데 체크 안하고 진행해야 하나요? 참고로 선생님 강의 44초에는 grovy 선택하는 구간이 나와서 저도 체크했어요. 제화면 선생님 화면 참고로 1. IDE에서 자동 생성 옵션 활성화 https://tychejin.tistory.com/340 이링크에 나와있는데로 세팅함. build.gradle을 아래처럼 세팅했습니다. 위 방법 실행 후 ./gradlew clean build 이 명령어 실행 프로젝트를 새로 열기 plugins { id 'java' id 'org.springframework.boot' version '3.3.9' id 'io.spring.dependency-management' version '1.1.7' } group = 'com.example' version = '0.0.1-SNAPSHOT' java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() } sourceSets { main { java { srcDirs = ['src/main/java'] } resources { srcDirs = ['src/main/resources'] } } test { java { srcDirs = ['src/test/java'] } resources { srcDirs = ['src/test/resources'] } } } 캐시 삭제 후 재 진행 File → Invalidate Caches / Restart 클릭 "Invalidate and Restart" 선택 IntelliJ가 다시 시작되면 Gradle 탭에서 "Reload Gradle Project" 버튼(↻ 아이콘) 클릭 참고로 인텔리제이 2021 얼티미디엇 버전입니다. 위에 파일 아래 메일로 보냈습니다. 혹시 문제점이 있는지 봐주실 수 있으신가요? jaytech108@gmail.com

  • java
  • spring
  • spring-boot
  • database
zzzzz 댓글 3 좋아요 0 조회수 259

5.4) Props로 데이터 전달하기 Button 추가 시 서버가 응답을 하지 않습니다.

해결됨

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

commponents 폴더 하위에 Button.jsx 파일을 만들고 const Button = () => { return <Button>Click</Button>; }; export default Button; 이렇게 입력한 후에 App.jsx에서 import "./App.css"; import Header from "./commponents/Header.jsx"; import Footer from "./commponents/Footer.jsx"; import Main from "./commponents/Main.jsx"; import Button from "./commponents/Button.jsx"; function App() { return ( <> <Button /> <Button /> <Button /> </> ); } export default App; 이렇게 입력하고 새로고침을 하면 계속 이렇게 나오는데 왜 그런걸까요. 🚨 아래의 가이드라인을 꼭 읽고 질문을 올려주시기 바랍니다 🚨 질문 하시기 전에 꼭 확인해주세요 - 질문 전 구글에 먼저 검색해보세요 (답변을 기다리는 시간을 아낄 수 있습니다) - 코드에 오타가 없는지 면밀히 체크해보세요 (Date와 Data를 많이 헷갈리십니다) - 이전에 올린 질문에 달린 답변들에 꼭 반응해주세요 (질문에 대한 답변만 받으시고 쌩 가시면 속상해요 😢) 질문 하실때 꼭 확인하세요 - 제목만 보고도 무슨 문제가 있는지 대충 알 수 있도록 자세한 제목을 정해주세요 (단순 단어 X) - 질문의 배경정보를 제공해주세요 (이 문제가 언제 어떻게 발생했고 어디까지 시도해보셨는지) - 문제를 재현하도록 코드샌드박스나 깃허브 링크로 전달해주세요 (프로젝트 코드에서 문제가 발생할 경우) - 답변이 달렸다면 꼭 확인하고 반응을 남겨주세요 - 강의의 몇 분 몇 초 관련 질문인지 알려주세요! - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

  • javascript
  • react
  • node.js
이성 댓글 3 좋아요 0 조회수 224

k가 0일 경우에

미해결

자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비

안녕하세요 선생님. 수업 정말 잘 듣고 있습니다. 이번 문제 조건에 첫번째 줄에 수열의 길이에대한 조건만 있고 k에대한 조건이 없어서 문제의 예시로 나온 수열에서 k에 0을 넣고 코드를 실행 시켜봤는데 정답 코드에서 잘못된 답을 주고 있어서 문의 드립니다. 혹시 k에대한 조건이 1 이상인가요? 아래 입력대로라면 정답은 2가 나와야할 것 같아서 문의 드립니다. 0 0 0 0 1 1 0 1 1 0 1 1 0 1 입력 14 0 0 0 0 0 1 1 0 1 1 0 1 1 0 1 public int solution(int[] input, int length, int k) { int lt = 0; int max = Integer.MIN_VALUE; int cnt = 0; for (int rt = 0; rt < length; rt++) { if (input[rt] == 0) cnt ++; while (cnt > k) { if (input[k] == 0) cnt--; lt ++; } max = Math.max(max, rt - lt + 1); } return max; }

  • java
  • 코딩-테스트
임인혁 댓글 2 좋아요 0 조회수 104

자동으로 import 되는 패키지 관련 문의

해결됨

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

안녕하세요 덕분에 좋은 강의 잘 듣고 있습니다! next.js 강의의 2.9 의 14분 가량 보면 <Link> 태그 입력하면 자동으로 import 문이 작성되는데 어떤 패키지를 쓰시는건지 물어봐도 될까요?

  • react
  • typescript
  • next.js
황일환 댓글 2 좋아요 0 조회수 146

인텔리제이에서 실행이 안됩니다..

미해결

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

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. > Task :prepareKotlinBuildScriptModel UP-TO-DATE Could not resolve: org.springframework.boot:spring-boot-starter-thymeleaf Could not resolve: org.springframework.boot:spring-boot-starter-web Could not resolve: org.springframework.boot:spring-boot-starter-test [Incubating] Problems report is available at: file:///C:/hello-spring/build/reports/problems/problems-report.html 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.12.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation. BUILD SUCCESSFUL in 1s 이러한 오류가 떠ㅏ서 진행을 못하고 있습니다. 2일째 고생중인데 도와주세요

  • java
  • spring
  • mvc
  • spring-boot
이재문 댓글 2 좋아요 0 조회수 838

[해결완료] 실습용 백엔드 서버 연결 오류

해결됨

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

혹시나 아래와 같은 오류가 발생하시는 분들중에 비밀번호도 다 알맞게 설정했는데 오류가 발생하신다면 supabase에 새로운 project를 생성하여 시도 해보시는 것도 좋을 것 같아요! 계속 안 되다가 새로 만들어서 시도했더니 되네요...ㅠㅠ 며칠동안 해결하려고 노력했다가 log보고 그냥 다시 만들어볼까해서 시도해봤는데 해결했습니다..ㅎ 다른 분들이 올려주신 오류와 유사하게 supabase와 연결하는 과정에서 오류가 발생합니다. supabase database log를 확인하였을 때에 error는 확인되지 않고, 비밀번호를 수정해봐도 오류가 바뀌지 않습니다. 비밀번호가 틀릴 경우에도 log에 error는 확인되지 않는걸까요?

  • react
  • typescript
  • next.js
하늘 댓글 2 좋아요 0 조회수 414

기출문제나 모의고사

해결됨

(2026 최신!) 일주일만에 합격하는 정보처리기사 실기

선생님 안녕하세요 혹시 강의 관련해서 강의업데이트나 이전 기출, 모의고사처럼 문제가 더 업데이트될까요? 문제모음 같이 해당문제지와 영상이 있으면 좋을 것 같아 여쭤봐요

  • python
  • java
  • c
  • 정보처리기사
rsrarsra 댓글 2 좋아요 0 조회수 126

양방향 연관관계가 아닌 단방향 연관관계일때도

미해결

자바 ORM 표준 JPA 프로그래밍 - 기본편

안녕하세요. 양방향 연관관계 일때만 연관관계의 주인 이라는 개념이 있는줄 알았는데, 양방향 연관관계 뿐만 아니라 단방향 연관관계에서도 연관관계의 주인이라는 개념이 있는건가요?

  • java
  • jpa
오리쉐리 댓글 1 좋아요 0 조회수 74

이거 맞아요?

해결됨

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

이런식으로 서비스 밑의 폴더 이어 붙이기 하고 article 따로 service 따로 서버 실행할수 있게 되면 그게 msa 기본 구조 잡아가는 과정인가요? 지금 막 우당탕탕 이렇게 저렇게 막 코드 붙여가면서 되는거 같기는 한데 뭐 하고 있는지 헷갈리고 어지러워요

  • java
  • mysql
  • spring-boot
  • kafka
  • redis
dktmvktm 댓글 1 좋아요 0 조회수 237

피그마 링크는 어디 있을까요?!

해결됨

[코드캠프] 부트캠프에서 만든 '완벽한' 프론트엔드 코스

피그마 링크를 못찾겠어요ㅠ 이미지 다운 받아야 하는데 어디서 볼 수 있을까요?

  • react
  • react-native
  • 하이브리드-앱
  • graphql
  • next.js
skykwj0422 댓글 2 좋아요 0 조회수 179

컴포넌트 외부에 선언한 함수에 대하여 질문드립니다.

해결됨

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

안녕하세요 강의 재밌게 잘 듣고 있습니다~ 수업 내용 중 getMonthlyData은 Home 컴포넌트 외부에, getSortedData는 DiaryList 컴포넌트 내부에 작성하셨는데요. 이전 강의 내용에 따르면 getMonthlyData를 컴포넌트 외부에 작성하신 이유는 Home 컴포넌트가 재렌더링 될 때 다시 선언할 필요가 없어서가 맞나요?? 그렇다면 비슷한 이유로 getSortedData도 컴포넌트 외부에 작성 가능할 것 같은데 안쪽에 작성하신 이유가 궁금합니다. props를 받아서 계산하고 있긴 하지만 인자값으로 넘겨주면 될 것 같아서요 감사합니다.

  • react
훗추추 댓글 1 좋아요 1 조회수 115

[5-4]글 수정/삭제 기능 구현하기(2) - API연동 부분에서 수정하기 누르면 제목과 내용이 비어있는데요,,, 한번 더 수정하기 눌러야 이전 제목과, 내용이 나옵니다...

미해결

아바타 커뮤니티앱 만들기 (React Native Expo)

import CustomButton from "@/components/CustomButton"; import DescriptionInput from "@/components/DescriptionInput"; import TitleInput from "@/components/TitleInput"; import { ImageUri } from "@/types"; import { router, useLocalSearchParams, useNavigation } from "expo-router"; import { useEffect } from "react"; import { FormProvider, useForm } from "react-hook-form"; import { StyleSheet,View } from "react-native"; import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"; import useGetPost from "@/hooks/queries/useGetPost"; import useUpdatePost from "@/hooks/queries/useUpdatePost"; type FormValues= { title:string; description: string; imageUris:ImageUri[]; }; export default function PostUpdateScreen () { const {id} = useLocalSearchParams(); const navigation = useNavigation(); const {data:post} = useGetPost(Number(id)); const updatePost = useUpdatePost(); const postForm = useForm<FormValues>({ defaultValues:{ title:post?.title, description:post?.description, imageUris:post?.imageUris, }, }); const onSubmit = (formValues: FormValues)=> { updatePost.mutate({ id: Number(id), body: formValues, },{ onSuccess:() => router.back(), } ); }; useEffect(()=>{ navigation.setOptions({ headerRight:() => ( <CustomButton label="저장" size="medium" variant="standard" onPress={postForm.handleSubmit(onSubmit)} /> ), }); },[]); return( <FormProvider {...postForm}> <KeyboardAwareScrollView contentContainerStyle={styles.container}> <TitleInput /> <DescriptionInput /> </KeyboardAwareScrollView> </FormProvider> ); } const styles = StyleSheet.create({ container:{ margin:16, gap:16, }, });

  • javascript
  • react
  • react-native
  • typescript
  • react-query
ksw 댓글 3 좋아요 0 조회수 298

PK 전략에 관련해서 질문 드립니다!

해결됨

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

안녕하세요. 만 1년된 작은 중소기업에서 일하고 있는 개발자입니다. 강의 잘 듣고 있습니다! 현재 회사에서는 오라클 데이터베이스를 사용하고 있고 최근 스프링부트와 JPA를 사용해서 프로젝트를 시작했고, 낡은 레거시 사업을 영위하는 업체라서 이게 회사의 첫 스프링부트 프로젝트입니다! 나름 새로운 기술스택을 제안했기에 가지는 부담감이 심한데요. 최근에 만든 거의 대부분의 프로젝트들은 단일 DB를 사용하고 있기 때문에 별다른 고민 없이 AutoIncrement를 선택했습니다. 오라클에서도 최신 버전에서는 잘 지원해주고 있고 DB 버전은 높았기 때문에 이에 익숙해서 JPA에서 지원하는 IDENTITY 전략을 사용해서 시스템을 만들었는데요. 현재 ID를 노출해야하는 상황이 생길 경우 이를 그대로 노출하고 있습니다. 다른 PK 전략을 사용하지 않고 보완할 수 있는 방법이 있을까요? 현재 떠오르는것은 외부로 노출할 때 컨트롤러에서 이를 해싱하거나 난수화를 하는 방법을 생각하고 있습니다. 감사합니다!

  • java
  • mysql
  • spring-boot
  • kafka
  • redis
wisehero 댓글 2 좋아요 0 조회수 226

Gitlab 소스코드 접속이 안됩니다

해결됨

[말 한마디로 뚝딱!] AI와 함께 나만의 수익화 웹사이트를 만드는 법

안녕하세요 강의 1강에 있는 완성코드 접속 했는데 프론트 , 백 둘 다 아래처럼 404 page가 나옵니다 확인 해주시면 감사하겠습니다

  • HTML/CSS
  • java
  • mysql
  • php
미다스 댓글 2 좋아요 1 조회수 216

cpu 스케줄링

미해결

자바 코딩테스트 - it 대기업 유제

package chapter3.sol5_cpu_스케줄링; import java.util.*; public class Solution { public int[] solution(int[][] tasks) { int[] answer = new int[tasks.length]; Queue<int[]> q = new PriorityQueue<>(Comparator.comparingInt((int[] a) -> a[1]).thenComparingInt(a -> a[0])); int[] ch = new int[tasks.length]; for (int s = 0, i = 0; ; s++) { for (int j = 0; j < tasks.length; j++) { if (tasks[j][0] <= s && ch[j] == 0) { q.offer(new int[] {j, tasks[j][1]}); ch[j] = 1; } } if (!q.isEmpty()) { int[] poll = q.poll(); answer[i++] = poll[0]; s += poll[1] - 1; } if (i == tasks.length) break; } return answer; } public static void main(String[] args) { Solution T = new Solution(); System.out.println(Arrays.toString(T.solution(new int[][] {{2, 3}, {1, 2}, {8, 2}, {3, 1}, {10, 2}}))); System.out.println(Arrays.toString(T.solution(new int[][] {{5, 2}, {7, 3}, {1, 3}, {1, 5}, {2, 2}, {1, 1}}))); System.out.println( Arrays.toString(T.solution(new int[][] {{1, 2}, {2, 3}, {1, 3}, {3, 3}, {8, 2}, {1, 5}, {2, 2}, {1, 1}}))); System.out.println(Arrays.toString(T.solution(new int[][] {{999, 1000}, {996, 1000}, {998, 1000}, {999, 7}}))); } } 안녕하세요 정답 코드가 아닌 이 코드도 가능한지 궁금합니다!

  • java
  • 코딩-테스트
cherryjuice 댓글 2 좋아요 0 조회수 118

req.cookies.token == undefined 현상

해결됨

React, Node.js, MongoDB로 만드는 나만의 회사 웹사이트: 완벽 가이드

logout을 해보니 400BadRequest:이미 로그아웃 됨 상태가 지속됩니다. console.log(req.cookies.token); 출력해보니 undefined 라고 출력됩니다. 쿠키를 제대로 읽지 못하는것 같은데 왜 이런 현상이 뜨는지 궁금합니다.. const express = require("express"); const router = express.Router(); const bcrypt = require("bcrypt"); const User = require("../models/User"); const axios = require("axios"); const jwt = require("jsonwebtoken"); router.post("/signup", async (req, res) => { try { const { username, password } = req.body; const existingUser = await User.findOne({ username }); if (existingUser) { return res.status(400).json({ message: "이미 존재하는 사용자입니다." }); } const hashedPassword = await bcrypt.hash(password, 10); const user = new User({ username, password: hashedPassword, }); await user.save(); res.status(201).json({ message: "회원가입이 완료되었습니다." }); } catch (error) { res.status(500).json({ message: "서버 오류가 발생했습니다." }); console.log(error); } }); router.post("/login", async (req, res) => { try { const { username, password } = req.body; const user = await User.findOne({ username }).select("+password"); //왜인지 password가 select되지 않아서 추가함 if (!user) { return res.status(401).json({ message: "존재하지 않는 사용자입니다." }); } if (!user.isActive) { return res.status(401).json({ message: "비활성화된 사용자입니다." }); } if (user.isLoggedIn == true) { return res.status(401).json({ message: "이미 접속 중인 사용자입니다." }); } const isValidPassword = await bcrypt.compare(password, user.password); //비밀번호 비교 if (!isValidPassword) { user.failedLoginAttempts += 1; user.lastLoginAttempt = new Date(); if (user.failedLoginAttempts >= 5) { user.isActive = false; //다섯번 틀리면 계정 비활성화 ㅋㅋ await user.save(); return res.status(401).json({ message: "비밀번호를 5회 이상 틀려 계정이 비활성화되었습니다.", }); } await user.save(); return res.status(401).json({ message: "비밀번호가 일치하지 않습니다.", remainingAttempts: 5 - user.failedLoginAttempts, }); } user.failedLoginAttempts = 0; user.lastLoginAttempt = new Date(); user.isLoggedIn = true; try { const response = await axios.get("https://api.ipify.org?format=json"); //공공장소 사용금지요 const ipAddress = response.data.ip; //한번 정제함 user.lastLoginIp = ipAddress; } catch (error) { console.log("IP 주소를 가져오는데 실패했습니다: ", error.message); } await user.save(); const token = jwt.sign( { userId: user._id, username: user.username }, process.env.JWT_SECRET, { expiresIn: "24h" } //토큰 만료는 24시간 ); console.log(token); //오 된다 res.cookie("token", token, { httpOnly: true, //자바스크립트에서 쿠키 접근 불가 secure: "production", //https에서만 쿠키 전송 sameSite: "strict", //같은 사이트에서만 쿠키 전송 maxAge: 24 * 60 * 60 * 1000, //24시간 }); const userWithoutPassword = user.toObject(); //구글링 해보니 이렇게 하면 문서 타입을 일반 객체로 변환할 수 있다고 한다 delete userWithoutPassword.password; //보안때문에 비밀번호는 삭제할 수 있다고 한다 res.json({ user: userWithoutPassword }); } catch (error) { console.log("서버 오류: ", error); res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); router.post("/logout", async (req, res) => { console.log(req.cookies.token); try { const token = req.cookies.token; if (!token) { return res.status(400).json({ message: "이미 로그아웃된 상태입니다." }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findById(decoded.userId); if (user) { user.isLoggedIn = false; await user.save(); } } catch (error) { console.log("토큰 검증 오류: ", error.message); } res.clearCookie("token", { httpOnly: true, secure: "production", sameSite: "strict", }); res.json({ message: "로그아웃되었습니다." }); } catch (error) { console.log("로그아웃 오류: ", error.message); res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); router.delete("/delete/:userId", async (req, res) => { try { const user = await User.findByIdAndDelete(req.params.userId); if (!user) { return res.status(404).json({ message: "사용자를 찾을 수 없습니다." }); } res.json({ message: "사용자가 성공적으로 삭제되었습니다." }); } catch (error) { res.status(500).json({ message: "서버 오류가 발생했습니다." }); } }); module.exports = router;

  • HTML/CSS
  • javascript
  • react
  • node.js
  • mongodb
Schwartz Melvin 댓글 1 좋아요 0 조회수 191

안녕하세요! 질문이 있습니다

미해결

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

안녕하세요. 강의 너무 잘 듣고 있습니다. 초장부터 이런식으로 질문드리는 거 안된다는 걸 잘알고 있지만 너무 죄송스럽게도 정말 도저히 모르겠는 부분이 있습니다. 어차피 나중에 혼자 프로젝트도 진행해봐야 하니 저는 강의 자료가 아니고 직접 프로젝트를 만들어서 따라가보려고 start.io 페이지에서 만든 프로젝트를 인텔리제이에 불러오려고 했는데 빌드할 때 동기화 부분에서 실패합니다. 근데 이게 어떤 오류 메시지도 나오지 않고 저렇게 실패라고만 나와서 원인을 알기 어렵습니다. PC에 설치된 자바 버전 21로 3이상을 사용해야 하기 때문에 17이상으로 다시 설치했고 강의대로 따라했는데 혹시 강의 자료처럼 빌드가 완료되려면 강의 내용뿐만이 아니라 다른 설정이 더 필요한건가요?

  • java
  • spring
  • aws
  • mysql
  • spring-boot
  • jpa
석지웅 댓글 2 좋아요 0 조회수 142

4:30 스위치 문에 for문은 생략인가요

해결됨

(2026 최신!) 일주일만에 합격하는 정보처리기사 실기

4:30 스위치 문 바로 위 for문은 생략하면 되는건지요?

  • python
  • java
  • c
  • 정보처리기사
kjh76065644 댓글 2 좋아요 0 조회수 92

인기 태그

인프런 TOP Writers

주간 인기글