JustDoEat

ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค์— ๊ฐ์ฒด ์ƒ์„ฑ์— ํ•„์š”ํ•œ ์„œ๋น„์Šค๋ฅผ ์˜์กด์„ ๋ฐ›์•˜๋‹ค. ์ •๋‹ต์ผ๊นŒ ์•„๋‹๊นŒ ๋ณธ๋ฌธ

Yajoba/Backend

ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค์— ๊ฐ์ฒด ์ƒ์„ฑ์— ํ•„์š”ํ•œ ์„œ๋น„์Šค๋ฅผ ์˜์กด์„ ๋ฐ›์•˜๋‹ค. ์ •๋‹ต์ผ๊นŒ ์•„๋‹๊นŒ

kingmusung 2024. 11. 21. 02:32

๊ฐœ์š”

๐Ÿ—ฃ๏ธ  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด ์ƒ์„ฑ์˜ ์ฑ…์ž„์ด ์žˆ๋‹ค๊ณ  ์•Œ๊ณ ์žˆ์Œ.

๐Ÿ—ฃ๏ธ ๐Ÿ—ฃ๏ธ ์„œ๋น„์Šค ํด๋ž˜์Šค์—์„œ๋Š” ์‘์ง‘๋„๋ฅผ ์œ„ํ•ด ์œ ์‚ฌํ•œ ์„ฑ๊ฒฉ์„ ๊ฐ€์ง„ ๊ธฐ๋Šฅ๋“ค์„ ๋ชจ์•„์•ผ ํ•œ๋‹ค๊ณ  ์•Œ๊ณ ์žˆ์Œ.

 

โ“ ์ด ๋‘๊ฐ€์ง€ ์ƒ๊ฐ์— ๋Œ€ํ•œ ์ถฉ๋Œ โ“


์ง„ํ–‰

์—ฌ๊ธฐ์„œ ๋“œ๋Š” ์˜๋ฌธ

Review๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” User Entity ๊ฐ์ฒด์™€, Product Entity ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์•ผ ํ•œ๋‹ค.

 


์ƒํ™ฉ

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฆฌ๋ทฐ๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, ๋ฆฌ๋ทฐ์˜ ๋‚ด์šฉ, ํ‰์ ์„ ์ž…๋ ฅํ•  ๊ฒƒ์ด๊ณ .

 

์ž‘์„ฑ์™„๋ฃŒ๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ”„๋ŸฐํŠธ์—”๋“œ์—์„œ๋Š” ํ•ด๋‹น ๋ฆฌ๋ทฐ์— ๋Œ€์‘๋˜๋Š” productId๋ฅผ ๋„˜๊ฒจ์ค„ ๊ฒƒ์ด๋‹ค.

 

Case 1.

@Service
@RequiredArgsConstructor
public class ReviewServiceImpl implements ReviewService{
    private final ReviewCrudService reviewCrudService;
    private final ReviewFactory reviewFactory;
    private final UserService userService;
    private final ProductCrudService productCrudService;

    @Override
    public void registerReview(ReviewCreateRequestDto review) {
        reviewCrudService.saveReview(createReviewWithUserAndProduct(review));
    }

    @Override
    public List<ReviewWithAvgProjection> getAllReview(Long productId) {
        return reviewCrudService.getReviewWithRateAvg(productId);
    }

    @Override
    public Review createReviewWithUserAndProduct(ReviewCreateRequestDto review) {
        User user = resolveUser();
        Product product = resolveProduct(review.getProductId());
        return reviewFactory.createWithRegisterRequest(review,user,product);
    }

    private Product resolveProduct(Long productId){
        return productCrudService.getProductById(productId);
    }
    private User resolveUser(){
        return userService.getDummyUser();
    }
}

 

๋ฆฌ๋ทฐ๋“ค์„ ๊ด€๋ฆฌํ•˜๋Š” ์„œ๋น„์Šค ์ฝ”๋“œ

 

๋‹ค์‹œ ํ•œ๋ฒˆ

 

๋ฆฌ๋ทฐ๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” User ๊ทธ๋ฆฌ๊ณ  Product๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

 

๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด ๋งจ ์•„๋ž˜ private ํด๋ž˜์Šค๋กœ User์™€ Product ์กฐํšŒ ๋กœ์ง์„ ๋งŒ๋“ค์—ˆ๋‹ค.

 

๊ถ๊ธˆ์ , ๊ทธ๋ฆฌ๊ณ  ๊ณ ๋ฏผ...

โ“ private ๋ฉ”์„œ๋“œ๋Š” ์•ˆ ์“ฐ๋Š” ๊ฒŒ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์—ฌ๋Ÿฌ๋ชจ๋กœ ์ข‹๋‹ค๊ณ (?) ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.. ๊ทธ๋Ÿผ ๋นผ์•ผ ํ• ๊นŒ์š”?

 

