Skip to content
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

[feat #4] : 시큐리티 세팅 및 소셜 로그인 API 구현 #13

Merged
merged 96 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from 94 commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
23591d7
[feat] : Security Config 작성
dudxo Jul 25, 2024
1a86bf4
[feat] : member Repository 추가
dudxo Jul 25, 2024
be602ff
[feat] : Oauth2UserSerivce 구현
dudxo Jul 25, 2024
4c542bb
[feat] : AuthErrorCode 구현
dudxo Jul 25, 2024
4a5dab1
[feat] : 인증 객체 Dto 추가
dudxo Jul 25, 2024
87ab12a
[feat] : Oauth2UserInfo Mapping 객체 구현
dudxo Jul 25, 2024
8fbffb3
[style] : AuthDto 네이밍 변경으로 인한 수정
dudxo Jul 25, 2024
df1d40e
[feat] : socialEmail update method 추가
dudxo Jul 25, 2024
3c65791
[feat] : Member Repository 추가
dudxo Jul 25, 2024
4351bf7
[test] : member socialEmail udpate method 테스트 구현
dudxo Jul 25, 2024
e5e4127
[test] : memberRepository.findBySocialEmail() 테스트 구현
dudxo Jul 25, 2024
00bbd45
[feat] : CustomOauth2User 구현
dudxo Jul 26, 2024
546755c
[refactor] : Provider로부터 획득한 유저 정보 처리 Service 리팩토링
dudxo Jul 26, 2024
a14d0f7
[feat] MemberService.class 추가
dudxo Jul 26, 2024
41665d5
[test] : 쿼리메서드 타입 변경으로 인한 테스트 코드 수정
dudxo Jul 26, 2024
2cdd4b7
[feat] : 회원 구분 객체 Auth 엔티티 추가
dudxo Jul 26, 2024
e706c88
[feat] : AuthRepository 추가
dudxo Jul 26, 2024
d3b7fe7
[feat] AuthService 추가
dudxo Jul 26, 2024
6435102
[feat] : AuthErrorCode 에러코드 추가
dudxo Jul 26, 2024
1859885
[feat] : Auth 객체 저장 또는 업데이트 로직 추가
dudxo Jul 26, 2024
d6189ed
[feat] : SocialName 필드에서 Provider 추출 메서드 구현
dudxo Jul 26, 2024
60de8a7
[feat] : OauthLogin 성공 핸들러 추가
dudxo Jul 26, 2024
e6e2b26
[refactor] : 단일 책임 원칙 준수하기 위한 메서드 이동
dudxo Jul 26, 2024
e723028
[fix] : Auth 생성 시 연관된 회원 주입
dudxo Jul 27, 2024
e314026
[fix] : 오탈자로 인한 오류 해결
dudxo Jul 27, 2024
55d4697
[feat] : MemberErrorCode 추가
dudxo Jul 27, 2024
f658a13
[feat] : AuthController 추가
dudxo Jul 27, 2024
c6c62e9
[fix] : 회원 검색 실패 시 예외 추가
dudxo Jul 27, 2024
e7eb2d6
[fix] : provider명 변경
dudxo Jul 27, 2024
19a3123
[fix] : Kakao Login Api 명세와 일치되도록 수정
dudxo Jul 27, 2024
33bf7df
[test] : AuthService UnitTest 구현
dudxo Jul 27, 2024
4762d46
[test] : MemberService UnitTest 구현
dudxo Jul 27, 2024
e8fa553
[fix] : Enum 필드 수정
dudxo Jul 27, 2024
2492908
[fix] : 소셜이름 메서드 로직 중 문자 포맷팅 오탈자 수정
dudxo Jul 29, 2024
9926aa2
[fix] : 소셜 이름 변경으로 인한 문제 발생 차단을 위한 수정
dudxo Jul 29, 2024
449ae2b
[test] : 소셜 이름 -> 소셜 이메일 로직으로 변경으로 인한 테스트 코드 수정
dudxo Jul 29, 2024
004e4ed
[fix] 신규 회원 DB 저장 로직 변경
dudxo Jul 29, 2024
147c8d0
[feat] : Member 공무원 이메일 여부를 통한 Auth 상태 변경 추가
dudxo Jul 29, 2024
037e74c
[test] : 공무원 이메일 여부 통한 Auth 상태 변경 단위 테스트 추가
dudxo Jul 29, 2024
46ce511
[feat] : 닉네임 중복 Api 구현
dudxo Jul 29, 2024
dfeacfc
[test] : 중복 닉네임 검증 단위테스트 작성
dudxo Jul 29, 2024
63594c5
[feat] : 신규 회원 추가 정보 입력을 통한 회원가입 구현
dudxo Jul 29, 2024
30ca76e
[test] : MemberService 회원가입 UnitTest 작성
dudxo Jul 29, 2024
6a2fa1d
[feat] : method 단위 읽기전용 트랜잭션 부여
dudxo Jul 29, 2024
8d8cbec
[test] : Member UnitTest 추가
dudxo Jul 29, 2024
0da91e5
[rename] : security 관련 클래스 파일 경로 수정
dudxo Jul 31, 2024
32bf08b
[style]: 코드 포맷팅
dudxo Jul 31, 2024
f850cc0
[chore] jwt 라이브러리 추가
dudxo Jul 31, 2024
ca4a3d9
[feat] : 소셜로그인 성공 이후 로직 구현
dudxo Aug 1, 2024
043fbdf
[feat] 소셜 로그인 실패 핸들러 추가
dudxo Aug 1, 2024
320eeed
[feat] : 인증 오류 EntryPoint 추가
dudxo Aug 1, 2024
a304057
[feat] : Jwt 관련 예외 클래스 추가
dudxo Aug 1, 2024
7873142
[feat] : jwt Provider 구현
dudxo Aug 1, 2024
4079520
[feat] : 토큰 서비스 추가
dudxo Aug 1, 2024
9234f33
[feat] : jwt 검증 필터 구현
dudxo Aug 1, 2024
b4f1165
[feat] : 토큰 예외처리 필터 구현
dudxo Aug 1, 2024
c9d5ce7
[feat] : SecuritConfig 설정 추가
dudxo Aug 1, 2024
0dd84ad
[test] : tokenProvider 단위 테스트 작성
dudxo Aug 1, 2024
210147b
[chore] : jwt 관련 라이브러리 추가
dudxo Aug 1, 2024
d7f3332
[fix] : 회원가입 임시토큰 관련 로직 삭제
dudxo Aug 1, 2024
326d708
[test] : 회원가입 임시토큰 발급 테스트 코드 삭제
dudxo Aug 1, 2024
271b595
[style] 코드 포맷팅
dudxo Aug 1, 2024
ff3ca70
Merge branch 'dev' into feat/#4/social-login
dudxo Aug 2, 2024
740a4dd
[refactor] : 정적 팩토리 메서드 추가 리펙토링
dudxo Aug 2, 2024
88b629b
[rename] : 패키지 네이밍 변경
dudxo Aug 2, 2024
d9403ec
[test] : 정적 팩토리 메서드, 클래스 네이밍 변경으로 인한 리팩토링
dudxo Aug 2, 2024
9b68deb
[rename] : AuthDto -> AuthInfo 클래스 네이밍 변경
dudxo Aug 2, 2024
fc4ba01
[style] Repository 코드 통일성을 위한 어노테이션 삭제
dudxo Aug 2, 2024
ab67793
[refactor] 변경 감지로 인한 불필요한 반환타입 제거
dudxo Aug 2, 2024
f594720
[test] : 변경 감지에 따른 반환타입 제거로 인한 테스트 로직 수정
dudxo Aug 2, 2024
42a30c0
[feat] : Member 외래키 제거
dudxo Aug 2, 2024
7c0a8a5
[refactor] 변경 감지로 인한 불필요한 반환타입 제거
dudxo Aug 2, 2024
99510b9
[fix] : 회원가입 응답DTO 필드 변경
dudxo Aug 2, 2024
d7eb1ad
[test] : 변경 감지에 따른 반환타입 제거로 인한 테스트 로직 수정
dudxo Aug 2, 2024
c4b6e0d
[rename] : 클래스명 및 필드명 수정
dudxo Aug 2, 2024
75a63fa
[test] : 레코드 필드명 수정에 따른 수정
dudxo Aug 2, 2024
95a5875
[style] : import 클래스명 변경
dudxo Aug 2, 2024
90a4ee3
[feat] : requestDto validation 추가
dudxo Aug 2, 2024
90745c3
[rename] : enum 필드명 통일을 위한 네이밍 수정
dudxo Aug 2, 2024
9006df8
[refactor] : 가독성을 위한 static import enum타입 제거
dudxo Aug 2, 2024
9bac4dc
[test] : 가독성을 위한 static import enum타입 제거
dudxo Aug 2, 2024
1c70ad0
[rename] : enum 에러코드 네이밍 수정
dudxo Aug 2, 2024
288f1a1
[feat] : requestMapping 추가
dudxo Aug 2, 2024
2d1b09b
[feat] : 추가정보 api 인증/인가 허용
dudxo Aug 2, 2024
7e50d2e
[sytle] : 안쓰는 의존 코드 삭제
dudxo Aug 2, 2024
4806bcb
[feat] : 소셜이메일로 회원 찾는 메서드 추가
dudxo Aug 2, 2024
e99cf34
[fix] : CustomOauth2User 객체가 아닌 Member 객체를 인증 객채로 생성되도록 변경
dudxo Aug 2, 2024
8b58c67
[test] : CI test 오류로 인한 테스트 disable 처리
dudxo Aug 3, 2024
adce9d9
[test] : 주입 클래스, 변수 순서 변경
dudxo Aug 3, 2024
e9808eb
[test] : mock 테스트 명시를 위한 어노테이션 수정
dudxo Aug 3, 2024
2fb8677
[refactor] : AuthInfo of() Builder를 이용한 객체 생성 변경
dudxo Aug 3, 2024
f12de11
[feat] : 모든 필드 값을 주입하여 생성하는 팩터리 메서드 추가
dudxo Aug 3, 2024
3f3ae1f
[test] : Member 관련 test를 위한 MemberFixture 추가
dudxo Aug 3, 2024
128ce98
[test] : API 테스트를 위한 인증 객체 setUp 추가
dudxo Aug 3, 2024
250b9ca
[feat] Auth 도메인 로딩 전략 변경
dudxo Aug 4, 2024
b565df1
[test] : 통합 테스트용 추상메서드 상속
dudxo Aug 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,17 @@ dependencies {
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// S3

/*JWT 관련 라이브러리*/
implementation 'io.jsonwebtoken:jjwt-api:0.12.3'
implementation 'io.jsonwebtoken:jjwt-impl:0.12.3'
implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3'

implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

//spring bean validation
implementation 'org.springframework.boot:spring-boot-starter-validation'

}

tasks.named('test') {
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/dnd/gongmuin/auth/cotroller/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.dnd.gongmuin.auth.cotroller;

import java.net.URI;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/auth")
public class AuthController {

@GetMapping("signin/kakao")
public ResponseEntity<?> kakaoLoginRedirect() {
HttpHeaders httpHeaders = new HttpHeaders();
// 카카오 로그인 페이지로 리다이렉트
httpHeaders.setLocation(URI.create("/oauth2/authorization/kakao"));
return new ResponseEntity<>(httpHeaders, HttpStatus.MOVED_PERMANENTLY);
}
}

63 changes: 63 additions & 0 deletions src/main/java/com/dnd/gongmuin/auth/domain/Auth.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.dnd.gongmuin.auth.domain;

import static jakarta.persistence.ConstraintMode.*;
import static jakarta.persistence.EnumType.*;

import com.dnd.gongmuin.member.domain.Member;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Enumerated;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Auth {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Enumerated(STRING)
dudxo marked this conversation as resolved.
Show resolved Hide resolved
@Column(name = "provider", nullable = false)
private Provider provider;

@Enumerated(STRING)
@Column(name = "status", nullable = false)
private AuthStatus status;

@OneToOne
dudxo marked this conversation as resolved.
Show resolved Hide resolved
@JoinColumn(name = "member_id",
nullable = false,
foreignKey = @ForeignKey(NO_CONSTRAINT))
private Member member;

@Builder
private Auth(Provider provider, AuthStatus status, Member member) {
this.provider = provider;
this.status = status;
this.member = member;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private으로 되어있는데 Builder로 생성할 수 있나요? 궁금해서 여쭤봅니다!

public static Auth of(Provider provider, AuthStatus status, Member member) {
return Auth.builder()
.provider(provider)
.status(status)
.member(member)
.build();
}

public void updateStatus() {
this.status = AuthStatus.OLD;
}
}
14 changes: 14 additions & 0 deletions src/main/java/com/dnd/gongmuin/auth/domain/AuthStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.dnd.gongmuin.auth.domain;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum AuthStatus {

NEW("신규"),
OLD("기존");

private final String label;
}
26 changes: 26 additions & 0 deletions src/main/java/com/dnd/gongmuin/auth/domain/Provider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.dnd.gongmuin.auth.domain;

import java.util.Arrays;

import com.dnd.gongmuin.auth.exception.AuthErrorCode;
import com.dnd.gongmuin.common.exception.runtime.NotFoundException;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum Provider {

KAKAO("kakao"),
NAVER("naver");

private final String provider;

public static Provider fromProviderName(String providerName) {
return Arrays.stream(values())
.filter(provider -> provider.getProvider().equalsIgnoreCase(providerName))
.findFirst()
.orElseThrow(() -> new NotFoundException(AuthErrorCode.NOT_FOUND_PROVIDER));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이것도 정적 팩토리 메서드의 일종인 것 같은데 다른 enum들처럼 네이밍을 통일해도 괜찮을 것 같습니다! 이 글을 보고 아예 from으로 통일할까도 생각이 드네요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정적 팩토리 메서드에 대해 새로 논의하여 결정된 부분으로 Member, Auth 등 Builder를 통한 객체 생성 -> 정적 팩토리 메서드를 이용한 객체 생성으로 수정했습니다!

}
18 changes: 18 additions & 0 deletions src/main/java/com/dnd/gongmuin/auth/exception/AuthErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.dnd.gongmuin.auth.exception;

import com.dnd.gongmuin.common.exception.ErrorCode;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum AuthErrorCode implements ErrorCode {

UNSUPPORTED_SOCIAL_LOGIN("해당 소셜 로그인은 지원되지 않습니다.", "AUHT_001"),
NOT_FOUND_PROVIDER("알맞은 Provider를 찾을 수 없습니다.", "AUTH_002"),
NOT_FOUND_AUTH("회원의 AUTH를 찾을 수 없습니다.", "AUTH_003");

private final String message;
private final String code;
}
13 changes: 13 additions & 0 deletions src/main/java/com/dnd/gongmuin/auth/repository/AuthRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.dnd.gongmuin.auth.repository;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import com.dnd.gongmuin.auth.domain.Auth;
import com.dnd.gongmuin.member.domain.Member;

public interface AuthRepository extends JpaRepository<Auth, Long> {

Optional<Auth> findByMember(Member member);
}
52 changes: 52 additions & 0 deletions src/main/java/com/dnd/gongmuin/auth/service/AuthService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.dnd.gongmuin.auth.service;

import java.util.Objects;

import org.springframework.stereotype.Service;

import com.dnd.gongmuin.auth.domain.Auth;
import com.dnd.gongmuin.auth.domain.AuthStatus;
import com.dnd.gongmuin.auth.domain.Provider;
import com.dnd.gongmuin.auth.exception.AuthErrorCode;
import com.dnd.gongmuin.auth.repository.AuthRepository;
import com.dnd.gongmuin.common.exception.runtime.NotFoundException;
import com.dnd.gongmuin.member.domain.Member;
import com.dnd.gongmuin.member.service.MemberService;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class AuthService {

private final AuthRepository authRepository;
private final MemberService memberService;

public void saveOrUpdate(Member savedMember) {
hyun2371 marked this conversation as resolved.
Show resolved Hide resolved
Auth findedOrCreatedAuth = authRepository.findByMember(savedMember)
.map(auth -> {
if (!memberService.isOfficialEmail(savedMember)) {
auth.updateStatus();
}
return auth;
})
.orElse(createAuth(savedMember));

authRepository.save(findedOrCreatedAuth);
}

public boolean isAuthStatusOld(Member member) {
Auth findAuth = authRepository.findByMember(member)
.orElseThrow(() -> new NotFoundException(AuthErrorCode.NOT_FOUND_AUTH));

return Objects.equals(findAuth.getStatus(), AuthStatus.OLD);
}

private Auth createAuth(Member savedMember) {
String providerName = memberService.parseProviderFromSocialEmail(savedMember);
Provider provider = Provider.fromProviderName(providerName);

return Auth.of(provider, AuthStatus.NEW, savedMember);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.dnd.gongmuin.common.exception.runtime;

import com.dnd.gongmuin.common.exception.ErrorCode;

import lombok.Getter;

@Getter
public class CustomJwtException extends RuntimeException {

private final String code;

public CustomJwtException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.dnd.gongmuin.member.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.dnd.gongmuin.member.dto.request.AdditionalInfoRequest;
import com.dnd.gongmuin.member.dto.request.ValidateNickNameRequest;
import com.dnd.gongmuin.member.dto.response.SignUpResponse;
import com.dnd.gongmuin.member.dto.response.ValidateNickNameResponse;
import com.dnd.gongmuin.member.service.MemberService;
import com.dnd.gongmuin.security.oauth2.CustomOauth2User;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/auth")
public class MemberController {

private final MemberService memberService;

@PostMapping("/check-nickname")
public ResponseEntity<ValidateNickNameResponse> checkNickName(
@RequestBody ValidateNickNameRequest validateNickNameRequest) {
return ResponseEntity.ok(memberService.isDuplicatedNickname(validateNickNameRequest));
}

@PostMapping("/member")
public ResponseEntity<SignUpResponse> signUp(@RequestBody AdditionalInfoRequest request,
@AuthenticationPrincipal CustomOauth2User loginMember) {
SignUpResponse response = memberService.signUp(request, loginMember.getEmail());

return ResponseEntity.ok(response);
}

}
44 changes: 39 additions & 5 deletions src/main/java/com/dnd/gongmuin/member/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,31 @@ public class Member extends TimeBaseEntity {
@Column(name = "member_id")
private Long id;

@Column(name = "nickname", nullable = false)
@Column(name = "nickname")
private String nickname;

@Column(name = "social_name", nullable = false)
private String socialName;

@Enumerated(STRING)
@Column(name = "job_group", nullable = false)
@Column(name = "job_group")
private JobGroup jobGroup;

@Enumerated(STRING)
@Column(name = "job_category", nullable = false)
@Column(name = "job_category")
private JobCategory jobCategory;

@Column(name = "social_email", nullable = false)
private String socialEmail;

@Column(name = "official_email", nullable = false)
@Column(name = "official_email")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullable = false를 지우신 이유가 있으실까요? 개발하는데 불편하셔서 일까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지난 논의 사항 때 회원 1자 저장을 위해 officialEmail 필드를 포함한 추가 정보 관련 필드는 null 값 허용을 위해 제거했습니다!
(default nullable =true)

private String officialEmail;

@Column(name = "credit", nullable = false)
private int credit;

@Builder
public Member(String nickname, String socialName, JobGroup jobGroup, JobCategory jobCategory, String socialEmail,
private Member(String nickname, String socialName, JobGroup jobGroup, JobCategory jobCategory, String socialEmail,
String officialEmail, int credit) {
this.nickname = nickname;
this.socialName = socialName;
Expand All @@ -59,4 +59,38 @@ public Member(String nickname, String socialName, JobGroup jobGroup, JobCategory
this.officialEmail = officialEmail;
this.credit = credit;
}

public static Member of(String socialName, String socialEmail, int credit) {
return Member.builder()
.socialName(socialName)
.socialEmail(socialEmail)
.credit(credit)
.build();
}

public static Member of(String nickname, String socialName, JobGroup jobGroup, JobCategory jobCategory,
String socialEmail, String officialEmail, int credit) {
return Member.builder()
.nickname(nickname)
.socialName(socialName)
.jobGroup(jobGroup)
.jobCategory(jobCategory)
.socialEmail(socialEmail)
.officialEmail(officialEmail)
.credit(credit)
.build();
}

public void updateSocialEmail(String socialEmail) {
this.socialEmail = socialEmail;
}

public void updateAdditionalInfo(String nickname, String officialEmail,
JobGroup jobGroup, JobCategory jobCategory) {
this.nickname = nickname;
this.officialEmail = officialEmail;
this.jobGroup = jobGroup;
this.jobCategory = jobCategory;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.dnd.gongmuin.member.dto.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public record AdditionalInfoRequest(

@NotBlank(message = "공무원 이메일은 필수 입력 항목입니다.")
String officialEmail,
@NotBlank(message = "닉네임은 필수 입력 항목입니다.")
@Size(min = 2, max = 12, message = "닉네임은 최소 2자리 이상 최대 12자 이하입니다.")
String nickname,
@NotBlank(message = "직군은 필수 입력 항목입니다.")
String jobGroup,
@NotBlank(message = "직렬은 필수 입력 항목입니다.")
String jobCategory
) {
}
Loading
Loading