inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

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

강의자료 부탁 드립니다~

미해결

프로그래밍 시작하기 : 파이썬 입문 (Inflearn Original)

안녕하세요, 강의자료 부탁 드려도 될까요? fbyksong@gmail.com 입니다.

  • python
댓글 1 좋아요 0 조회수 265

오류 메세지

미해결

실전 프로젝트로 배우는 데이터 앱 만들기 with Python & Streamlit

안녕하세요~~ 루비네 코딩 입니다 ^^ 최근 앱을 런칭할 때 다음과 같은 오류가 발생하고 있습니다. ModuleNotFoundError: No module named 'altair.vegalite.v4' 이런경우, 다음과 같이 altair 패키지의 버전을 바꾸어 설치해 주세요 ^^ 감사합니다~ pip uninstall altair pip install altair==4.2.2

  • python
  • streamlit
루비네 코딩 댓글 2 좋아요 1 조회수 921

최신 소식은 어떻게 접할 수 있을까요?

해결됨

실리콘밸리 엔지니어와 함께하는 아마존 웹서비스(Core)편

안녕하세요! 파이썬 강의를 완강하고 이번 aws 강의를 수강하게 되었습니다. 다름이 아니라 이번 강의 소개에서도 컨퍼런스나 여러 최신 소식에 대해 항상 잘 말씀해주시고, 그런 내용을 언급해주실 때마다 중요성을 많이 느낍니다. 혹시 실리콘밸리 개발자분들은 이런 소식을 접하는 커뮤니티 같은 게 별도로 활성화가 되어있나요? 저는 이제야 주니어 개발자로 시작하는 입장이라 그런 노하우라든지 소식을 어디서 접해야 하는지 어디서부터 어떻게 시작해야 하는지 방향성을 잘 모르는 상태라 질문드립니다.

  • aws
  • aws-rds
  • ec2
  • iam
  • s3
서영민 댓글 1 좋아요 1 조회수 258

x.com에 모달창에 url을 적용시킨 이유가 있을까요?

해결됨

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

x.com 을 보면 로그인도 그렇고 게시글 올릴때도 그렇고 모달창이 뜰때마다 그냥 화면에 띄우는 방식이 아니라 저렇게 모달창을 띄울수 있는 url 따로 만든 이유가 뭘까요? 관리가 더 편해서일까요?

  • react
  • next.js
  • react-query
  • next-auth
  • msw
쵸잉 댓글 1 좋아요 0 조회수 598

젠킨스와 도커를 사용해서 배포할 때

해결됨

