DB의 User 를 삭제하는 deleteUser 메서드가 Controller 계층, Service 계층에 아래와같이 정의되어 있고 이와 관련된 메서드들도 다음과 같다고 하자.
@ApiOperation("회원 탈퇴")
@DeleteMapping("/{userNo}")
public UserDetailResponseDto deleteUser(@PathVariable Long userNo){
return userService.deleteUser(userNo);
}
Controller 단 deleteUser 메서드
@Transactional
public UserDetailResponseDto deleteUser(Long userNo){
User user = findUserByUserNo(userNo);
userRepository.deleteById(userNo);
return returnUserDetailDto(user);
}
Service 단 deleteUser 메서드
@Transactional
public UserDetailResponseDto returnUserDetailDto(User user){
List<ReminderResponseDto> r_list = new ArrayList<>();
List<Reminder> reminderList = user.getReminderList();
for(Reminder r : reminderList){
ReminderResponseDto dto = new ReminderResponseDto(r);
r_list.add(dto);
}
List<GiftResponseDto> g_list = new ArrayList<>();
List<Gift> giftList = user.getGiftList();
for(Gift g : giftList){
GiftResponseDto dto = new GiftResponseDto(g);
g_list.add(dto);
}
List<FriendResponseDto> f_list = new ArrayList<>();
List<Friend> friendList = user.getFriendList();
for(Friend f : friendList){
FriendResponseDto dto = new FriendResponseDto(f);
f_list.add(dto);
}
List<Favor> favor_List = new ArrayList<>();
for(Integer favorType : user.getFavorList()){
favor_List.add(Favor.valueOf(favorType));
}
UserDetailResponseDto dto = new UserDetailResponseDto(user, r_list, g_list, f_list, favor_List);
return dto;
}
순환참조를 막기 위해 DTO를 만들어주는 returnUserDetailDto 메서드
public void isExistingUserNo (Long userNo){
Boolean isExistingUser = null;
try{
isExistingUser = userRepository.existsByUserNo(userNo);
} catch(RuntimeException e){
throw new CustomException(e, SERVER_ERROR);
}
if(!isExistingUser){
throw new CustomException(null, USER_NOT_FOUND);
}
}
userNo 식별자로 존재하는 회원인지 여부를 반환하는 isExistingUser 메서드
"페이버" 라는 한 명의 회원이 존재할 때,
그 회원을 삭제하는 deleteUser 메서드의 반환값은 지금까지 다음과 같았다.
이는 반환타입을 일반 객체로 받은 것으로, HTTP의 Response 표준 규약을 지키지 않은 것이기에 클라이언트 사이드가 정형화되어있지 않은 환경에서 개발속도가 저하될 수 있다.
HTTP 규약을 지키게 된다면 클라이언트 입장에서도 어떤 요청을 하였고 어떤 상황인지 이해가 쉬워진다.
ResponseEntity (Spring Framework 6.0.7 API)
이 때 사용하는 ResponseEntity는 HttpEntity를 상속하여
HttpHeaders headers와 T body, HttpStatus status 를 포함한 클래스이다.
즉, HTTP 요청에 응답 Entity로 사용 가능한 클래스이다.
headers에는 웹서버가 웹브라우저에 응답하는 메세지가 담겨있다.
body에는 데이터 값이 들어간다.
ResponseEntity를 사용하면 에러코드를 설정하고, 결과값과 상태코드, 헤더값을 넘겨줄 수 있다.
ResponseEntity.status(200).body(dto)
ResponseEntity를 생성하는 기본 방법은 status와 body를 이용해서
status : status code와
body : JSON으로 변환할 객체를 지정하는 것이다.
이 때 사용할 객체 DTO인 DefaultResponseDto 클래스를 만들었다.
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
@Getter
@Builder
@AllArgsConstructor
@ApiModel(value = "기본 응답")
public class DefaultResponseDto<T> {
@ApiModelProperty(position = 1, value = "응답 코드", example = "RESPONSE_CODE")
private String responseCode;
@ApiModelProperty(position = 2, value = "응답 메세지", example = "응답 메세지")
private String responseMessage;
@ApiModelProperty(position = 3, value = "응답 데이터", example = "응답 데이터")
private T data;
public DefaultResponseDto(final String responseCode, final String responseMessage){
this.responseCode = responseCode;
this.responseMessage = responseMessage;
this.data = null;
}
public static <T> DefaultResponseDto<T> response(final String responseCode, final String responseMessage){
return response(responseCode, responseMessage, null);
}
public static <T> DefaultResponseDto<T> response(final String responseCode, final String responseMessage, final T data){
return DefaultResponseDto.<T>builder()
.responseCode(responseCode)
.responseMessage(responseMessage)
.data(data)
.build();
}
}
DefaultResponseDto를 ResponseEntity에서 다음과 같이 적용하면 된다.
@Transactional
@DeleteMapping("/{userNo}")
public ResponseEntity<DefaultResponseDto<Object>> deleteUser(
@PathVariable Long userNo){
userService.isExistingUserNo(userNo);
User user = userService.findUserByUserNo(userNo);
UserDetailResponseDto dto = userService.returnUserDetailDto(user);
userService.deleteUser(userNo);
return ResponseEntity.status(200)
.body(DefaultResponseDto.builder()
.responseCode("USER_DELETED")
.responseMessage("회원 탈퇴 완료 (임시)")
.data(dto)
.build());
}
Controller 단 deleteUser 메서드
@Transactional
public User deleteUser(Long userNo){
User user = findUserByUserNo(userNo);
userRepository.deleteByUserNo(userNo);
return user;
}
Service 단 deleteUser 메서드
실행 결과 반환 타입 ResponseEntity가 적용되었음을 알 수 있다.
나중에는 로그인에 사용된 인증받은 토큰에서 로그인중인 회원의 정보를 찾아내 해당 회원을 삭제하는 방식으로 진행할 것이기 때문에 임시를 붙여놓았다.
'[Project] > Favor 프로젝트' 카테고리의 다른 글
프로젝트 날짜 필터 구현 (0) | 2023.04.19 |
---|---|
@Builder.Default (0) | 2023.04.16 |
User 삭제 시 FriendList에서 사라지지 않는 이슈 (0) | 2023.03.26 |
import가 제대로 되지 않는 오류 (0) | 2023.03.12 |
회원가입 처리 이슈 (API 분리) (0) | 2023.03.07 |