DevLog ๐Ÿ˜ถ

[์šฐํ…Œ์ฝ” 5๊ธฐ] ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฏธ์…˜ ํšŒ๊ณ  ๋ณธ๋ฌธ

์šฐ์•„ํ•œํ…Œํฌ์ฝ”์Šค/๋ ˆ๋ฒจ 2

[์šฐํ…Œ์ฝ” 5๊ธฐ] ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฏธ์…˜ ํšŒ๊ณ 

dolmeng2 2023. 5. 15. 16:24

ํ—™ํฌ์™€ ์ง„ํ–‰ํ•œ ๋ ˆ๋ฒจ 2 ๋‘ ๋ฒˆ์งธ ํŽ˜์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฏธ์…˜์ธ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฏธ์…˜์ด๋‹ค!

์–ด์ฉŒ๋‹ค ๋ณด๋‹ˆ ๋ ˆ๋ฒจ 1 ๋ฐ์ผ๋ฆฌ ์กฐ ํŒ€์›๋“ค๊ณผ ํ•œ ๋ฒˆ์”ฉ ํŽ˜์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋Š” ๋Š๋‚Œ์ด๋‹ค ใ…Ž_ใ…Ž ์žฌ๋ฐŒ๋‹ค!

 

์ด๋ฒˆ ๋ฏธ์…˜์—์„œ๋Š” ์š”๊ตฌ์‚ฌํ•ญ๋ณด๋‹ค๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ์ง„ํ–‰ํ•˜๊ณ  ์‹ถ์€ ๋ถ€๋ถ„๋“ค์— ๋Œ€ํ•ด ๊ตฌํ˜„ํ•˜๋‹ค ๋ณด๋‹ˆ ๋˜๊ฒŒ ์žฌ๋ฐŒ๊ฒŒ ๊ตฌํ˜„ํ–ˆ์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ... ์ง€๊ธˆ ์™€์„œ ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ˆ ์•„์ง ๋งŽ์ด ๋ถ€์กฑํ•˜๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค ๐Ÿฅฒ... ์–ด๋ ต๋‹ค!

 


โœ”๏ธ ์ž‘์„ฑํ•œ ์ฝ”๋“œ

 

GitHub - Cl8D/jwp-shopping-cart: ๋ ˆ๋ฒจ 2 ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฏธ์…˜ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ

๋ ˆ๋ฒจ 2 ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ฏธ์…˜ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ. Contribute to Cl8D/jwp-shopping-cart development by creating an account on GitHub.

github.com

 

โœ”๏ธ 1์ฐจ PR

 

[1๋‹จ๊ณ„ - ์ƒํ’ˆ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ] ์ ธ๋‹ˆ(์ด์ง€์›) ๋ฏธ์…˜ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค. by Cl8D · Pull Request #202 · woowacourse/jwp-shopp

์•ˆ๋…•ํ•˜์„ธ์š”, ์ฝ”์ง€! ๋ฐฑ์—”๋“œ 5๊ธฐ ํฌ๋ฃจ ์ ธ๋‹ˆ์ž…๋‹ˆ๋‹ค ๐Ÿ™‡‍โ™€๏ธ ์ด๋ฒˆ์— ํ—™ํฌ์™€ ๋ ˆ๋ฒจ 2 ๋‘ ๋ฒˆ์งธ ๋ฏธ์…˜์ธ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜์–ด์š”. ์กฐ๊ธˆ ๋” ์ด๊ฒƒ์ €๊ฒƒ ํ•ด๋ณด๊ณ  ์‹ถ์–ด์„œ ์ƒํ’ˆ์— ๋Œ€ํ•œ ์นดํ…Œ๊ณ ๋ฆฌ ํ•„๋“œ

github.com

 

โœ”๏ธ 2์ฐจ PR

 

[2๋‹จ๊ณ„ - ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ธฐ๋Šฅ] ์ ธ๋‹ˆ(์ด์ง€์›) ๋ฏธ์…˜ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค. by Cl8D · Pull Request #270 · woowacourse/jwp-shoppi

์•ˆ๋…•ํ•˜์„ธ์š”, ์ฝ”๋‹ค! ๐Ÿ™‡‍โ™€๏ธ ์ง€๋‚œ 1๋‹จ๊ณ„ ๋ฏธ์…˜ ๋•Œ ๋น ๋ฅด๊ฒŒ ํ”ผ๋“œ๋ฐฑ ํ•ด์ฃผ์…”์„œ 2๋‹จ๊ณ„๋„ ๊ธˆ๋ฐฉ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์—ˆ์–ด์š”. ๊ฐ์‚ฌ๋“œ๋ ค์š”! ๊ฐœ์ธ์ ์ธ ์š•์‹ฌ์œผ๋กœ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์„ ๋” ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ๊ธฐ๋Š” ํ–ˆ๋Š”๋ฐ, ๋จผ์ €

github.com


โœ”๏ธ ๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ

- ์ƒํ’ˆ ๋ชฉ๋ก ํŽ˜์ด์ง€ ์—ฐ๋™ํ•˜๊ธฐ (Thymeleaf)

- ์ƒํ’ˆ ๊ด€๋ฆฌ CRUD API ์ž‘์„ฑํ•˜๊ธฐ

