@Data
@NoArgsConstructor
@AllArgsConstructor
public class SignUpRequestDto {
@Pattern(regexp = "^[a-zA-Z0-9._]+$", message = "유효한 닉네임을 입력해주세요.")
private String nickName;
@Pattern(regexp = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", message = "유효한 이메일 주소를 입력해주세요.")
@NotNull(message = "E-mail을 입력해주세요.")
private String email;
@Size(min = 8, max = 20, message = "비밀번호는 최소 8자에서 20자 사이로만 가능합니다.")
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]).+$", message = "비밀번호는 대문자,소문자,숫자,특수문자만 가능합니다.")
private String password;
}
하지만, dto 상에서 유효성 검사를 하는 과정에서 옳지 않는 형식일 경우 회원 가입이 허용되지 않는 기능하는 정상 작동하지만, 상태 코드는 200을 내보내면서 로그인 화면으로 넘어가는 이슈가 생겼다.
유효성 검사를 하는 로직을 Dto 상에서 구성하는 것이 아닌 비지니스 로직 상에서 dto로 받은 필드 값들을 받아 조건문 형식 검사를 한 후 예외 처리를 하도록 변경하였다. 이를 통해 400 에러 코드를 내보내도록 하여 로그인 페이지로 넘어가지 않도록 하는 정상 동작을 성공하였다.
if(!Pattern.matches("^[a-zA-Z0-9._]+$", nickName)){
throw new CustomException(NOT_MATCH_NICKNAME);
}
Optional<Member> checkNickName = memberRepository.findByNickName(nickName);
if (checkNickName.isPresent()) {
throw new CustomException(EXIST_NICKNAME);
}
if(!Pattern.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
email)){
throw new CustomException(NOT_MATCH_EMAIL);
}
Optional<Member> checkEmail = memberRepository.findByEmail(email);
if (checkEmail.isPresent()) {
throw new CustomException(EXIST_EMAIL);
}
if(!Pattern.matches("^[a-zA-Z\p{Punct}0-9]*$", password)){
throw new CustomException(NOT_MATCH_PASSWORD);
}
if (password.length() <= 8 || password.length() >= 20) {
throw new CustomException(INVALID_PASSWORD_LENGTH);
}
board를 1차 캐시에 먼저 저장을 한 후 tag 처리 로직을 수행하도록 변경하였다.
// JPA에서 관계를 맺고 있는 엔티티의 영속성 처리 문제를 위해
// 먼저 board를 1차 캐시에 save를 보냄
boardRepository.save(board);
boardRequestDto.setHashtags(boardRequestDto.getHashtags());
for(String hashTag : boardRequestDto.getHashtags()){
String hashTagString = hashTag.substring(1);
HashTag existHashTag = hashTagRepository.findByHashTag(hashTagString);
if(existHashTag != null){
Tag_Board tag_board = new Tag_Board(existHashTag, board);
tag_boardRepository.save(tag_board);
}else {
HashTag hashTagTable = new HashTag(hashTagString);
hashTagRepository.save(hashTagTable);
Tag_Board tag_board = new Tag_Board(hashTagTable, board);
tag_boardRepository.save(tag_board);
}
}
초기 셀프 참조
@ManyToOne
@JoinColumn
private User userFollowing = this;
@ManyToOne
@JoinColumn
private User userFollower = this;
@OneToMany(mappedBy = "userFollowing")
private List<User> followingList = new ArrayList<User>();
@OneToMany(mappedBy = "userFollower")
private List<User> followerList = new ArrayList<User>();
public void addFollowing(User following) {
this.followingList.add(following);
if(!following.getFollowerList().contains(this)) {
following.getFollowerList().add(this);
}
//연관관계의 주인을 통한 확인
if(!following.getUserFollower().getFollowerList().contains(this)) {
following.getUserFollower().getFollowerList().add(this);
}
}
public void addFollower(User follower) {
this.followerList.add(follower);
if(follower.getFollowingList().contains(this)) {
follower.getFollowingList().add(this);
}
//연관관계의 주인을 통한 확인
if(!follower.getUserFollowing().getFollowingList().contains(this)) {
follower.getUserFollowing().getFollowingList().add(this);
}
}
수정 코드
@Entity
@Getter
@NoArgsConstructor
public class Follow {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "FOLLOWING_ID", referencedColumnName = "id")
private Member memberFollowing;
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnore
@JoinColumn(name = "FOLLOWER_ID", referencedColumnName = "id")
private Member memberFollower;
public Follow(Member memberFollowing, Member memberFollower) {
this.memberFollowing = memberFollowing;
this.memberFollower = memberFollower;
}
}
//Member Entity
@Builder.Default
@OneToMany(mappedBy = "memberFollowing", cascade = CascadeType.REMOVE)
private List<Follow> followingList = new ArrayList<>();
@Builder.Default
@OneToMany(mappedBy = "memberFollower", cascade = CascadeType.REMOVE)
private List<Follow> followerList = new ArrayList<>();
//serivce Logic
@Transactional
public ResponseEntity<ResponseMsgDto<Void>> follow(String nickName,
Member member) {
Member followMember = memberRepository.findByNickName(nickName)
.orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_USER));
Follow follow = new Follow(member, followMember);
Follow existFollow = followRepository.existFollow(member.getNickName(),
followMember.getNickName());
if (existFollow != null) {
followRepository.delete(existFollow);
return ResponseEntity.ok(ResponseMsgDto.setSuccess(HttpStatus.OK.
value(), "팔로우 취소", null));
} else {
followRepository.save(follow);
}
return ResponseEntity.ok(ResponseMsgDto.setSuccess(HttpStatus.OK.
value(), "팔로우 등록", null));
}