🏕️상황
- 게시판의 형식으로 (개발 관련해서) 웹 사이트의 오류, 개선사항, 에러 발견 등의 사항들을 올릴 수 있도록 개발하는 것이 목표였다.
- 게시글에 대한 권한 부여를 어떻게 구현할 것인지 살짝 고민이 되었지만 spring security를 사용하지 않아도 복잡하거나 어렵지 않게 구현할 수 있을 거 같아 일단은 단편적인 방법으로 구현하기로 했다.
- 기능 개발을 다 하고 보니 여러 메서드들에 공통적으로 사용되는 부분이 있었고, 그걸 보니 최근에 배운 내용이 생각났다. (아래와 같은) 🔽
공통적으로 사용되는 부분은 끄집어 내서 따로 정의한다.
⭐리팩토링 전 코드
@Service
public class feedbackService {
@Autowired
private feedbackRepository repository;
// 하나의 피드백 정보를 가지고 옴. (게시글 작성자 or 관리자만 볼 수 있음)
public ResponseDTO<Optional<FeedbackBoard>> getFeedback(Long id, User user) {
try {
Optional<FeedbackBoard> feedbackOptional = repository.findById(id);
if (feedbackOptional.isPresent()) {
FeedbackBoard feedback = feedbackOptional.get();
if (user.getId() == feedback.getUser().getId() || user.getRole() == 1) {
return ResponseDTO.success(feedbackOptional);
} else {
return ResponseDTO.fail("Unauthorized", "You are not authorized to access this feedback.");
}
} else {
return ResponseDTO.fail("Not Found", "Feedback with ID " + id + " not found.");
}
} catch (Exception e) {
String error = e.getMessage();
return ResponseDTO.fail("Error", error);
}
}
// 접근 권한이 있는 사용자만 해당 글을 수정할 수 있음.
public ResponseDTO<?> updateFeedback(feedbackDTO updatedFeedback,Long id, User user) {
try {
Optional<FeedbackBoard> feedbackOptional = repository.findById(id);
if (feedbackOptional.isPresent()) {
FeedbackBoard feedback = feedbackOptional.get();
// 사용자의 ID와 피드백 게시물의 사용자 ID가 일치하거나 사용자의 역할이 1인 경우에만 수정 허용
if (user.getId() == feedback.getUser().getId() || user.getRole() == 1) {
// 엔티티 필드 업데이트
feedback.setTitle(updatedFeedback.getTitle());
feedback.setContent(updatedFeedback.getContent());
feedback.setCategory(updatedFeedback.getCategory());
feedback.setResponse(updatedFeedback.getResponse());
// 변경 사항을 데이터베이스에 저장
repository.save(feedback);
return ResponseDTO.success(feedback);
} else {
return ResponseDTO.fail("Unauthorized", "You are not authorized to update this feedback.");
}
} else {
return ResponseDTO.fail("Not Found", "Feedback not found.");
}
} catch (Exception e) {
String error = e.getMessage();
return ResponseDTO.fail("Error", error);
}
}
public ResponseDTO<?> deleteFeedback(Long id, User user) {
try {
Optional<FeedbackBoard> feedbackOptional = repository.findById(id);
if (feedbackOptional.isPresent()) {
FeedbackBoard feedback = feedbackOptional.get();
// 사용자의 ID와 피드백 게시물의 사용자 ID가 일치하거나 사용자의 역할이 1인 경우에만 삭제 허용
if (user.getId() == feedback.getUser().getId() || user.getRole() == 1) {
// 피드백 게시물 삭제
repository.delete(feedback);
return ResponseDTO.success("Feedback deleted successfully.");
} else {
return ResponseDTO.fail("Unauthorized", "You are not authorized to delete this feedback.");
}
} else {
return ResponseDTO.fail("Not Found", "Feedback not found.");
}
} catch (Exception e) {
String error = e.getMessage();
return ResponseDTO.fail("Error", error);
}
}
}
🗝️리팩토링 후 코드
@Service
public class feedbackService {
@Autowired
private feedbackRepository repository;
// update 기능 (권한 필요 O)
public ResponseDTO<?> updateFeedback(feedbackDTO updatedFeedback, Long id, User user) {
return processFeedbackRequest(id, user, feedback -> {
feedback.setTitle(updatedFeedback.getTitle());
feedback.setContent(updatedFeedback.getContent());
feedback.setCategory(updatedFeedback.getCategory());
feedback.setResponse(updatedFeedback.getResponse());
repository.save(feedback);
return ResponseDTO.success(feedback);
});
}
// 피드백 1개 상세조회 (권한 필요 O)
public ResponseDTO<?> getFeedback(Long id, User user) {
return processFeedbackRequest(id, user, feedback -> {
return ResponseDTO.success(Optional.of(feedback));
});
}
// 피드백 삭제 (권한 필요 O)
public ResponseDTO<?> deleteFeedback(Long id, User user) {
return processFeedbackRequest(id, user, feedback -> {
repository.delete(feedback);
return ResponseDTO.success("Feedback deleted successfully.");
});
}
// 사용자 권한 여부를 판단하는 메소드
// 중복을 줄이기 위해서 정의한 메소드
public ResponseDTO<?> processFeedbackRequest(Long id, User user, Function<FeedbackBoard, ResponseDTO<?>> action) {
try {
Optional<FeedbackBoard> feedbackOptional = repository.findById(id);
return feedbackOptional.map(feedback -> {
//여기에 있는 feedback은 feedbackOptional를 복제해온 객체이다. (현재 feedback = feedbackOptional)
// 동일한 객체인 feedback을 가지고 아래의 코드에서 원하는 작업을 진행한다.
if (user.getId() == feedback.getUser().getId() || user.getRole() == 1) {
return action.apply(feedback);
} else {
return ResponseDTO.fail("Unauthorized", "You are not authorized to access this feedback.");
}
}).orElseGet(() -> ResponseDTO.fail("Not Found", "Feedback with ID " + id + " not found."));
//.orElseGet() 메서드는 Optional이 비어있을 때 대체 값을 생성하는 데 사용
} catch (Exception e) {
String error = e.getMessage();
return ResponseDTO.fail("Error", error);
}
}
}
Function<FeedbackBoard, ResponseDTO<?>> action
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
- Function은 Java의 함수형 프로그래밍을 지원하는 인터페이스 중 하나로, java의 'java.util.function' 패키지에 포함되어 있다.
- T : 입력 형식(parameter type)을 나타낸다.
- R : 반환 값 형식(return type)을 나타낸다.
- FeedbackBoard를 입력받아 ResponseDTO<?>를 반환하는 함수이다.
