스프링 프로젝트 리팩토링 전 코드(review)

2022. 8. 22. 00:28·Java/Spring

많은 리팩토링과 다양한 기능을 추가해 포스트맨으로 시험해 봤습니다.

우선적으로 이번 프로젝트를 통해서 게시판 기능을 이용한 CRUD에 대해 다잡을 수 있었고,

시큐리티, jwt token에 대해서도 조금 생각해볼 수 있는 계기가 되었습니다. 

팀마다 기능을 나누어 구현했기에, 팀과의 협력과 공유하는 것이 얼마나 중요한지에 대해 깨닫게 되었습니다.

리팩토링 전 코드

Entity

Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Review {

    // 아이디
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 상품 매핑
    @JoinColumn(name = "Product_id")
    @ManyToOne(fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Product product;

    // 평점
    @Column(nullable = false)
    @Max(100)
    @Min(0)
    private int rate;

    // 리뷰 코멘트
    @Column(nullable = false)
    private String comment;

    // 리뷰생성날짜
    @Column(nullable = false)
    @CreatedDate
    @DateTimeFormat(pattern = "yyyy-mm-dd")
    private LocalDate createDate;

    @PrePersist
    public void createDate() {
        this.createDate = LocalDate.now();
    }

    // 유저 매핑
    @JoinColumn(name = "User_id")
    @ManyToOne(fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.NO_ACTION)
    private User user;

    @Builder
    public Review(Product product, int rate, LocalDate createDate, String comment,User user)
    {
        this.product = product;
        this.rate = rate;
        this.createDate = createDate;
        this.comment = comment;
        this.user = user;
    }
}

ReviewService

@Service
@RequiredArgsConstructor
public class ReviewService {

    private ReviewRepository reviewRepository;
    private ProductRepository productRepository;
    // Read All
    @Transactional(readOnly = true)
    public List<ReviewResponseDto> getReviews() {
        List<Review> reviews = reviewRepository.findAll();
        List<ReviewResponseDto> reviewResponseDtos = new ArrayList<>();
        for(Review review : reviews) {
            reviewResponseDtos.add(ReviewResponseDto.toDto(review));
        }
        return reviewResponseDtos;
    }
    @Transactional(readOnly = true)
    public Review getReview(Long id){
        Review review = reviewRepository.findById(id).orElseThrow(ReviewNotFoundException::new);
        return review;
    }

    // Create
    @Transactional
    public Review saveReview(ReviewRequestDto reviewRequestDto,User writer) {
        Review review = Review.builder()
                .comment(reviewRequestDto.getComment())
                .createDate(reviewRequestDto.getDate())
                .product(reviewRequestDto.getProduct())
                .rate(reviewRequestDto.getRate())
                .user(writer)
                .build();
        return reviewRepository.save(review);
    }

    // Update
    @Transactional
    public Review updateReview(Long id, Review review) {
        // 원래 있던 review 객체 불러옴
        Review originalReview = reviewRepository.findById(id).orElseThrow(ReviewNotFoundException::new);
        // 오리지날리뷰에 새 리뷰객체의 정보 덮어쓰기
        originalReview.setRate(review.getRate());
        originalReview.setComment(review.getComment());
        originalReview.setCreateDate(review.getCreateDate());
        // 저장 후 리턴
        return reviewRepository.save(originalReview);
    }

    // Delete
    @Transactional
    public void deleteReview(Long id) {
        reviewRepository.findById(id).orElseThrow(ReviewNotFoundException::new);
        //리뷰 못 찾으면 예외처리
        reviewRepository.deleteById(id);

    }

}

ReviewController

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

    private ReviewService reviewService;

    private UserRepository userRepository;

    private ReviewRepository reviewRepository;


    @ApiOperation(value = "전체 리뷰 게시글 보기", notes = "전체 리뷰 게시글을 조회합니다.")
    @ResponseStatus(HttpStatus.OK)
    @GetMapping("/reviews")
    public Response findAll() {
        return success(reviewService.getReviews());
    }

    @ApiOperation(value = "리뷰 게시글 일부 보기",notes = "리뷰 게시글 일부를 조회합니다.")
    @ResponseStatus(HttpStatus.OK)
    @GetMapping("/reviews/find/{id}")
    public Response findReview(Long id){
        return success(reviewService.getReview(id));
    }

    @ApiOperation(value = "리뷰 게시글 작성", notes = "리뷰 게시글을 작성합니다.")
    @ResponseStatus(HttpStatus.CREATED)
    @PostMapping("/reviews/write")
    public Response saveReview(@RequestBody ReviewRequestDto reviewRequestDto,Review review) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User loginUser = userRepository.findByUsername(authentication.getName()).orElseThrow(UserNotFoundException::new);
        return success(reviewService.saveReview(reviewRequestDto, loginUser));
    }

    @ApiOperation(value = "리뷰 게시글 수정", notes = "리뷰 게시글을 수정합니다.")
    @ResponseStatus(HttpStatus.OK)
    @PutMapping("/reviews/update/{id}")
    public Response updateReview(@PathVariable("id") Long id, Review newReview) {
        Review oldReview = reviewRepository.findById(id).orElseThrow(ReviewNotFoundException::new);
        User writer = oldReview.getUser();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User loginUser = userRepository.findByUsername(authentication.getName()).orElseThrow(UserNotFoundException::new);
        if(loginUser.equals(writer)){
            return success(reviewService.updateReview(id, newReview));
        }
        else{
            throw new UserNotEqualsException();
        }
    }

    @ApiOperation(value = "리뷰 게시글 삭제", notes = "리뷰 게시글을 삭제합니다.")
    @ResponseStatus(HttpStatus.OK)
    @DeleteMapping("/reviews/delete/{id}")
    public Response deleteReview(@PathVariable("id") Long id) {
        Review oldReview = reviewRepository.findById(id).orElseThrow(ReviewNotFoundException::new);
        User writer = reviewRepository.findByUserId(id).getUser();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User loginUser = userRepository.findByUsername(authentication.getName()).orElseThrow(UserNotFoundException::new);
        if(loginUser.equals(writer)){
            reviewService.deleteReview(id);
            return success("삭제 완료");
        }
        else{
            throw new UserNotEqualsException();
        }
    }

}