โ“ ๋ฆฌ๋ทฐ ๊ด€๋ จ ์„œ๋น„์Šค์ธ๋ฐ ๋‹ค๋ฅธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์—ฌ๊ธฐ์„œ ์กฐํšŒ๋ฅผ ํ•˜๋Š” ๊ฒŒ ๋งž์„๊นŒ์š”?

 

 ๊ทธ๋ž˜์„œ ? ๋‚œ ๋ญ˜ ํ–ˆ์„๊นŒ ?

Case 2.

@Service
@RequiredArgsConstructor
public class ReviewServiceImpl implements ReviewService{
    private final ReviewCrudService reviewCrudService;
    private final ReviewFactory reviewFactory;
    private final UserService userService;
    private final ProductCrudService productCrudService;

    @Override
    public void registerReview(ReviewCreateRequestDto review) {
        reviewCrudService.saveReview(createReviewWithUserAndProduct(review));
    }

    @Override
    public List<ReviewWithAvgProjection> getAllReview(Long productId) {
        return reviewCrudService.getReviewWithRateAvg(productId);
    }

    @Override
    public Review createReviewWithUserAndProduct(ReviewCreateRequestDto review) {
        return reviewFactory.createWithRegisterRequest(review);
    }
    
}

 

Case 1. ์—์„œ ๋ฆฌ๋ทฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ReviewService์—  UserService, ProductService๋ฅผ ์˜์กด์„ฑ ์ฃผ์ž…๋ฐ›์•„์„œ ์‚ฌ์šฉํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

Case 2. ์—์„œ๋Š” ์ž…๋ ฅ๋ฐ›์€ ๋ฆฌ๋ทฐ์˜ ๋‚ด์šฉ, ํ‰์ , productId ๊ฐ€ ๋‹ด๊ธด DTO๋ฅผ ๊ทธ๋Œ€๋กœ Review๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ๋ณด๋‚ด๋ฒ„๋ ธ์Šต๋‹ˆ๋‹ค.

 

@Component
@RequiredArgsConstructor
public class ReviewFactory {
    private final UserService userService;
    private final ProductCrudService productCrudService;

    public Review createWithRegisterRequest(ReviewCreateRequestDto reviewCreateRequestDto, User user, Product product){
        String constent = reviewCreateRequestDto.getContent();
        Integer rating = reviewCreateRequestDto.getRating();
        return Review.builder().content(constent).rating(rating).user(user).product(product).build();
    }

    public Review createWithRegisterRequest(ReviewCreateRequestDto reviewCreateRequestDto) {
        User user = userService.getDummyUser();
        Product product = productCrudService.getProductById(reviewCreateRequestDto.getProductId());
        return Review.builder()
                .content(reviewCreateRequestDto.getContent())
                .rating(reviewCreateRequestDto.getRating())
                .user(user)
                .product(product)
                .build();
    }
}

 

์š”์•ฝ์„ ํ•˜์ž๋ฉด,

 

๊ธฐ์กด(Case1.) Review ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์—๋Š” (๋ฆฌ๋ทฐ์˜ ๋‚ด์šฉ, ํ‰์ ) DTO , Product, User๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ Review ๊ฐ์ฒด ์ƒ์„ฑ.

 

๋ณ€๊ฒฝ(Case1.) Review ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์—๋Š” (๋ฆฌ๋ทฐ์˜ ๋‚ด์šฉ, ํ‰์ , productId) DTO๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ Review ๊ฐ์ฒด ์ƒ์„ฑ.

 

โ“ ์™œ ์ด๋ ‡๊ฒŒ ํ–ˆ์„๊นŒ ๋‚œ?

โœ…  ์—”ํ‹ฐํ‹ฐ ๋‚ด๋ถ€์— ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์•ˆ ๋‘” ์ด์œ ๋„, ๊ฐ์ฒด ์ƒ์„ฑ ๋กœ์ง์ด ๋ณต์žก ํ•ด์ง€๋ฉด ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋ฌด๊ฑฐ์›Œ์ง€๊ธฐ ๋•Œ๋ฌธ์— ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌ๋ฅผ ํ–ˆ์Œ.

๊ทผ๋ฐ? ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ˜ธ์ถœ์ž์—์„œ ๊ฐ์ฒด ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๋ชจ๋“  ์ธ์ž๋ฅผ ๋„ฃ์–ด ์ฃผ๊ณ  ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ•œ๋‹ค๋ฉด, ๊ตณ์ด...? ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ„๋ฆฌํ•  ํ•„์š”๊ฐ€ ์žˆ์„๊นŒ?๋ผ๋Š” ์ƒ๊ฐ์œผ๋กœ ํ•จ.

 

โœ…  ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋Š” ํ•ด๋‹น ๊ฐ์ฒด ์ƒ์„ฑ์— ๋Œ€ํ•œ ์ฑ…์ž„์ด ์žˆ๋Š”๋ฐ, Review๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ReviewService์—์„œ UserService, ProductService๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š” ๊ฒƒ๋„ ๋งˆ์Œ์— ์•ˆ ๋“ค์—ˆ๋‹ค. ์˜ˆ์‹œ๋Š” Review๋งŒ ๋“ค์—ˆ์ง€๋งŒ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ๋„ ๋น„์Šทํ•œ ๊ณ ์ถฉ์„ ๊ฒช์—ˆ๋‹ค.

 