인터넷에서 조사한 대로 하다가 에러를 만났는데 해결전에 프리티어 기간이 끝나서 결국 실습으로 해결하지 못해서 질문드립니다 ㅠㅠ 제가 진행한게 맞는지 이해한게 맞는지도 독학으로 하다보니 잘 모르겠네요... 진행한 순서 : EC2 리눅스 생성 EC2 시간 설정과 프로젝트에서 사용할 환경변수 설정 git 설치 sudo yum install git 도커 다운 sudo yum install docker 도커 시작 sudo systemctl start docker 도커로 자바 다운 docker pull openjdk:11 도커로 젠킨스 이미지 다운로드 docker pull jenkins/jenkins:jdk11 다운로드 이미지 조회 docker images 젠킨스 이미지를 컨테이너로 실행 ocker run -d -p 8080:8080 -p 50000:50000 -v /home/jenkins:/var/jenkins_home -v /usr/bin/docker:/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -u root jenkins/jenkins:jdk11 젠킨스에서 가입 젠킨스에서 시간 설정 젠킨스에서 사용할 플로그인 다운받아서 플러그인 올리기로 등록 젠킨스 디렉토리 생성 sudo mkdir -p /home/jenkins/.ssh SSH 권한 부여 sudo chmod 700 /home/jenkins/.ssh SSH key 생성 sudo ssh-keygen -t rsa 키 파일 설정 구간 /home/jenkins/.ssh/id_rsa 비밀번호 없이 진행할 수 있도록 jenkins ALL=(ALL) NOPASSWD: ALL ssh 퍼블릭을 복사해서 개발서버(authorized_keys)에 복사 git에서 프로젝트의 레포지토리의 설정에서 Deploy keys에 ssh 퍼블릭을 넣음 웹훅 설정 : 젠킨스가 설치된 서버 :포트/github-webhook/ Git Token 발급 Credential 등록 Kind : SSH Username with private key Username : 깃허브 아이디(닉네임) password : git token ID : 원하는 값 설정(아무거나) private key : ssh private 넣기 Publish Over SSH 설정 name : 본인이 사용하고자하는 이름 HostName : EC2 퍼블릭 ip username : 리눅스니 ec2-user directory : 인스턴스 디렉토리`/home/ec2-user` 여기서 Test Configurations을 누르면 에러발생 여기서부터 막혀서 진행이 안됐는데 다음꺼는 조사한 거로 정리한건데 맞는지 확인을 위해 올립니다. Dockerfile 작성 FROM openjdk:11-jre-slim-buster ARG JAR_FILE=build/libs/*.jar COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"] 젠킨스 item 생성 :파이프라인 파이프라인 설정 파이프라인 충돌 방지 옵션 체크 스크립트 작성 pipeline { agent any stages { stage('Checkout') { steps { git branch: '원하는 브랜치명', url: '본인의 깃 레파지토리 URL(.git으로 끝나는링크)' } } stage('Build') { steps { sh './gradlew build' } } stage('Dockerize') { steps { sh ''' docker stop my_container_name || true docker rm my_container_name || true docker rmi my_image_name || true docker build -t my_image_name . ''' } } stage('Deploy') { steps { sh 'docker run -d --name my_container_name -p 8080:8080 my_image_name' } } } } 도커 허브에 회원가입 도커 로그인 젠킨스 build 부분 수정 ./gradlew clean build echo " Execute shell start" # 도커 빌드와 개시 삭제 sudo docker build --no-cache -t cova1256/dev . # 기존 서버에 있는 컨테이너 중지 sudo docker stop spring-container || true #기존 서버에 있는 컨테이너 삭제 sudo docker rm -f spring-container || true # 도커 로그인 sudo docker login -u cova1256 -p password 입력 # 도커 이미지 태그 설정 및 태그가 없다면 오류가 발생해도 넘어가도록 true 처리 sudo docker image tag dev cova1256/dev || true # 도커 허브에 나의 레포지토리에 도커 푸시 sudo docker push cova1256/dev # 푸시 후 빌드한 이미지 삭제 sudo docker rmi -f cova1256/dev || true echo " Execute shell end" 빌드 후 조치 echo " 빌드 후 조치 start" # 기존에 있는 이미지를 삭제합니다. sudo docker rmi -f cova1256/dev || true # 기존에 있는 컨테이너를 중지합니다. sudo docker stop spring-container || true # 기존에 있는 컨테이너를 삭제합니다. sudo docker rm -f spring-container || true # 컨테이너를 설치하고 실행합니다. sudo docker run -d -p 8080:8080 --name spring-container cova1256/dev # none인 이미지 삭제 sudo docker rmi $(docker images -q -f dangling=true) echo " 빌드 후 조치 end" 질문 1 : 제가 진행했던 진행하려고 정리하는 방식이 맞나요? 질문 2 : 저는 현재 EC2 외부에서 환경변수를 사용하는 방법을 사용했는데 Docker에서 외부 설정 파일 주입할 수도 있다고 하던데 Docker을 사용할 때는 후자의 방법을 선택해야 하나요? 질문 3 : 저 에러는 어떻게 고칠 수 있을 까요? 찾아보니 권한을 줘야한다고 해서 주었고 git이나 젠킨스에 모두 넣었는데...

  • jenkins
  • docker
  • ec2
  • linux
유요한 댓글 1 좋아요 1 조회수 1146

npm run start:dev 명령어 실행시 Error: connect ECONNREFUSED ::1:6379 에러 발생

미해결

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

해당 강의에서 postgresql 설치와 노드버전 18.17.0 환경에서 nest-prisma의 폴더를 다운 받은 후 npm i -> npx prisma migrate dev 까지는 순조롭게 진행되었으나 npm run start:dev에서 Error: connect ECONNREFUSED ::1:6379 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16) { errno: -61, code: 'ECONNREFUSED', syscall: 'connect', address: '::1', port: 6379 } 에러가 발생했습니다 구글링을 해보니 레디스 서버가 구동이 안된 것 같다고 나오기도하고 서버쪽을 잘 몰라 질문 드립니다 .env 파일 입니다 DATABASE_URL="postgresql://postgres:비번@localhost:5432/zcom?schema=public" REDIS_URL=redis://localhost:6379 COOKIE_SECRET=cookienyamnyam

  • react
  • next.js
  • react-query
  • next-auth
  • msw
mun9927 댓글 4 좋아요 2 조회수 1427

API 요청 시, cookie 보내는 것에 대한 질문

미해결

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

안녕하세요! 제로초님! 보너스 강의까지 잘 챙겨보고 있습니다. 매번 감사합니다! 제 질문은..! server action 함수쪽에서 fetch config 객체에 credentials 을 include로 해줘야 쿠키(세션)를 API 요청 시 같이 태워서 보낼 수 있다고 설명해주셨는데, 혹시 이것이 next-auth 로부터 도움을 받는 것일까요? 강의 수강 후, next 14로 프로젝트를 구현하고 있는데, fetch 할 때, credentials 를 include 해주었음에도 불구하고, 브라우저 application 탭에서 확인 할 수 있는 쿠키가 태워지지 않아서요. 해당 쿠키는 서버에서 로그인 시에 set-cookie 해준 쿠키이고, 프론트엔드는 localhost , 서버는 ec2에 배포된 서버입니다. 그래서 현재는 server action 함수내에서 next.js에서 지원해주는 cookie() 를 이용해서 fetch config 객체 내 headers 에 직접 쿠키를 넣어주고 있는데, 강의에서는 credentials 만으로 API 요청시 쿠키(세션)을 잘 태워서 보내주고 있는 것 같아 질문을 남기게 되었습니다.

  • react
  • next.js
  • react-query
  • next-auth
  • msw
withkey 댓글 2 좋아요 0 조회수 1083

[실습] 1.S3 버킷 생성하기 영상 짤림(?)

해결됨

비전공자도 이해할 수 있는 AWS 입문/실전

안녕하세요. 강의 잘 듣고있습니다. 강의 내용에 관한 질문은 아니구요. 커리큘럼 중, '섹션5. 파일 및 이미지 업로드 (S3)'의 '[실습] 1.S3 버킷 생성하기' 강의가 있는데, 영상이 3초로 이상 편집된 것 같습니다. 저만 그렇게 보이는 것인지 모르겠지만 확인 부탁드립니다.

  • aws
  • aws-elb
  • aws-rds
  • ec2
  • s3
olzzor 댓글 3 좋아요 0 조회수 443

RS232c Serial 통신 관련 질문이 있습니다.

미해결

안녕하세요 연구실에서 자체적으로 실험기기와 컴퓨터랑 통신을 진행하는 중인데, 하나가 해결이 안 되어서 너무 답답해서 고수님들께 자문을 구하려고 합니다. Rs232 rtu 모드를 지원한다고 한 OS-20 overhead stirrer과 통신을 진행 중 입니다. 이 친구의 통신 규격과 방식은 아래 그림 3개와 같습니다. 이중 stirrer control 부분을 제가 참조해서 저 command를 hex 방식으로 입력하였는데 도무지 안되는 겁니다. 그런데 웃긴게 이 회사에서 지원하는 공식 통신프로그램을 사용하면 작동이 잘 되더군요. Instruction overview에서 나온 규칙은 다음과 같습니다. Command 구조는 Prefix Instruction_code Data_frame Checksum로 되어 있고 입력의 prefix는 0xfe로 시작하며 responce는 0xfd로 시작합니다. 모든 바이트 사이에는 50ms delay가 존재해야하며 Dataframe은 큰 수 자리부터 전송합니다. ex) 1000rpm을 data frame에 입력하려고 할 시 Hex값이 03E8이니까 앞에 두 자리를 0x03에 해당하고 뒤에 두 자리를 0xE8로 해당시킵니다. Null은 0x00입니다. Checksum 방식은 0xfe,0xfd인 prefix를 제외하고 나머지를 전부 더한 값으로 0xnn 이런식으로 표현됩니다. 신기하게도 16진수의 2자리를 넘어가도 뒤에 2 자리만 붙이면 된다고 하더군요. ex) 0xfe 0xb1 0x03 0xe8 0x00 checksum인데 0xfe를 제외하고 다 더하면 019c이지만 0x9c만 입력하면 되는 형식입니다. 그래서 이 규칙대로 코드를 짜서 통신을 해 보았는데, 아무리 해도 안되어서 너무 답답합니다. 심지어 제가 잘못했는지 확인하려고 시리얼 통신 sniffer을 사용하여서 공식 프로그램에서는 어떻게 통신이 되나 뜯어보았습니다. 결과는 아래 사진과 같습니다. 제가 python으로 작성한 코드는 아래와 같습니다. import serial import time ser = serial.Serial( port='COM7', # Update with your actual port baudrate=9600, parity=serial.PARITY_NONE, # No parity stopbits=serial.STOPBITS_ONE, # 1 stop bit bytesize=serial.EIGHTBITS # 8 data bits ) def send_hex_string(hex_string): # Convert the hex string to bytes byte_data = bytes.fromhex(hex_string) # Send the bytes over the serial port ser.write(byte_data) def send_hex_string_with_delay(hex_string, delay_ms=50): for i in range(0, len(hex_string), 2): # Extract each pair of characters and convert to bytes hex_pair = hex_string[i:i + 2] byte_data = bytes.fromhex(hex_pair) # Send the bytes over the serial port ser.write(byte_data) # Wait for the specified delay time.sleep(delay_ms / 1000.0) command = 'feb103e8009c' send_hex_string_with_delay(command) ser.close() 또한 파이썬에서의 결과를 시리얼 전송으로 보면 다음과 같습니다. 입력은 제대로 되는데 기기에는 반응이 제대로 나오지 않네요... 제가 잘못하고 빠뜨린 점이 있을까요? 읽어주셔서 정말 감사드립니다.

  • rs232
  • serial
  • 커뮤니케이션
  • python
전성훈 댓글 1 좋아요 1 조회수 1023

섹션3. 날씨 재검증하기 NextRequest 질문입니다.

해결됨

손에 익는 Next.js - 공식 문서 훑어보기

콘솔로그 결과 안녕하세요 선생님, 강의를보고 간단하게 따라해보았는데요 NextRequest 타입의 req를 매개변수로 받아와서 req를 console.log 에 찍어보면 undefined가 뜹니다. 혹시 NextRequest 사용에 조건이 따로 있을까요? req.nextUrl.pathname 으로 url 도 가져와보고 싶고한데 생각처럼 잘 안되네요..

  • react
  • typescript
  • next.js
  • next.js13
가스라이팅의정석 댓글 1 좋아요 1 조회수 364

강의 자료 부탁드립니다!

미해결

프로그래밍 시작하기 : 파이썬 입문 (Inflearn Original)

안녕하세요. 강의 자료 요청합니다. elel3418@daum.net 감사합니다!

  • python
댓글 1 좋아요 0 조회수 216

강의내용 중복

미해결

실리콘밸리 엔지니어와 함께하는 아마존 웹서비스(Core)편

11:46 구간에서 강의가 끝났는데요 다시 중간으로 돌아가서 강의가 반복 재생됩니다. 확인바랍니다~

  • aws
  • aws-rds
  • ec2
  • iam
  • s3
sohee kim 댓글 2 좋아요 1 조회수 339

print 출력

미해결

프로그래밍 시작하기 : 파이썬 입문 (Inflearn Original)

선생님처럼 깔끔하게 괄호 안에 있는 부분만 뜨는 게 아니라 저 파란 줄로 길게 뜨는 건 왜 그런 건가요? 어떻게 하면 없앨 수 있나요?

  • python
hjy648012 댓글 2 좋아요 0 조회수 325

ELB로 부하분산되고 있는 EC2의 서비스를 블루그린 배포하는 강의를 추가해주시면 감사하겠습니다.

해결됨

비전공자도 이해할 수 있는 AWS 입문/실전

안녕하세요, 강사님 좋은 강의 만들어 주셔서 감사합니다. 다름이 아니오라 ELB로 부하분산되고 있는 EC2의 서비스를 블루그린 배포하는 강의를 추가해주시면 감사하겠습니다. 강사님, 오늘도 기분 좋은 하루 되세요~

  • aws
  • aws-elb
  • aws-rds
  • ec2
  • s3
ericserra 댓글 2 좋아요 1 조회수 621

vanila-extract window 문제

해결됨

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

windows 에서 vanila-extract 의 문제점은 구체적으로 어떤 것일까요? https://github.com/vanilla-extract-css/vanilla-extract/issues/1086 해당 이슈가 맞는지 궁금합니다!

  • react
  • next.js
  • react-query
  • next-auth
  • msw
부드러운 펭귄 댓글 1 좋아요 0 조회수 1048

'[섹션 8. Connection & Hook] Postgres 컨테이너 올리기' 강의에서 sudo docker compose up 명령어가 제대로 실행되지 않습니다.

미해결

Airflow 마스터 클래스

이전까지는 도커 서비스를 잘 수행이 됐었습니다. 이번 강의에서 docker-compose.yaml파일을 수정 후 서비스를 내렸다가 다시 올리려고 하니 사진처럼 해당 로그까지만 찍힌 후에 더 이상 진행이 되지 않고 있습니다. 계속 기다려봐도 상태가 그대로인 것을 보아하니 어딘가 문제가 생긴 것 같습니다. yaml파일은 올려주신 파일과 비교해봤을 때 오타나 다른 문제는 없는 것 같습니다. 원래의 docker-compose.yaml로 교체하면 잘 실행이 되는 상태입니다. 뭐가 문제일까요?

  • python
  • 데이터-엔지니어링
  • airflow
재윤 댓글 2 좋아요 0 조회수 465

EC2 배포후 구글 로그인 안됨

미해결

스프링부트 REST + OAuth2 + JWT를 사용하고 있는 상황인데 로컬에서는 잘 돌아갑니다. 로컬에서 소셜로그인이 성공하면 OAuth2SuccessHandler에서 바로 JSON으로 반환해주는 형태입니다. 즉, 컨트롤러가 딱히 무슨 역할을 하지 않아도 바로 반환을 해줍니다. 하지만 EC2에 배포하고 구글 개발자 센터, yml에 EC2 퍼블릭을 제대로 입력해주고 제대로 일치하는 것을 확인했고 버튼을 클릭하면 아이디들이 제대로 뜹니다. 하지만 로그인한 결과 로그인할 아이디를 클릭을 하면 Whitelabel Error Page 404페이지가 뜹니다. 그래서 실패했을 때 JSON으로 반환시켜주는 로직을 추가해서 확인한 결과 "error 발생 : ": "[authorization_request_not_found] " 이러한 오류가 발생했습니다. 항상 체크해야하는요소 yml 체크함 구글 개발자 센터 확인함 → 1, 2번은 일치함 EC2 인스턴스의 보안 그룹이 OAuth2 콜백 URL로 요청을 수신할 수 있도록 올바르게 설정되었는지 확인 → 이거는 어떻게 다른 설정법이 있을까요? application.yml 또는 application.properties 에 설정된 값들이 프로덕션 환경에 맞게 정확히 설정 이렇게 환경변수를 받아서 ec2 배포시 사용할 수 있도록 설정했는데 추가적으로 또 뭔가를 해줘야 하나요? 혹시 OAuth2 google을 테스터로 해놓고 http로 해놓으면 ec2 배포시에는 사용하지 못하나요?

  • google
  • 소셜로그인
  • oauth2
  • ec2
유요한 댓글 1 좋아요 0 조회수 1468

wilcoxon 검정에 대한 질문입니다!

해결됨

[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)

이전 단일 표본 검정에서 정규성 검증을 진행할 때 willcoxon 코드를 알려주실 때stats.wilcoxon(df[’무게‘]-120, alternative=’less’)와 같이 알려주셨는데 이번 대응표본 검정에서 정규성 검증을 진행할 때 willcoxon는 stats.wilcoxon(df[‘after’] ,df[‘before’], alternative = ‘greater’)와 같이 알려주셨습니다.또한 강의에서도 after와 before의 값을 빼서 넣은 값인 df['diff']를 그대로 사용해도 된다고 말씀하셨습니다.그래서 아래 사진과 같이 임의로 df[‘after’] - df[‘before’]를 넣어서 실행해봤는데 결과값이 똑같이 나왔습니다. 그럼 단일 표본 검정에서 알려주신대로 df[’무게‘]-120와 같이 df[‘after’] - df[‘before’]로 생각하고 넣어줘도 무방한 것인가요?

  • python
  • 머신러닝
  • 빅데이터
  • pandas
  • 빅데이터분석기사
김건우 댓글 1 좋아요 0 조회수 315

4-2 type 1 4 번 문제

해결됨

[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)

형별로 합하기 위해 df = df.T 를 쓰셨는데 print(sum(df.sum(axis=1) > 3000)) 를 쓰면 안 될까요 ? 해보니 답은 동일 했습니다.

  • python
  • 머신러닝
  • 빅데이터
  • pandas
  • 빅데이터분석기사
paul1142 댓글 3 좋아요 1 조회수 401

배포후 소셜로그인 에러

미해결

스프링부트 REST + OAuth2 + JWT를 사용하고 있는 상황인데 로컬에서는 잘 돌아갑니다. 로컬: <a id="google-login" href="/oauth2/authorization/google">구글 로그인</a> <a id="naver-login" href="/oauth2/authorization/naver">네이버 로그인</a> @Service @Log4j2 @RequiredArgsConstructor public class PrincipalOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> { private final MemberRepository memberRepository; private final JwtProvider jwtProvider; private final TokenRepository tokenRepository; @Override public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { // userRequest.getClientRegistration()은 인증 및 인가된 사용자 정보를 가져오는 // Spring Security에서 제공하는 메서드입니다. ClientRegistration clientRegistration = userRequest.getClientRegistration(); log.info("clientRegistration : " + clientRegistration); // 소셜 로그인 accessToken String socialAccessToken = userRequest.getAccessToken().getTokenValue(); log.info("소셜 로그인 accessToken : " + socialAccessToken); OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService = new DefaultOAuth2UserService(); log.info("oAuth2UserService : " + oAuth2UserService); // 소셜 로그인한 유저정보를 가져온다. OAuth2User oAuth2User = oAuth2UserService.loadUser(userRequest); log.info("oAuth2User : " + oAuth2User); log.info("getAttribute : " + oAuth2User.getAttributes()); // 회원가입 강제 진행 OAuth2UserInfo oAuth2UserInfo = null; String registrationId = clientRegistration.getRegistrationId(); log.info("registrationId : " + registrationId); if(registrationId.equals("google")) { log.info("구글 로그인"); oAuth2UserInfo = new GoogleUser(oAuth2User, clientRegistration); } else if(registrationId.equals("naver")) { log.info("네이버 로그인"); oAuth2UserInfo = new NaverUser(oAuth2User, clientRegistration); } else { log.error("지원하지 않는 소셜 로그인입니다."); } // 사용자가 로그인한 소셜 서비스를 가지고 옵니다. // 예시) google or naver 같은 값을 가질 수 있다. String provider = oAuth2UserInfo.getProvider(); // 사용자의 소셜 서비스(provider)에서 발급된 고유한 식별자를 가져옵니다. // 이 값은 해당 소셜 서비스에서 유니크한 사용자를 식별하는 용도로 사용됩니다. String providerId = oAuth2UserInfo.getProviderId(); String name = oAuth2UserInfo.getName(); // 사용자의 이메일 주소를 가지고 옵니다. // 소셜 서비스에서 제공하는 이메일 정보를 사용합니다. String email = oAuth2UserInfo.getEmail(); // 소셜 로그인의 경우 무조건 USER 등급으로 고정이다. Role role = Role.USER; MemberEntity findUser = memberRepository.findByEmail(email); if(findUser == null) { log.info("소셜 로그인이 최초입니다."); log.info("소셜 로그인 자동 회원가입을 진행합니다."); findUser = MemberEntity.builder() .email(email) .memberName(name) .provider(provider) .providerId(providerId) .memberRole(role) .nickName(name) .build(); log.info("member : " + findUser); findUser = memberRepository.save(findUser); } else { log.info("로그인을 이미 한적이 있습니다."); } // 권한 가져오기 List<GrantedAuthority> authorities = getAuthoritiesForUser(findUser); // 토큰 생성 TokenDTO tokenForOAuth2 = jwtProvider.createTokenForOAuth2(email, authorities, findUser.getMemberId()); // 기존에 이 토큰이 있는지 확인 TokenEntity findToken = tokenRepository.findByMemberEmail(tokenForOAuth2.getMemberEmail()); TokenEntity saveToken; // 기존의 토큰이 없다면 새로 만들어준다. if(findToken == null) { TokenEntity tokenEntity = TokenEntity.tokenEntity(tokenForOAuth2); saveToken = tokenRepository.save(tokenEntity); log.info("token : " + saveToken); } else { // 기존의 토큰이 있다면 업데이트 해준다. tokenForOAuth2 = TokenDTO.builder() .grantType(tokenForOAuth2.getGrantType()) .accessToken(tokenForOAuth2.getAccessToken()) .accessTokenTime(tokenForOAuth2.getAccessTokenTime()) .refreshToken(tokenForOAuth2.getRefreshToken()) .refreshTokenTime(tokenForOAuth2.getRefreshTokenTime()) .memberEmail(tokenForOAuth2.getMemberEmail()) .memberId(tokenForOAuth2.getMemberId()) .build(); TokenEntity tokenEntity = TokenEntity.updateToken(findToken.getId(), tokenForOAuth2); saveToken = tokenRepository.save(tokenEntity); log.info("token : " + saveToken); } // 토큰이 제대로 되어 있나 검증 if(StringUtils.hasText(saveToken.getAccessToken()) && jwtProvider.validateToken(saveToken.getAccessToken())) { Authentication authenticationToken = jwtProvider.getAuthentication(saveToken.getAccessToken()); log.info("authentication : " + authenticationToken); SecurityContextHolder.getContext().setAuthentication(authenticationToken); UserDetails userDetails = new User(email, "", authorities); log.info("userDetails : " + userDetails); Authentication authenticationUser = new UsernamePasswordAuthenticationToken(userDetails, authorities); log.info("authentication1 : " + authenticationUser); SecurityContextHolder.getContext().setAuthentication(authenticationUser); } else { log.info("검증 실패"); } // attributes가 있는 생성자를 사용하여 PrincipalDetails 객체 생성 // 소셜 로그인인 경우에는 attributes도 함께 가지고 있는 PrincipalDetails 객체를 생성하게 됩니다. PrincipalDetails principalDetails = new PrincipalDetails(findUser, oAuth2User.getAttributes()); log.info("principalDetails : " + principalDetails); return principalDetails; } // 권한 가져오기 로직 private List<GrantedAuthority> getAuthoritiesForUser(MemberEntity findUser) { Role role = findUser.getMemberRole(); List<GrantedAuthority> authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority("ROLE_" + role.name())); log.info("권한 : " + role.name()); return authorities; } } @Log4j2 @RequiredArgsConstructor @Component public class OAuth2SuccessHandler implements AuthenticationSuccessHandler { private final MemberRepository memberRepository; private final TokenRepository tokenRepository; // Jackson ObjectMapper를 주입합니다. private final ObjectMapper objectMapper; @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { try { log.info("OAuth2 Login 성공!"); // 소셜 로그인 이메일 가져오기 String email = authentication.getName(); log.info("email : " + email); // 토큰 조회 TokenEntity findToken = tokenRepository.findByMemberEmail(email); log.info("token : " + findToken); // 토큰 DTO 반환 TokenDTO tokenDTO = TokenDTO.toTokenDTO(findToken); // 회원 조회 MemberEntity findUser = memberRepository.findByEmail(email); // 회원 DTO 반환 ResponseMemberDTO memberDTO = ResponseMemberDTO.socialMember(findUser); // 헤더에 담아준다. response.addHeader("email", memberDTO.getEmail()); // 바디에 담아준다. Map<String, Object> responseBody = new HashMap<>(); responseBody.put("providerId", memberDTO.getProviderId()); responseBody.put("provider", memberDTO.getProvider()); responseBody.put("accessToken", tokenDTO.getAccessToken()); responseBody.put("refreshToken", tokenDTO.getRefreshToken()); responseBody.put("email", tokenDTO.getMemberEmail()); responseBody.put("memberId", tokenDTO.getMemberId()); responseBody.put("grantType", tokenDTO.getGrantType()); // JSON 응답 전송 response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(responseBody)); } catch (Exception e) { // 예외가 발생하면 클라이언트에게 오류 응답을 반환 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.getWriter().write("OAuth 2.0 로그인 성공 후 오류 발생: " + e.getMessage()); response.getWriter().flush(); } } } 로컬에서 소셜로그인이 성공하면 OAuth2SuccessHandler에서 바로 JSON으로 반환해주는 형태입니다. 즉, 컨트롤러가 딱히 무슨 역할을 하지 않아도 바로 반환을 해줍니다. 하지만 EC2에 배포하고 구글 개발자 센터, yml에 EC2 퍼블릭을 제대로 입력해주고 로그인한 결과 아이디들 제대로 뜨는데 로그인할 아이디를 클릭을 하면 Whitelabel Error Page 404페이지가 뜹니다. 로컬 코드를 그대로 배포한건데 왜 안될까요?

  • google
  • oauth2
  • 소셜로그인
  • ec2
유요한 댓글 1 좋아요 0 조회수 733

인기 태그

인프런 TOP Writers

주간 인기글