์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

๋‚˜ํ˜ผ์ž ๋ฏธ์А๋žญ ๊ฐœ๋ฐœ์ผ์ง€ #8 – ๋ฆฌ๋ทฐ ์ˆ˜์ • ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๋ฐ ๋ณ„์  ๊ตฌ์กฐ ๊ฐœ์„ 

Coding Kitsune 2025. 6. 3. 01:22

๐Ÿ“Œ scope ?

  • ๋ฆฌ๋ทฐ ์ˆ˜์ • ํŽ˜์ด์ง€(EditReviewPage) ๊ฐœ๋ฐœ
  • ์Œ์‹/๋ถ„์œ„๊ธฐ/์„œ๋น„์Šค ๋ณ„์  ๋ถ„๋ฆฌ ๊ตฌ์กฐ ๋ฐ˜์˜
  • ๋ฐฑ์—”๋“œ ๋ฆฌ๋ทฐ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ ์ˆ˜์ •
  • ๋ฆฌ๋ทฐ ์ˆ˜์ • API ๋ฐ ์ด๋ฏธ์ง€ ์—…๋ฐ์ดํŠธ ๊ธฐ๋Šฅ ๊ตฌํ˜„
 

 

 

1. ๋ฆฌ๋ทฐ ์ˆ˜์ • ๊ธฐ๋Šฅ ํ•„์š”์„ฑ

๋ฆฌ๋ทฐ ์ž‘์„ฑ ์ดํ›„ ์‚ฌ์šฉ์ž๊ฐ€ ๋‚ด์šฉ์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋‹จ์ˆœํžˆ ํ‰์  ํ•˜๋‚˜๋งŒ ๋ฐ”๊พธ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ์Œ์‹/๋ถ„์œ„๊ธฐ/์„œ๋น„์Šค ๊ฐ๊ฐ์˜ ์ ์ˆ˜๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ๋ฐ›๊ณ  ์žˆ์—ˆ๊ธฐ์—, ๊ธฐ์กด ๋ฆฌ๋ทฐ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ ์ž์ฒด๋ฅผ ๋ฐ”๊ฟ”์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค... (์„ค๊ณ„ํ•  ๋•Œ ํ•œ๋ฒˆ ๋” ์ƒ๊ฐํ• ๊ฑธ....ใ…œ)

 

 

 

2. BE ๋ฆฌ๋ทฐ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ ์ˆ˜์ •

๊ธฐ์กด์—๋Š” ํ‰๊ท  ํ‰์  rating ํ•„๋“œ๋งŒ ์žˆ์—ˆ์ง€๋งŒ, ์ด๋ฒˆ ์ˆ˜์ •์œผ๋กœ ๋‹ค์Œ 3๊ฐ€์ง€ ํ•ญ๋ชฉ๋“ค์„ ์ถ”๊ฐ€ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  • foodRating: ์Œ์‹ ๋ง›์— ๋Œ€ํ•œ ์ ์ˆ˜
  • moodRating: ๋ถ„์œ„๊ธฐ ์ ์ˆ˜
  • serviceRating: ์„œ๋น„์Šค ์ ์ˆ˜

์ˆ˜์ •๋œ DTO:

public class ReviewUpdateRequest {
    private Float foodRating;
    private Float moodRating;
    private Float serviceRating;
    private Float rating; // ์„ธ ํ•ญ๋ชฉ์˜ ํ‰๊ท ๊ฐ’
    private String comment;
}
 
 
 

3. ๋ฆฌ๋ทฐ ์ˆ˜์ • API ๊ตฌํ˜„

์ปจํŠธ๋กค๋Ÿฌ์—์„œ @RequestPart๋ฅผ ํ™œ์šฉํ•˜์—ฌ JSON + ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋™์‹œ์— ๋ฐ›๋„๋ก ์ฒ˜๋ฆฌ.

@PutMapping("/{id}")
public ReviewResponse updateReview(@PathVariable Long id,
    @RequestPart("review") @Valid ReviewUpdateRequest request,
    @RequestPart(value = "image", required = false) MultipartFile imageFile) {
    return reviewService.updateReview(id, request, imageFile);
}

 

 

