-
Notifications
You must be signed in to change notification settings - Fork 1
[Feature] OAuth 2.0 기반 소셜 로그인 및 JWT 인증 시스템 구현 #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
- 데이터베이스 네이밍 컨벤션(snake_case)을 스키마(camelCase)와 명시적으로 매핑 하도록 하고 Prisma 클라이언트 프로바이더를 개선했어요. - prisma-client-js 프로바이더 명시 - 필드명 camelCase 정규화 및 @Map 추가 - 중복 인덱스 제거 (email)
- Passport 기반 Google OAuth 2.0 및 JWT 인증 구현을 위한 의존성 추가 - 인증: @nestjs/jwt, @nestjs/passport, passport-google-oauth20 - 검증: class-validator, class-transformer
- rootDir -> roots로 변경 (src와 test 디렉토리 명시)
- @typescript-eslint/no-unused-vars 규칙 활성화 - 언더스코어(_)로 의도적 미사용 변수 허용 - 함수 매개변수, 변수, catch 에러 모두 적용
- .js 확장자 제거 - bootstrap() 앞에 void 연산자 추가 (floating promise 경고 해결)
- .js 확장자 제거 - PrismaClient 임포트 경로: '@prisma/client' 사용
- JwtPayload 인터페이스 정의 - JwtProvider 서비스 (access, refresh token 생성 및 검증)
- *.spec.ts, *.test.ts, test/**/*.ts에서 type-safety 규칙 완화 - Jest Mock/expect 관련 unsafe 규칙 비활성화
- generateAccessToken, generateRefreshToken 테스트 - verifyAccessToken, verifyRefreshToken 테스트
- Passport Google OAuth 2.0 전략 설정 - 프로필 정보 추출 및 사용자 조회 및 생성 로직 구현
- validate 메서드 테스트 - 생성자: 환경 변수 초기화 확인
AuthController - GET /auth/oauth2/google: Google 로그인 - GET /auth/oauth2/callback/google: OAuth 콜백 → 토큰 발급 및 리다이렉트 AuthService - generateTokens: Access, Refresh Token 생성 - reissueAccessToken: Refresh Token으로 새 Access Token 발급
- 토큰 생성 테스트 - 토큰 갱신 테스트
- Authorization 헤더에서 Bearer 토큰 추출 및 검증 - 유효한 토큰 → request.user에 JwtPayload 저장 - 토큰 유효하지 않음 → UnauthorizedException - @currentuser() 로 현재 사용자 정보 접근 - 필드 선택 가능: @currentuser('sub')
- GET /users/me: JWT로 인증된 사용자 프로필 조회 - findOrCreateOAuthUser: OAuth 사용자 조회/생성 - findById: 사용자 ID로 조회 (비밀번호 제외)
- findOrCreateOAuthUser 테스트 - findById 테스트
- ConfigModule.forRoot 추가 (전역 환경 변수) - AuthModule, UsersModule 추가
- passport-oauth2 기반 Naver OAuth 전략구현 - 네이버 API로 사용자 정보 조회 프로필 추출 후 사용자 생성 - NaverAuthGuard: Naver 인증 가드 구현
- moduleNameMapper의 @/ 경로 매핑에 src 디렉토리 명시 - '<rootDir>/$1' → '<rootDir>/src/$1' - jest 테스트에서 @/ import 시 정확한 경로 해석하도록
- validate 메서드 테스트 - API 호출 테스트
- extractGoogleProfile 메서드 추가 (프로필 추출 로직 분리) - 이메일 필수 검증 하도록 개선 (UnauthorizedException) - 사용하지 않는 파라미터에 _ 접두사
- Naver OAuth 엔드포인트 추가 - 공통 콜백 로직 handleOAuthCallback으로 추출 - 리다이렉트 URL 생성 로직 buildRedirectUrl으로 분리
- Passport Kakao OAuth2 전략 - 이메일 필수 검증 - KakaoAuthGuard: Kakao 인증 가드 - KakaoStrategy provider 등록
- GET /auth/oauth2/kakao: Kakao 로그인 페이지로 리다이렉트 - GET /auth/oauth2/callback/kakao: Kakao OAuth 콜백 처리
- validate 메서드
- done 관련 수정 (불필요한 null 인자 제거) - done(error, null) → done(error)
이걸 하루만에...! 고생 많으셨어요🔥🔥🔥 현재 해당 이슈는 해결해서, 제 로컬 브랜치에 커밋해두었습니다! 앗 그리고 현재 PR의 TODO로 남겨두신 항목들도 리뷰를 지금 진행하면 좋을지, |
허스키 같은 경우에는 스테이징된 파일(변경 파일)에 대해서만 lint를 확인하게 되어서 그런거 같아요! TODO로 남긴 것들은 하다가 생각난 것들 적어논거라 다음에 이슈를 생성하고 따로 작업할 거 같아요! |
|
그렇군요! 스테이징 된 것만 확인하는거라 그랬나봐요!
저도 두 방식의 차이가 궁금해서 문서들을 조금 찾아봤는데, 정리해보면 대략 이런 트레이드오프가 있는 것 같았습니다.
best practice 같은 건 존재하지 않고 트레이드 오프의 문제 같은데... 여러 레퍼런스를 훑어봤을 때는
이 조합을 전제로 설명하는 경우가 가장 많아보였어요! 🔖 참고 자료 목록
개인적으로는,
구조 자체가 이미 확장 가능하게 잡혀 있어서, |
mindaaaa
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
env.example 파일 하나 생성해주신 후에 머지해주시면 좋을 것 같아요!
좋은 의견 감사합니다!@! 어떤 식으로 토큰을 프론트에서 저장하고 있는지에 따라 달라질 수 있을 것 같아요!! 제가 일단 생각해본 건 아래 방향이긴 했는데 이 부분은 추후 수정해도 될거 같아요!!
|
추가했어요~!! |
📌 관련 이슈
closed: [Feature] OAuth 2.0 기능 구현 (Google, Naver, Kakao) #27
✅ PR 체크리스트(최소요구조건)
✨ 작업 개요
🔑 인증 시스템 구현
👤 사용자 관리
✅ 개발 환경 수정
apps/api-> ESM 확장자 제거)🧹 작업 상세 내용
prisma/schema.prismasrc/auth/jwt/jwt-payload.interface.tssub(user id),email,provider포함src/auth/jwt/jwt.provider.tsgenerateAccessToken: 사용자 정보 포함 Access Token 생성generateRefreshToken: Refresh Token 생성verifyAccessToken: Access Token 검증verifyRefreshToken: Refresh Token 검증 및 userId 추출src/auth/strategies/google.strategy.tsPassport Google OAuth 2.0전략을 이용했어요.src/auth/guards/google-auth.guard.ts네이버같은 경우에는 passport-naver 가 꽤 오래되고 업데이트가 안되어서 직접 profile을 가져오는 형식으로 구현해봤어요.
src/auth/guards/jwt.auth.guard.tssrc/auth/decorators/current-user.decorator.ts@CurrentUser(): 현재 인증된 사용자 정보 접근@CurrentUser('sub'): 특정 필드만 추출 가능사용자 서비스 구현
src/users/users.service.tsfindOrCreateOAuthUser: OAuth 사용자 조회/생성 (upsert)findById: 사용자 ID로 조회 (비밀번호 제외)src/users/users.controller.tsGET /users/me: 현재 인증된 사용자 프로필 조회⚙️ 개발 환경 수정
jest.config.jsroots: ['/src', '/test'] (디렉토리 분리)apps/api/.eslintrc.mjs코드 정리
📸 스크린샷 (선택)
2025-12-29.7.18.40.mov
2025-12-29.10.02.51.mov
2025-12-30.12.18.12.mov
2025-12-30.12.20.31.mov
사용자 조회 (JWT)
2025-12-29.7.15.33.mov
🔍 고민 지점
패키지 분리
나름 패키지 분리해서 책임을 분리해보고자 했는데 맞는지 잘 모르겠어요.. 지금 약간 머리가 멍해져서 다시 확인해보고 ... 피드백 주시면.. 적용할게요
리프레시 토큰
일단 리프레시 토큰 넣어놓긴 했는데 어떻게 관리할지 고민입니다.
다른 분들은 어떤 식으로 관리하셨나요?!?
이거 때문에 Redis를 사용해야 하나..
그냥 refresh token 없이 할까...
토큰 전달 방식
현재는 그냥 일단 Requestparam으로 accesstoken이나 refreshtoken을 client에 전달을 해주는 형식과 HTTP Header의 Authorization 로 accesstoken 값을 넣어서 요청을 보내면 처리하는 식으로 해줬는데 어떤 방식이 좋을까 고민이에요..
💬 기타 참고 사항
🌍 환경변수!!
일단은 제가 예전에 만든 google client 를 이용했는데 다른 provider나 google을 사용하더라도 공통 이메일 같은 것을 만들어야 할 것 같아요!!
📖 문서화
☑️ Todo
💣 Lint 에러
프론트쪽에서 lint 에러가 발생하는 거 같더라구요!! 일단 제가 해결하다가 더 문제가 생길수도 있을거 같아서,, 냅뒀습니다..! ㅜ