- ๊ด€๋ฆฌ์ž ๋„๊ตฌ ํŽ˜์ด์ง€ ์—ฐ๋™ํ•˜๊ธฐ

- ์ƒํ’ˆ ๋„๋ฉ”์ธ ์„ค๊ณ„ (์ž์œ ๋กญ๊ฒŒ, ID, ์ด๋ฆ„, ์ด๋ฏธ์ง€ URL, ๊ฐ€๊ฒฉ์€ ๊ณ ์ •)

- ์‚ฌ์šฉ์ž ๋„๋ฉ”์ธ ์„ค๊ณ„ (์ž์œ ๋กญ๊ฒŒ, ์ด๋ฉ”์ผ, ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ๊ณ ์ •)

- ์‚ฌ์šฉ์ž ์„ค์ • ํŽ˜์ด์ง€ ์—ฐ๋™

- ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ธฐ๋Šฅ ๊ตฌํ˜„ (์ƒํ’ˆ ์ถ”๊ฐ€, ์ œ๊ฑฐ, ๋ชฉ๋ก ์กฐํšŒ, Basic ์ธ์ฆ ๋ฐฉ์‹)

 

๋‚˜๋Š” ์—ฌ๊ธฐ๋‹ค๊ฐ€ ์‚ฌ์šฉ์ž ์ถ”๊ฐ€, ์ƒํ’ˆ ์นดํ…Œ๊ณ ๋ฆฌ ๊ธฐ๋Šฅ, ๊ด€๋ฆฌ์ž ๊ธฐ๋Šฅ, api ๋ฌธ์„œ๊นŒ์ง€ ์ ์šฉํ•ด๋‘์—ˆ๋‹ค.

rest-docs ๊ด€๋ จํ•ด์„œ๋Š” ์ถ”๊ฐ€์ ์œผ๋กœ ๊ธ€์„ ์ž‘์„ฑํ•  ์˜ˆ์ •์ด๋‹ค ใ…Ž_ใ…Ž


๋Š˜ ๊ทธ๋žฌ๋“ฏ์ด ๊ณ ๋ฏผํ–ˆ๋˜ ๋ถ€๋ถ„๊ณผ ๋‚˜๋ฆ„์˜ ์†”๋ฃจ์…˜์— ๋Œ€ํ•ด์„œ ์ž‘์„ฑํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

 

 

๐Ÿ’ฌ Redirect๊ฐ€ ๋ฌด์—‡์ผ๊นŒ?

์‚ฌ์‹ค ์ด๊ฑฐ๋Š”... ๋‚ด๊ฐ€ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ์ œ๋Œ€๋กœ ์žก์ง€ ๋ชปํ•ด์„œ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ์˜€๋‹ค ๐Ÿฅฒ

@GetMapping
public String getProducts(final Model model) {
    final List<ProductDto> products = productService.getProducts();
    model.addAttribute("products", products);
    return "admin";
}

์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ์—์„œ ๋ทฐ ์ด๋ฆ„์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์€ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋กœ ๋ด์•ผ ํ•˜๋ƒ๊ณ  ์งˆ๋ฌธ์„ ๋“œ๋ ธ์—ˆ๋‹ค.

๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋Š” ์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋‹ค๋ฅธ ์œ„์น˜์— ์žˆ์œผ๋‹ˆ, ํ•ด๋‹น ๋ฆฌ์†Œ์Šค ์œ„์น˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

-> ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์˜ ์ฃผ์†Œ๋กœ ๋‹ค์‹œ ์š”์ฒญ์„ ๋‚ ๋ฆฌ๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•˜๋‹ค.

์œ„์™€ ๊ฐ™์ด ๋ทฐ ์ด๋ฆ„์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์€ ๋‹จ์ˆœํžˆ ์š”์ฒญ์— ๋Œ€ํ•œ ๋ Œ๋”๋ง์„ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋กœ ๋ณด๊ธฐ๋Š” ์–ด๋ ต๋‹ค.

 

์ด๊ฑฐ๋Š” ์ถ”๊ฐ€์ ์œผ๋กœ JS ์ชฝ ์ฝ”๋“œ์ธ๋ฐ... ๊ด€๋ จ์€ ์—†์ง€๋งŒ ์ƒˆ๋กญ๊ฒŒ ์•ˆ ๊ฑฐ์—ฌ์„œ ์ •๋ฆฌํ•ด๋‘”๋‹ค.

  location.href location.replace
๊ธฐ๋Šฅ ์ƒˆ๋กœ์šด ํŽ˜์ด์ง€๋กœ ์ด๋™ ๊ธฐ์กด ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ์šด ํŽ˜์ด์ง€๋กœ ๋ณ€๊ฒฝ
ํ˜•ํƒœ ์†์„ฑ ๋ฉ”์„œ๋“œ
์ฃผ์†Œ ํžˆ์Šคํ† ๋ฆฌ ๊ธฐ๋ก๋œ๋‹ค (๋’ค๋กœ ๊ฐ€๊ธฐ ๊ฐ€๋Šฅ) ๊ธฐ๋ก๋˜์ง€ ์•Š๋Š”๋‹ค
์˜ˆ์‹œ location.href="" location.replace("")

 


 