Service ์ฃผ์š” ๋กœ์ง:

  • ๊ธฐ์กด ๋ฆฌ๋ทฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ → ์—†์œผ๋ฉด ์˜ˆ์™ธ
  • ๊ฐ ๋ณ„์ , ์ฝ”๋ฉ˜ํŠธ ์—…๋ฐ์ดํŠธ
  • LocalDateTime.now()๋กœ ์ˆ˜์ • ์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ
  • ์ด๋ฏธ์ง€๊ฐ€ ์ „๋‹ฌ๋œ ๊ฒฝ์šฐ๋งŒ ์ƒˆ๋กœ ์—…๋กœ๋“œ → ๊ธฐ์กด ์ด๋ฏธ์ง€ ์œ ์ง€
  • ๋ณ€๊ฒฝ ์‚ฌํ•ญ ์ €์žฅ ํ›„ ์‘๋‹ต DTO๋กœ ๋ณ€ํ™˜

์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊นŒ์ง€ ๋ช…์‹œ:

if (imageFile != null && !imageFile.isEmpty()) {
    try {
        String imageUrl = s3Uploader.upload(imageFile);
        review.setImageUrl(imageUrl);
    } catch (IOException e) {
        throw new RuntimeException("์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ", e);
    }
}
 
 
 

4. FE – EditReviewPage ๊ตฌ์„ฑ

์ƒˆ ํŽ˜์ด์ง€ EditReviewPage.jsx๋ฅผ ์ƒ์„ฑํ•ด์„œ ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ๊ตฌ์„ฑ.

 

flowb:

  • useParams()๋กœ ๋ฆฌ๋ทฐ id ์ถ”์ถœ ํ›„ ๊ธฐ์กด ๋ฆฌ๋ทฐ ์ •๋ณด GET ์š”์ฒญ
  • ๊ฐ€์ ธ์˜จ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒํƒœ ์ดˆ๊ธฐํ™” (๋ณ„์ , ์ฝ”๋ฉ˜ํŠธ, ์ด๋ฏธ์ง€)
  • ์ˆ˜์ •๋œ ํ‰์ ์„ ๊ธฐ์ค€์œผ๋กœ ํ‰๊ท  ํ‰์  ๊ณ„์‚ฐ
  • FormData๋กœ JSON(review) + image ํ•จ๊ป˜ ์„œ๋ฒ„์— ์ „์†ก
  • ์ˆ˜์ • ์„ฑ๊ณต ์‹œ /list๋กœ ๋ฆฌ๋””๋ ‰์…˜

๋ณ„์  ์ปดํฌ๋„ŒํŠธ๋Š” ๊ธฐ์กด StarRating์„ ๊ทธ๋Œ€๋กœ ์žฌํ™œ์šฉ. ์ด๋ฏธ์ง€ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๊ธฐ๋Šฅ๋„ ์ถ”๊ฐ€ํ•˜์—ฌ, ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ ์ด๋ฏธ์ง€๋ฅผ ์„ ํƒํ–ˆ๋Š”์ง€ ๋ช…ํ™•ํžˆ ์ธ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ .

 

 

5. ๊ณ ๋ ค ์‚ฌํ•ญ ๋ฐ ๊ฐœ์„  ํฌ์ธํŠธ

  • ํ‰๊ท  ํ‰์ ์€ ํด๋ผ์ด์–ธํŠธ์—์„œ ๊ณ„์‚ฐํ•ด์„œ ์„œ๋ฒ„๋กœ ๋„˜๊ธฐ๋Š” ๊ตฌ์กฐ๋กœ ๊ตฌํ˜„ (์„œ๋ฒ„ ๊ณ„์‚ฐ ๊ณ ๋ ค)
  • ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ์ด ์—†๋Š” ๊ฒฝ์šฐ ๊ธฐ์กด ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•จ์œผ๋กœ์จ S3 ํŠธ๋ž˜ํ”ฝ ์ตœ์†Œํ™”
  • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๋ฐ ์˜ค๋ฅ˜ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€๋Š” ํ›„์† ์ž‘์—…์œผ๋กœ ๊ฐœ์„  ์˜ˆ์ •
 
์ˆ˜์ • ์„ฑ๊ณต !
 
 

Today Key word

  • ๋ณ„์  ํ•ญ๋ชฉ ๋ถ„๋ฆฌ (food/mood/service)
  • ๋ฆฌ๋ทฐ ์ˆ˜์ • API (PUT + multipart/form-data)
  • ์ด๋ฏธ์ง€ ์ˆ˜์ • ๋ฐ S3 ์—ฐ๋™
  • ํ”„๋ก ํŠธ์—”๋“œ EditReviewPage ๊ตฌํ˜„