ReviewRequestDto

@Data
@AllArgsConstructor
public class ReviewRequestDto {



    @NotNull(message = "평점을 입력해주세요")
    private int rate;

    @NotBlank(message = "리뷰를 입력해주세요.")
    private String comment;





}

ReviewResponseDto

Data
public class ReviewResponseDto {

    @NotBlank
    private String buyerName;

    @NotNull
    private int rate;

    @NotBlank
    private String sellerName;

    @NotBlank
    private LocalDate date;

    @NotBlank(message = "제품명을 입력해주세요.")
    private String productName;

    @NotBlank(message = "리뷰를 입력해주세요.")
    private String comment;

    // Constructor
    public ReviewResponseDto(String buyerName, int rate, String sellerName, LocalDate date, String productName, String comment) {
        this.buyerName = buyerName;
        this.rate = rate;
        this.sellerName = sellerName;
        this.date = date;
        this.productName = productName;
        this.comment = comment;
    }

    // toDto
    public static ReviewResponseDto toDto(Review review) {
        return new ReviewResponseDto(
                review.getUser().getUsername(),
                review.getRate(),
                review.getProduct().getSeller().getUsername(),
                review.getCreateDate(),
                review.getProduct().getProductName(),
                review.getComment()
        );
    }
}

리뷰 기능들에 대한 url

/join => 회원가입

/login => 로그인

/users/myPage =>마이페이지

전체 리뷰 조회:/api/reviews/

일부 리뷰 조회:/api/reviews/find/{id}

리뷰 작성 :/api/reviews/write

리뷰 수정:/api/reviews/update/{id}

리뷰 삭제:/api/reviews/delete/{id}

 