๐Ÿ’ฌ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋Š” ์–ด๋””์—์„œ ํ•ด์•ผ ํ•˜๋Š”๊ฐ€? - ๋„๋ฉ”์ธ vs DTO

public class ProductDto {

    @Length(min = 1, max = 25, message = "์ƒํ’ˆ ์ด๋ฆ„์˜ ๊ธธ์ด๋Š” {min} ~ {max}๊ธ€์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.")
    private final String name;

    private final String imageUrl;

    @NotNull(message = "์ƒํ’ˆ ๊ฐ€๊ฒฉ์€ ๋น„์–ด์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
    @Range(min = 0, max = 10_000_000, message = "์ƒํ’ˆ ๊ฐ€๊ฒฉ์€ {min} ~ {max}์›๊นŒ์ง€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.")
    private final Integer price;

    @NotNull(message = "์ƒํ’ˆ ์นดํ…Œ๊ณ ๋ฆฌ๋Š” ๋น„์–ด์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
    private final ProductCategory category;
}

์ฒ˜์Œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์„ ๋•Œ๋Š” ์œ„์™€ ๊ฐ™์ด DTO์—์„œ ์ด๋ฆ„, ๊ฐ€๊ฒฉ์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์กฐ๊ฑด๋“ค๋„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก validation ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•˜์˜€์—ˆ๋‹ค.

๐ŸŒฑ
์ €๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋„ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š”๋ฐ์š”.
1. ๋น„์ฆˆ๋‹ˆ์Šค์™€ ๊ด€๋ จ๋œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
2. ๋‹จ์ˆœ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
์š”๋ ‡๊ฒŒ ๋‚˜๋ˆ„์–ด์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ ˆ์ด์–ด๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด์š”!

ํ•˜์ง€๋งŒ ๋ฆฌ๋ทฐ์–ด๋‹˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•˜๋Š” ๋ถ€๋ถ„์„ ๋‚˜๋ˆ ๋ณด๋Š” ๊ฒŒ ์–ด๋– ๋ƒ๊ณ  ์ด์•ผ๊ธฐ๋ฅผ ํ•ด์ฃผ์…จ๋‹ค.

๋‹น์‹œ์—๋Š” validation annotation์— ๊ต‰์žฅํžˆ ์ง‘์ฐฉ(?)์„ ํ•˜๊ณ  ์žˆ์—ˆ์–ด์„œ, ๋„๋ฉ”์ธ์—์„œ @Range, @Length ๊ฐ™์€ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•˜์—ฌ ๊ฒ€์ฆํ•˜๋ฉด ๋„๋ฉ”์ธ์—์„œ ๋ทฐ์— ์ถœ๋ ฅํ•  ๋ฌธ๊ตฌ๋ฅผ ์˜์กดํ•˜๋Š” ํ˜•ํƒœ๊ฐ€ ๋  ๊ฒƒ ๊ฐ™์•„์„œ ์„ ๋œป ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์› ๋‹ค. (์ง€๋‚œ๋ฒˆ ๋ฏธ์…˜ ๋•Œ ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ํ”ผ๋“œ๋ฐฑ์„ ๋“ค์—ˆ์–ด์„œ ๋” ์กฐ์‹ฌ์Šค๋Ÿฌ์› ๋˜ ๊ฒƒ๋„ ์žˆ๋‹ค ใ…Žใ…Ž)

 

ํ•˜์ง€๋งŒ...! ์ƒ๊ฐํ•ด๋ณด๋ฉด ๊ตณ์ด validation annotation์„ ์‚ฌ์šฉํ•  ํ•„์š”๋Š” ์—†์—ˆ๋‹ค.

๋ ˆ๋ฒจ 1 ๋ฏธ์…˜์—์„œ๋Š” ๊ทธ๋ƒฅ ์ž๋ฐ” ์ฝ”๋“œ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ๊ฒ€์ฆ์„ ํ–ˆ์—ˆ๊ณ , ๋งŒ์•ฝ ์ƒˆ๋กœ์šด ๊ฐœ๋ฐœ์ž๊ฐ€ ์™€์„œ '์ƒํ’ˆ ๋„๋ฉ”์ธ์— ํ•„์š”ํ•œ ํ•„๋“œ๋“ค์˜ ์ œ์•ฝ ์‚ฌํ•ญ์€ ์–ด๋””์—์„œ ๊ด€๋ฆฌ๋˜์ง€?'๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์„ ๋•Œ DTO๋ณด๋‹ค๋Š” ๋„๋ฉ”์ธ ํด๋ž˜์Šค๋ฅผ ๋จผ์ € ์—ด์–ด๋ณผ ๊ฒƒ ๊ฐ™์•˜๋‹ค.

 

๋˜ํ•œ, ์ง€๊ธˆ์€ SSR์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์‹œ์ง€ ์ž์ฒด๊ฐ€ ๋ฐ”๋กœ ๋ทฐ๋กœ ๋…ธ์ถœ๋˜์ง€๋งŒ, CSR ์ƒํ™ฉ์ด๋ผ๋ฉด ์—ฌ๊ธฐ์„œ ์ „ํŒŒ๋˜๋Š” ๋ฉ”์‹œ์ง€๋Š” ์‹ค์‚ฌ์šฉ์ž๊ฐ€ ์•„๋‹Œ ์ƒ๋Œ€ ๊ฐœ๋ฐœ์ž, ์ฆ‰ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ™•์ธํ•˜๋Š” ๋ฉ”์‹œ์ง€์ด๊ธฐ ๋•Œ๋ฌธ์— '๋„๋ฉ”์ธ์ด ๋ทฐ์— ์ถœ๋ ฅ๋  ๋ฉ”์‹œ์ง€๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค'๋ผ๋Š” ๊ด€์ ๊ณผ๋Š” ์กฐ๊ธˆ ๋–จ์–ด์ ธ ์žˆ๋‹ค๊ณ  ๋ด๋„ ๋œ๋‹ค.

 

๋ฌด์—‡๋ณด๋‹ค ๋„๋ฉ”์ธ ๊ฐ์ฒด๋Š” POJO๋กœ ๊ด€๋ฆฌ๋˜๋Š” ๊ฒŒ ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์„œ, ์•„๋ž˜์™€ ๊ฐ™์ด ๊ทธ๋ƒฅ ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๊ฒ€์ฆ์„ ์ง„ํ–‰ํ•ด์ฃผ์—ˆ๋‹ค.

public class ProductName {

    private static final int NAME_MIN_LENGTH = 1, NAME_MAX_LENGTH = 25;

    private final String name;
	
    ...

    private static void validateNameLength(final String name) {
        if (name.length() < NAME_MIN_LENGTH || name.length() > NAME_MAX_LENGTH) {
            throw new GlobalException(PRODUCT_NAME_LENGTH);
        }
    }
}

๊ทธ๋ฆฌ๊ณ  DTO ์ชฝ์—๋Š” ๋‹จ์ˆœํžˆ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ง„ํ–‰ํ•ด์ฃผ์—ˆ๋‹ค.

public class ProductRequest {

    @NotBlank(message = "์ƒํ’ˆ ์ด๋ฆ„์€ ๋น„์–ด์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
    private final String name;

    @NotNull(message = "์ƒํ’ˆ ๊ฐ€๊ฒฉ์€ ๋น„์–ด์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
    private final Integer price;

    @NotNull(message = "์ƒํ’ˆ ์นดํ…Œ๊ณ ๋ฆฌ๋Š” ๋น„์–ด์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
    private final String category;
    ...
}

 

์•ž์œผ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ์ค€์„ ํ†ตํ•ด์„œ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์„ ํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

- DTO : ๋ฐ์ดํ„ฐ ํƒ€์ž…์— ๋Œ€ํ•œ ๊ฒ€์ฆ
ex.
์ˆซ์ž๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋“ค์–ด์˜ค๋Š”๊ฐ€?
๋นˆ ๊ฐ’์ด ๋“ค์–ด์˜ค๋Š”๊ฐ€?
์ „ํ™”๋ฒˆํ˜ธ ํ˜•ํƒœ (-๋กœ ๊ตฌ๋ถ„๋œ 13๊ธ€์ž)์ธ๊ฐ€?
์ด๋ฉ”์ผ ํ˜•ํƒœ (@๋กœ ๊ตฌ๋ถ„๋œ ํ˜•ํƒœ)์ธ๊ฐ€?

- ๋„๋ฉ”์ธ: ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์— ๋Œ€ํ•œ ๊ฒ€์ฆ
ex.
๊ฐ€๊ฒฉ์€ 0์› ~ 10000์› ์ดํ•˜์˜ ๊ฐ’์„ ๊ฐ€์ง€๋Š”๊ฐ€?
์ด๋ฆ„์˜ ๊ธธ์ด๋Š” ์ตœ์†Œ 1๊ธ€์ž ์ด์ƒ์ธ๊ฐ€?
์ด๋ฉ”์ผ์˜ ๋„๋ฉ”์ธ์ด ํŠน์ • ๋„๋ฉ”์ธ๋งŒ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€? (gmail, daum, naver... etc)

 


 

๐Ÿ’ฌ Dto <-> Entity ๋ณ€ํ™˜ ๋กœ์ง์€ ์–ด๋””์— ์žˆ์œผ๋ฉด ์ข‹์„๊นŒ?

public class ProductDto {
    public Product toEntity() {
        return new Product(name, imageUrl, price, category);
    }

    public static ProductDto fromEntity(final Product product) {
        return new ProductDto(product.getId(), product.getName(), product.getImageUrl(),
                product.getPrice(), product.getCategory());
    }
}

์‚ฌ์‹ค ์ด๊ฑฐ๋Š” ์ •๋ง ๋ฆฌ๋ทฐ์–ด๋‹˜๋งˆ๋‹ค ์ •๋ง ๋งŽ์ด ๊ฐˆ๋ฆฌ๋Š” ๋ถ€๋ถ„์ธ ๊ฒƒ ๊ฐ™๋‹ค.

 

๋‚ด ๋ฆฌ๋ทฐ์–ด๋‹˜ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์˜์กด๊ด€๊ณ„๊ฐ€ Controller -> Dto -> Entity์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ํ๋ฅด๊ฒŒ ๋œ๋‹ค๋ฉด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํ•ด๋‹น Dto ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด์„œ ๋„๋ฉ”์ธ์— ๋Œ€ํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ์ง€๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ƒ๊ณ  ๋ง์”€ํ•ด ์ฃผ์…จ๋‹ค.

๋ฌผ๋ก , ๊ฐœ๋ฐœ์ž์˜ ์ดํ•ด๋„๊ฐ€ ๋†’๋‹ค๋ฉด Dto์—์„œ Entity๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ฝ”์–ดํ•œ ๋„๋ฉ”์ธ ๊ณ„์ธต์˜ ๊ฐ์ฒด๋ฅผ ์นจ๋ฒ”ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๊ฑฐ์˜ ์—†๊ฒ ์ง€๋งŒ, ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜์˜ ์‹œ์ž‘์€ '~ํ•œ ์œ„ํ—˜์ด ์žˆ์ง€ ์•Š์„๊นŒ?'๋กœ ๋ถ€ํ„ฐ ์‹œ์ž‘๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ์œ„ํ—˜์„ฑ์€ ๋Š์–ด์ฃผ๋Š” ๊ฒŒ ์˜ณ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ๋ฆฌํŒฉํ„ฐ๋ง ์‹œ์—๋Š” service layer์—์„œ private method๋ฅผ ํ†ตํ•ด ์œ„์™€ ๊ฐ™์€ ๋ณ€ํ™˜ ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋งŒ๋“ค์—ˆ๊ณ , ์ถ”ํ›„ ๋งคํ•‘ํ•˜๋Š” ํด๋ž˜์Šค๋“ค์ด ๋งŽ์•„์ง„๋‹ค๋ฉด ๋ณ„๋„์˜ mapper class๋ฅผ ๋‘์–ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•˜์˜€๋‹ค. (๋งคํผ ํด๋ž˜์Šค ์—ญ์‹œ service์™€ ๊ฐ™์€ ๊ณณ์— ์œ„์น˜)

 

+) ์˜์กด ๊ด€๊ณ„๋ฅผ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ€์ ธ๊ฐ€๋ ค๋ฉด dto๊ฐ€ ์กด์žฌํ•ด์•ผ ํ•˜๋Š” ํŒจํ‚ค์ง€๋Š” service ์ชฝ์ด์–ด์•ผ ํ•œ๋‹ค ๐Ÿ˜Š

์•„๋ฌด ์ƒ๊ฐ ์—†์ด controller ์ชฝ์— ๋‘์—ˆ๋‹ค๊ฐ€ controller -> service -> dto ๊ฐ™์€ ์š”์ƒํ•œ ํ๋ฆ„ ๊ด€๊ณ„๊ฐ€ ์ƒ๊ฒจ๋ฒ„๋ ธ์—ˆ๋‹ค... ใ…Ž_ใ…Ž ์œ ์˜ํ•˜์ž!

 


 

๐Ÿ’ฌ ์—”ํ‹ฐํ‹ฐ์™€ ๋„๋ฉ”์ธ

์•„๋งˆ ์ด๋ฒˆ ๋ฏธ์…˜์—์„œ ๋‚˜๋ฅผ ๊ฐ€์žฅ ๋งŽ์ด ๊ดด๋กญํ˜”๋˜ ์ฃผ์ œ์ธ ๊ฒƒ ๊ฐ™๋‹ค ๐Ÿฅฒ (์—ฌ์ „ํžˆ ๊ฒฐ๋ก ์„ ํ™•์‹คํ•˜๊ฒŒ ๋‚ด๋ฆฌ์ง€ ๋ชปํ•œ ์ƒํƒœ์ด๋‹ค)

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

 

๋ฏธ์…˜ ์š”๊ตฌ์‚ฌํ•ญ์ด CRUD์ด๋‹ค ๋ณด๋‹ˆ๊นŒ DB์™€ ๊ต‰์žฅํžˆ ๋ฐ€์ ‘ํ•ด์ง€๊ณ , ํ…Œ์ด๋ธ”์— ๋‚ด์šฉ์„ ์‚ฝ์ž…ํ•˜๊ฑฐ๋‚˜, ์กฐํšŒํ•˜๊ฑฐ๋‚˜ ํ•˜๋Š” ๋กœ์ง๋งŒ ์žˆ๋‹ค ๋ณด๋‹ˆ ๋ณ„๋„์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐ๋˜์–ด ๋ณ„๋„๋กœ ๋‘˜ ํ•„์š”์„ฑ์„ ๋Š๋ผ์ง€ ๋ชปํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋˜ํ•œ, ์—”ํ‹ฐํ‹ฐ์˜ ๊ฒฝ์šฐ DB์™€ 1:1๋กœ ๊ฐ’์„ ๋งคํ•‘ํ•˜๊ณ , ๋ณ„๋„์˜ ๋กœ์ง ์—†์ด ๋‹จ์ˆœํžˆ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ญํ• ๋งŒ ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์—ˆ๋‹ค. 

 

ํ•˜์ง€๋งŒ, ์œ„์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์— ๋Œ€ํ•œ ๊ฒ€์ฆ์„ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋„๋ฉ”์ธ ํด๋ž˜์Šค๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค.

์—”ํ‹ฐํ‹ฐ์—์„œ ๊ฒ€์ฆ์„ ์ง„ํ–‰ํ•˜๊ธฐ์—๋Š”, ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๊ฐ€์ง€๋Š” ๊ฒƒ ๊ฐ™์•„์„œ ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์•˜๊ณ , ๊ทธ๋ ‡๋‹ค๊ณ  ๋„๋ฉ”์ธ์„ ๋งŒ๋“ค๊ธฐ์—๋Š” ๋‹จ์ˆœํžˆ ๊ฒ€์ฆ๋ฐ–์— ์•ˆ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ตณ์ด ๋งŒ๋“ค์–ด์•ผ ํ•˜๋‚˜...? ๋ผ๋Š” ์ƒ๊ฐ๋„ ๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค... ๐Ÿฅน (์—ฌ๊ธฐ์„œ ๋จธ๋ฆฌ ํ„ฐ์ง)

 

ํ•˜์ง€๋งŒ, ๋ฆฌ๋ทฐ์–ด๋‹˜์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ”ผ๋“œ๋ฐฑ์„ ๋‚จ๊ฒจ ์ฃผ์…จ๋‹ค.

๐ŸŒฑ ์ €๋Š” ๋„๋ฉ”์ธ์€ ํ•ญ์ƒ ์žˆ์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด์š”.
์ƒˆ๋กœ์šด ๊ฐœ๋ฐœ์ž๊ฐ€ ๋„๋ฉ”์ธ์— ๋Œ€ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด๋–ค ํด๋ž˜์Šค๋ฅผ ํ™•์ธํ• ๊นŒ์š”?

์ด ๋ง์„ ๋“ฃ๊ณ  ๋‚˜๋ฆ„๋Œ€๋กœ ๋„๋ฉ”์ธ๊ณผ ์—”ํ‹ฐํ‹ฐ์— ๋Œ€ํ•œ ์ •์˜๋ฅผ ๋‚ด๋ ค ์•„๋ž˜์™€ ๊ฐ™์ด ๋‹ต๋ณ€์„ ํ–ˆ๋‹ค.

๋ง์ด ๊ธธ์ง€๋งŒ ์š”์•ฝํ•˜์ž๋ฉด, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด๋Š” ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฉฐ, ์˜์†์„ฑ ๋ ˆ์ด์–ด์™€ ๊ฐ•๊ฒฐํ•ฉ์„ ๋งบ์€, ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋“ค์„ ์ €์žฅํ•˜๋Š” ๊ฐ์ฒด๋Š” ์—”ํ‹ฐํ‹ฐ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋„๋ฉ”์ธ / ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์—ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ, ์ด๋Ÿฌํ•œ ์ •์˜์—์„œ๋„ ๊ฒฐ๊ตญ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋ฐ–์— ์—†์—ˆ๋‹ค.

๋ฐ”๋กœ... Join์„ ํ†ตํ•ด์„œ ์กฐํšŒํ•ด์˜ฌ ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ์—”ํ‹ฐํ‹ฐ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š”์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.

๊ธฐ์กด์—๋Š” ์กฐ์ธ์„ ์ง„ํ–‰ํ•˜๋Š” ์ฃผ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ dao (CartDao)์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์˜€๊ณ , MemberProductEntity๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์กฐํšŒํ•ด์˜จ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด์•„์˜ค๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.

public class MemberProductEntity {
    private final Long cartId;
    private final Long memberId;
    private final Long productId;
    private final String productName;
    private final String productImageUrl;
    private final int productPrice;
    private final String productCategory;
	
    ...
}
public List<MemberProductEntity> getProductByMemberId(final Long memberId) {
    final String query = "SELECT c.id, c.member_id, c.product_id, p.name, p.image_url, p.price, p.category " +
            "FROM cart c JOIN product p ON c.product_id = p.id WHERE c.member_id = ?";
    return jdbcTemplate.query(query, (result, count) ->
            new MemberProductEntity(result.getLong("id"), result.getLong("member_id"),
                    result.getLong("product_id"), result.getString("name"),
                    result.getString("image_url"), result.getInt("price"),
                    result.getString("category")), memberId);
}

-> 1์ค„ ์š”์•ฝ: SRP ์œ„๋ฐ˜ ์•„๋‹๊นŒ์š”? + ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ด๋Ÿฐ ์‹์œผ๋กœ ์จ๋„ ๋˜๋‚˜์š”? + ๊ฒฐ๊ตญ ๋„๋ฉ”์ธ๊ณผ ์—”ํ‹ฐํ‹ฐ์˜ ์ฐจ์ด์ ์ด ๋ญ์ฃ ? (๋‹ค์‹œ ์›์ )

๋‹น์‹œ์—๋Š” ์—”ํ‹ฐํ‹ฐ๋Š” ๋„๋ฉ”์ธ์œผ๋กœ์„œ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ •๋ณด ์ „๋‹ฌ์— ๊ฐ€๊นŒ์šด ๊ฐ์ฒด๋ผ๋ฉด ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ์ €๋Ÿฐ ๊ตฌ์กฐ๋กœ ํ–ˆ๋‹ค.

 

๊ฐ“ ๋ฆฌ๋ทฐ์–ด๋‹˜์€ ์ด๊ฑธ ๋ณด๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ํ”ผ๋“œ๋ฐฑ์„ ๋‚จ๊ฒจ์ฃผ์…จ๋‹ค.

๐ŸŒฑ ๋„๋ฉ”์ธ: ์šฐ๋ฆฌ๊ฐ€ ํ•ด๊ฒฐํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฌธ์ œ ์˜์—ญ์ด์ž, ๋ฌธ์ œ ์˜์—ญ์„ ํด๋ž˜์Šคํ™” ํ•˜์—ฌ ์ฝ”๋“œ๋กœ ์˜ฎ๊ธด ๋ถ€๋ถ„
๐ŸŒฑ ์—”ํ‹ฐํ‹ฐ: ์‹๋ณ„์ž๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด
์œ„ ์ •์˜๋Œ€๋กœ๋ผ๋ฉด ๋„๋ฉ”์ธ์ด ๋” ํฐ ๋ฒ”์œ„์ด๋ฉด์„œ, ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๊ทธ ์ผ๋ถ€๋ถ„์œผ๋กœ ๋ณด์ผ ํ…๋ฐ, ๋งž์Šต๋‹ˆ๋‹ค!

๋„๋ฉ”์ธ์—๋Š” VO, Entity, Domain Service ๋“ฑ ๋งŽ์€ ๊ฒƒ๋“ค์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋ฌธ์ œ ์˜์—ญ์„ ํด๋ž˜์Šคํ™” ํ•œ ๊ฒƒ์ด๋ผ๋ฉด ๋ชจ๋‘ ๋„๋ฉ”์ธ์œผ๋กœ ๋ฐ”๋ผ๋ณธ๋‹ค๊ณ  ํ•˜์…จ๋‹ค. (์ด์— ๋Œ€ํ•ด์„œ ์˜ค๋Š˜ ํ—ˆ๋ธŒ๋ž‘๋„ ์ด์•ผ๊ธฐ๋ฅผ ๋‚˜๋ˆด์—ˆ๋Š”๋ฐ, ํ—ˆ๋ธŒ์˜ ๋ฆฌ๋ทฐ์–ด๋‹˜๋„ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋Œ€ํ•œ Service Layer๋ฅผ ๋„๋ฉ”์ธ ์ชฝ์œผ๋กœ ๋ฐ”๋ผ๋ณธ๋‹ค๊ณ  ๋ง์”€ํ•ด ์ฃผ์…จ๋‹ค.) ๊ทธ๋ฆฌ๊ณ , ๊ทธ ์ค‘์—์„œ ์‹๋ณ„์ž๊ฐ€ ์žˆ๋‹ค๋ฉด ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋œ๋‹ค.

 

์—ฌ๊ธฐ์„œ ์‹๋ณ„์ž๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ์ƒ์œผ๋กœ ๋‘ ๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ ์œ ํ•œ ๊ธฐ์ค€์ด๋‹ค.

DB์˜ pk ๊ฐ’์ด๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, PK๊ฐ€ ๋  ์ˆ˜๋„ ์žˆ๊ณ  ๋‹ค๋ฅธ ํ•„๋“œ ๊ฐ’์ด ๋  ์ˆ˜๋„ ์žˆ๋‹ค.

์–ด๋– ํ•œ ๊ฐ์ฒด๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ธฐ์ค€์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋งŒ์•ฝ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ƒ '์ด๋ฆ„'์ด๋ผ๋Š” ํ•„๋“œ๊ฐ€ ๊ณ ์œ ํ•˜๊ฒŒ ์กด์žฌํ•œ๋‹ค๋ฉด ํ•ด๋‹น ๊ฐ์ฒด๋Š” '์ด๋ฆ„'์ด๋ผ๋Š” ์‹๋ณ„์ž๋ฅผ ๊ฐ€์ง„ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋  ์ˆ˜๋„ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ๋ณ„๋„์˜ ์‹๋ณ„์ž๊ฐ€ ์žˆ๋Š” ๋„๋ฉ”์ธ์€ ๊ณง ์—”ํ‹ฐํ‹ฐ๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด ๋‹จ๊ณ„์—์„œ๋Š” DB์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.

 

๋งˆํ‹ด ํŒŒ์šธ๋Ÿฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ ๊ฐœ๋…๋“ค์„ ์ •์˜ํ•˜์˜€๋‹ค.

- Entity: Objects that have a distinct identity that runs through time and different representations. You also hear these called "reference objects".

- Value Object: Objects that matter only as the combination of their attributes. Two value objects with the same values for all their attributes are considered equal. I also describe value objects in P of EAA.

- Service: A standalone operation within the context of your domain. A Service Object collects one or more services into an object. Typically you will have only one instance of each service object type within your execution context.

์ด์ „ ๋ฏธ์…˜์„ ํ•˜๋ฉด์„œ Reference Object์™€ Value Object์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•œ ์ ์ด ์žˆ์—ˆ๋Š”๋ฐ ์—ฌ๊ธฐ์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ Reference Object๋กœ์„œ ์ƒ๊ฐํ•œ๋‹ค๋Š” ์ ์„ ๋ณด๊ณ  ํ™•์‹คํ•˜๊ฒŒ ์ดํ•ดํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. ์‹๋ณ„์ž๋กœ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ๋˜๋Š” ๊ฒƒ. ์šฐ์„  ๋‚˜๋Š” ์ด ์ •๋„๋กœ ์ดํ•ด๋ฅผ ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ณดํ†ต ์—”ํ‹ฐํ‹ฐ๋Š” ์‹๋ณ„์ž๋กœ ๋™์ผ์„ฑ์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— equals, hashcode๋ฅผ ์ผ๋ฐ˜์ ์œผ๋กœ ์ •์˜ํ•˜์ง€ ์•Š๋Š”๋‹ค. 

 

์•„๋ฌดํŠผ, ๋‹ค์‹œ ๋Œ์•„์™€์„œ... ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ์ฒด๋กœ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ๋ณดํ†ต PK๋ฅผ ์ด์šฉํ•ด ์‹๋ณ„์ด ๋˜๋Š” Reference Object์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฒˆ ๋ ˆ๋ฒจ์—์„œ๋Š” DB์˜ PK๋ฅผ ์‹๋ณ„์ž๋กœ ์‚ฌ์šฉํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ณ„๋„๋กœ ๋‘์—ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ๋Œ€ํ•œ CUD ๋กœ์ง์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ’€์–ด๋‚˜๊ฐ”๋‹ค.

- '์žฅ๋ฐ”๊ตฌ๋‹ˆ (Cart)' ๋ผ๋Š” ๋„๋ฉ”์ธ์€ Member์™€ List<Product>์˜ ์กฐํ•ฉ์œผ๋กœ ๋งŒ๋“ค๊ธฐ.
: ํ•œ ๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ด์€ ๋ฌผ๊ฑด ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋„๋ฉ”์ธ ๊ฐ์ฒด.

- ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ƒํ’ˆ ์ €์žฅ, ์ œ๊ฑฐ ์‹œ ์‹๋ณ„์ž๋ฅผ ๊ฐ€์ง„ ์—”ํ‹ฐํ‹ฐ์ธ CartEntity๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ฐ”๋กœ insert๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— (๋ณธ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ DB์— ๋Œ€ํ•œ ์—ฐ์‚ฐ์ด ์œ„์ฃผ์ž„) ๋ณ„๋„์˜ ๋„๋ฉ”์ธ ๊ฐ์ฒด๋กœ ํ‘œํ˜„ํ•  ํ•„์š”๊ฐ€ ์—†์„ ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จ. (์–ด์ฐจํ”ผ ์—”ํ‹ฐํ‹ฐ๋„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฒ”์œ„๋กœ ๋ณธ๋‹ค๋ฉด ๋„๋ฉ”์ธ ๊ฐ์ฒด์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.)

- ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ƒํ’ˆ ์ •๋ณด ๋ฐ˜ํ™˜ ์‹œ ์กฐ์ธ์„ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋‹ˆ Entity๋ณด๋‹ค๋Š” DTO๋กœ ์‚ฌ์šฉ (์—ฌ๋Ÿฌ ๊ฐ’๋“ค์„ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Œ)

๋ง์ด ๊ธธ์ง€๋งŒ ๊ฒฐ๊ณผ์ ์œผ๋กœ ์—”ํ‹ฐํ‹ฐ์™€ ๋„๋ฉ”์ธ์„ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

 

๋Œ€์ถฉ ํ•œ ๊ฐ€์ง€ ์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ๋ณด์—ฌ์ฃผ์ž๋ฉด ์ด๋Ÿฐ ์‹์ด์—ˆ๋‹ค.

public CartResponse getCartResponseByMemberEmail(final String memberEmail) {
    final MemberEntity memberEntity = getMemberEntity(memberEmail);
    final List<CartDto> cartDtos = cartDao.getProductsByMemberId(memberEntity.getId());
    final Cart cart = convertToCart(memberEntity, cartDtos);
    final List<ProductResponse> productResponses = convertToProductResponse(cart);
    final int productCount = cart.getProductCount();
    return new CartResponse(productCount, productResponses);
}

๋‹ค๋งŒ, ์ด ๊ณผ์ •์—์„œ entity -> domain์œผ๋กœ ๋งŒ๋“œ๋Š” ์ปจ๋ฒ„ํŒ… ๋กœ์ง์ด ๋งŽ์•„์ ธ์„œ ์ฝ”๋“œ๊ฐ€ ์•ฝ๊ฐ„ ๋ณด๊ธฐ ํž˜๋“ค์–ด์กŒ๋‹ค.

๋˜ํ•œ, ์„œ๋น„์Šค ๋ ˆ์ด์–ด์—์„œ ๋„๋ฉ”์ธ, ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋‘˜ ๋‹ค ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉด์„œ service -> entity(persistence layer), service -> domain์™€ ๊ฐ™์€ ์ˆœํ™˜์ฐธ์กฐ ํ˜•ํƒœ๊ฐ€ ๋ฐœ์ƒํ•ด์„œ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ํ๋ฅด์ง€ ์•Š๊ฒŒ ๋˜์—ˆ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‹ค์Œ ๋ฏธ์…˜์—์„œ๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ ์šฉํ–ˆ๋Š”๋ฐ...! ์ด๊ฑฐ๋Š” ์ง€ํ•˜์ฒ  ๋ฏธ์…˜ ๋๋‚˜๊ณ  ํฌ์ŠคํŒ… ํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

 

๋‹ค์Œ ๋ฏธ์…˜๋„ ํŒŒ์ดํŒ…! ๐Ÿ’ช

Comments