개발 기록/도서관 관리 시스템

[Library Management System] 25.08.29 (31일)

dev.jelee 2025. 8. 29. 23:44

[ 작업한 내용 ]

1. 로그인 상태 별 예외처리

1-1) messages.properties

- 로그인 시 사용자 상태에 따른 예외처리 메시지.

error.user.status_inactive=탈퇴된 계정입니다. 재가입해 주세요.
error.user.status_suspended=정지된 계정입니다. 고객센터에 문의해 주세요.
error.user.status_deleted=삭제된 계정입니다.

1-2) UserErrorCode

- 에러 코드 정의

USER_STATUS_INACTIVE(HttpStatus.BAD_REQUEST, "USER_007", "error.user.status_inactive"),
USER_STATUS_SUSPENDED(HttpStatus.BAD_REQUEST, "USER_008", "error.user.status_suspended"),
USER_STATUS_DELETED(HttpStatus.BAD_REQUEST, "USER_009", "error.user.status_deleted");

1-3) AuthService

-  사용자 상태별 예외처리 추가. (ACTIVE가 아닌 경우)

// 사용자의 상태가 ACTIVE인지 체크
if (user.getStatus() == UserStatus.INACTIVE) {
  throw new BaseException(UserErrorCode.USER_STATUS_INACTIVE);
} else if (user.getStatus() == UserStatus.SUSPENDED) {
  throw new BaseException(UserErrorCode.USER_STATUS_SUSPENDED);
} else if (user.getStatus() == UserStatus.DELETED) {
  throw new BaseException(UserErrorCode.USER_STATUS_DELETED);
}

2. 사용자가 email 업데이트시 응답 변경

2-1) 요청, 응답 각각 DTO 필드 수정

- 요청 DTO에는 email

- 응답 DTO에는 id username, email, updatedAt

@Getter
public class UpdateEmailReqDTO {
  @Email
  private String email;
}
@Getter
@Setter
@Builder
public class UpdateEmailResDTO {
  private Long id;
  private String username;
  private String email;
  private LocalDateTime updatedAt;
}

2-2 ) UserController - 수정

- 서비스 계층으로 수정할 email과 user 인증 객체를 보낸 다음 결과를 UpdateEmailResDTO responseDTO에 저장한다.

- 저장한 responseDTO를 클라이언트측으로 반환시킨다.

UpdateEmailResDTO responseDTO = userService.updateEmail(user.getUsername(), updateEmail.getEmail());
return ResponseEntity
              .status(UserSuccessCode.USER_EMAIL_UPDATE.getHttpStatus())
              .body(ApiResponse.success(
                UserSuccessCode.USER_EMAIL_UPDATE, 
                message, 
                responseDTO));

2-3) UserService - 수정

- 이메일 업데이트와 함께 수정된 날짜도 저장한다.

- 응답으로 UpdateEmailResDTO를 반환한다.

user.setEmail(newEmail);
user.setUpdatedAt(LocalDateTime.now());
userRepository.save(user);

// 반환
return UpdateEmailResDTO.builder()
          .id(user.getId())
          .username(user.getUsername())
          .email(user.getEmail())
          .updatedAt(user.getUpdatedAt())
          .build();

3. 사용자가 password 업데이트시 응답 변경

3-1) 요청과 응답 DTO 필드 수정

- 요청 DTO는 password, repassword

- 응담 DTO는 id, username, updatedAt

@Getter
public class UpdatePasswordReqDTO {
  private String password;
  private String repassword;
}
@Getter
@Setter
@Builder
public class UpdatePasswordResDTO {
  private Long id;
  private String username;
  private LocalDateTime updatedAt;
}

3-2) UserController - 수정

- 서비스 계층으로 수정할 password와 user 인증 객체를 보낸 다음 결과를 UpdatePasswordResDTO responseDTO에 저장한다.

- 저장한 responseDTO를 클라이언트측으로 반환시킨다.