이와 같이, 코드를 작성해보았는데 한 가지 간과한 사실을 발견했습니다.

어떤 제품에 대한 리뷰인가에 대해서는 전혀 생각하지 않고, 단편적으로 리뷰를 작성하고, 수정하고 조회하는 기능만 구현했습니다. 그래서 추가된 방법이 제품에 대한 리뷰를 작성, 수정 및 조회하는 기능을 구현하는데 초점을 두었습니다.

 

수정된 url코드

회원가입:/join 

로그인:/login 

마이페이지:/users/myPage 

전체 리뷰 조회:/product/{productId}/reviews

단건 리뷰조회:/product/{productId}/reviews/{reviewId}

리뷰 작성:/product/{productId}/reviews/write 

리뷰 수정:/product/{productId}/reviews/update/{reviewId} 

리뷰 삭제:/product/{productId}/reviews/delete/{reviewId} 

사용자명을 통한 리뷰 조회 : /products/{productId}/reviews/byUser/{username}

리뷰내용을 통한 리뷰 조회 : /products/{productId}/reviews/byComment/{Comment}

저작자표시 비영리 변경금지 (새창열림)

'Java > Spring' 카테고리의 다른 글

스프링 프로젝트 코드 리뷰  (1) 2022.08.23
스프링부트 프로젝트 최종 결과물  (0) 2022.08.22
Junit5을 이용한 테스트코드 작성(단위 테스트 코드)  (0) 2022.08.15
SpringBoot JPA(Java Persistence API) 사용 목적  (0) 2022.08.05
DTO, DAO, Repository, Entity 개념  (0) 2022.08.04
'Java/Spring' 카테고리의 다른 글
  • 스프링 프로젝트 코드 리뷰
  • 스프링부트 프로젝트 최종 결과물
  • Junit5을 이용한 테스트코드 작성(단위 테스트 코드)
  • SpringBoot JPA(Java Persistence API) 사용 목적
SeungbeomKim
SeungbeomKim
[IT(PS, CS, SW, etc.) 지식 기록] Github : https://github.com/daily1313/
  • SeungbeomKim
    개발 블로그
    SeungbeomKim
  • 전체
    오늘
    어제
    • 분류 전체보기 (383)
      • 일상 (33)
        • 여행 (17)
        • 회고록 (9)
        • 리뷰 (7)
      • PS (138)
        • 그리디 알고리즘[Greedy] (25)
        • 정렬 알고리즘[Sort] (18)
        • 문자열 알고리즘[String] (14)
        • 동적 계획 알고리즘[DP] (17)
        • 깊이 우선 탐색, 너비 우선 탐색[DFS, BFS.. (34)
        • 재귀[Recursion] (2)
        • 백트래킹[Backtracking] (5)
        • 브루트포스 알고리즘[Bruteforce] (16)
        • 자료 구조[Data Structure] (4)
        • 분할 정복 알고리즘[Divide & Conquer.. (3)
      • CS (22)
      • Network (11)
      • Database (8)
        • Elasticsearch (3)
      • Linux (2)
      • JavaScript (4)
        • AngularJS (1)
      • Java (92)
        • Effective Java (5)
        • Java Concept (20)
        • Spring (61)
        • Design Pattern (3)
      • Python (2)
      • Vscode (1)
      • DevOps (43)
        • AWS (27)
        • Git (7)
        • Docker (6)
        • Nginx (1)
      • 자격증 (10)
        • SQL (4)
      • 사이드 프로젝트 (2)
        • MatJido (2)
      • 기타 (9)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 소개
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    Effective Java
    정보처리기사 실기
    sqld
    springboot
    docker
    컴퓨터구조
    Wi-Fi
    정보처리기사 필기
    dfs
    dp
    AWS
    이펙티브 자바
    정보처리기사
    메타코딩
    일본여행
    BFS
    백트래킹
    너비 우선 탐색
    Spring
    다이나믹 프로그래밍
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
SeungbeomKim
스프링 프로젝트 리팩토링 전 코드(review)
상단으로

티스토리툴바