โœ…  ๊ทธ๋ž˜ DTO๋‚˜ VO๋Š” ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ์ƒ์„ฑํ•œ๋‹ค๊ณ  ํ•˜์ง€๋งŒ, ์ด๊ฑฐ์•ผ ๋ง๋กœ ๊ฐ์ฒด์ƒ์„ฑ ๋กœ์ง์ด ๋ณต์žกํ•œ ๊ฑฐ ์•„๋‹Œ๊ฐ€? ์ถ”ํ›„ ๋‹ค๋ฅธ ์„œ๋น„์Šค์—์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ผ์ด ์žˆ๋‹ค๋ฉด ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์— ๊ธฐ๋ณธ์ ์ธ ๊ฐ’๋งŒ ๋„ฃ์–ด์ฃผ๋ฉด ํ•ด๋‹น ๊ฐ์ฒด์™€ ์—ฐ๊ด€ ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์•Œ์•„์„œ ์กฐํšŒํ•ด ์ฃผ๋‹ˆ๊นŒ ํŽธํ•œ ๊ฑฐ ์•„๋…€?

 

โ“ ๊ถ๊ธˆ์  ์ด ์ •๋ฆฌ (๊ถ๊ธˆํ•œ ๊ฑฐ ์ฐธ๋ง๋กœ ๋งŽ๋‹ค)

โ“ ๊ทผ๋ฐ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค์— ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•ด์„œ ์“ฐ๋Š” ๊ฒŒ ๊ณผ์—ฐ ๊ดœ์ฐฎ์„๊นŒ? case 1. ๊ณผ case 2. ์ค‘ ์ ํ•ฉํ•œ ๊ฑด?

 

โ“ private ๋ฉ”์„œ๋“œ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฉด ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ํž˜๋“ค๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ, ๊ทธ๋Ÿผ ์™œ ์“ฐ๋Š” ๊ฑฐ์ง€?

(Review์„œ๋น„์Šค์—์„œ Product, User ์กฐํšŒํ•˜๋Š” ๋กœ์ง๋“ค์€ ๋ฆฌ๋ทฐ์„œ๋น„์Šค๋ž‘ ์ง์ ‘์ ์ธ ๊ด€๊ณ„๊ฐ€ ์—†์–ด์„œ ์ผ๋‹จ private ๋ฉ”์„œ๋“œ๋กœ ์ฒ˜๋ฆฌํ•ด ๋†“์Œ)


๋ฐœํ’ˆ ํŒ”๊ธฐ


์ •๋ฆฌ

private ๋ฉ”์„œ๋“œ์—์„œ ์‚ฌ์šฉํ•œ ๊ฑด ๋‹จ์ˆœํžˆ ๋‹ค๋ฅธ ์„œ๋น„์Šค์˜ ๊ธฐ๋Šฅ์„ ํ˜ธ์ถœํ•œ ๊ฑฐ๋ฐ–์— ์—†๋‹ค. ํ˜ธ์ถœํ•œ ์„œ๋น„์Šค์—์„œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ธฐ์— private๋กœ ํ•œ๋‹ค ํ•œ๋“ค ๋ฌธ์ œ๊ฐ€ ํฌ๊ฒŒ ์—†์„ ๊ฑฐ๋ž€ ์ƒ๊ฐ์ด ๋“ ๋‹ค. BUT ๋„ˆ๋ฌด ๊ณผํ•˜๊ฒŒ ์‹œ์šฉํ•œ๋‹ค๋ฉด ์ฝ”๋“œ์— ์ค‘๋ณต์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ์„ ๊ฑฐ ๊ฐ™์•„์„œ ์‚ฌ์šฉ์€ ํ•˜๋˜ ๋–ก์น ์€ ํ•˜์ง€ ๋ง์ž.

 

์•„๋ฌด๋ž˜๋„ Case 2. ๋‚ด๊ฐ€ ์ด์ƒํ•œ ์ƒ๊ฐ์„ ํ•œ ๊ฑฐ ๊ฐ™๋‹ค ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ ํ˜ธ์ถœ์ž๊ฐ€ ์ฃผ๋Š” ๊ฒŒ ๋งž๊ณ , ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด์ƒ์„ฑ์˜ ์ฑ…์ž„๋งŒ ์ง€๋ฉด ๋œ๋‹ค.

์ƒ์„ฑ์˜ ์ฑ…์ž„์ด๋ผ๊ธธ๋ž˜ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๊ฒƒ๋“ค๊นŒ์ง€ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒŒ ํ•˜๋‚˜์˜ ์ฑ…์ž„์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ ์ž˜๋ชป ์ƒ๊ฐ ํ•œ๊ฑธ์ˆ˜๋„ ์žˆ๊ฒ ๋‹ค!