UpdatePasswordResDTO responseDTO = userService.updatePassword(user.getId(), updatePassword);

return ResponseEntity
              .status(UserSuccessCode.USER_PASSWORD_UPDATE.getHttpStatus())
              .body(ApiResponse.success(
                UserSuccessCode.USER_PASSWORD_UPDATE, 
                message, 
                responseDTO));

3-3) UserService - 수정

- 비밀번호와 함께 수정된 날짜를 저장하는 것으로 수정.

- 응답으로 UpdatePasswordResDTO를 반환한다.

 

// 새로운 비밀번호 암호화, 수정된 날짜 저장 후 DB에 user 객체 저장.
String encodedNewPassword = passwordEncoder.encode(newPassword);
user.setPassword(encodedNewPassword);
user.setUpdatedAt(LocalDateTime.now());
userRepository.save(user);

// 반환
return UpdatePasswordResDTO.builder()
          .id(user.getId())
          .username(user.getUsername())
          .updatedAt(user.getUpdatedAt())
          .build();

4. 사용자 탈퇴 요청시 코드 리팩토링

4-1) DB와 User 엔티티에 각각 deleted_at 컬럼과 필드 추가

- DB에는 deleted_at 컬럼 추가.

- User 엔티티에는 deletedAt 필드 추가.


4-2) UserController - 수정

- 서비스 계층으로 userId와 사용자가 입력한 비밀번호를 전달하여 삭제 비즈니스 로직 수행.

- 로그인한 사용자의 쿠키 제거.


4-3) UserService - 수정

- 사용자의 상태를 INACTIVE로 변경하여 저장.

- INACTIVE로 변경을 하면서 inactiveAt 현재 시간으로 저장.

- repository를 통해 User 객체 저장. (덮어씌우기)

user.setStatus(UserStatus.INACTIVE);
user.setInactiveAt(LocalDateTime.now());
userRepository.save(user);

4-4) UserStatusScheduler 생성

- 사용자의 상태가 INACTIVE이고 INACTIVE 된 시각으로 부터 30일 뒤 자동으로 DELETED 상태 변경.


4-5) UserRepository - 수정

- 상태가 INACTIVE이고 inactive_at이 30일 이전인 사용자 목록을 조회

List<User> findByStatusAndInactiveAtBefore(UserStatus status, LocalDateTime inactiveAt);

4-6) Application에 @EnableScheduling 추가

- @Scheduled는 사용자 요청 없이 백그라운드에서 자동 실행되는 작업이기 때문에 Application에 추가해야한다. 즉, 애플리케이션이 실행될 때 자동으로 주기적으로 실행되어야하기 때문에 Application에 추가.

- Controller에 추가 안 하는 이유는 Controller는 클라이언트의 요청을 받았을 때에 사용하기 때문이다.


5. 관리자 - 사용자 계정 삭제

5-1) message.properties - 수정

- 메시지 추가

error.user.deleted.status_deleted=상태가 DELETED만 삭제가 가능합니다.

5-2) UserErrorCode - 수정

- 에러 코드 추가

USER_DELETE_ACCOUNT_STATUS_DELETED(HttpStatus.BAD_REQUEST, "USER_010", "error.user.deleted.status_deleted");

5-3) 삭제시 응답 DTO 생성

@Getter
@Setter
@Builder
public class UserDeleteResDTO {
  private Long id;
  private String username;
}

5-4) AdminUserController - 수정

- UserService로 userId 데이터를 보내 삭제 비즈니스 로직 수행후 UserDeletedResDTO로 반환받기.


5-5) UserService - 수정

- 사용자의 상태가 DELETED 인 경우에만 삭제가 가능.

// 사용자 상태가 DELETED 이면 삭제
if (user.getStatus() == UserStatus.DELETED) {
  userRepository.delete(user);
} else {
  throw new BaseException(UserErrorCode.USER_DELETE_ACCOUNT_STATUS_DELETED);
}

commit
postman api test
postman api test