[์ฐ์ํํ ํฌ์ฝ์ค 6๊ธฐ] ํ๋ฆฌ์ฝ์ค 4์ฃผ์ฐจ ํฌ๋ฆฌ์ค๋ง์ค ํ๋ก๋ชจ์ ๋ฏธ์ ํ๊ธฐ
by rlaehddnd0422๊ธธ์๋ 4์ฃผ๊ฐ์ ํ๋ฆฌ์ฝ์ค๊ฐ ๋์ด ๋ฌ์ต๋๋ค. ๋ง์ง๋ง ์ฃผ์ฐจ๋ ํฌ๋ฆฌ์ค๋ง์ค ํ๋ก๋ชจ์ ๋ฏธ์ ์ผ๋ก 3์ฃผ์ฐจ ๋ก๋ ๋ฏธ์ ๊ณผ ๋น์ทํ๋ ํ์ฅ๋ ๋งฅ๋ฝ์ ๋ฏธ์ ์ด์๋๋ฐ์. ๊ฐ๋จํ๊ฒ ์ด๋ฒ ์ฃผ์ฐจ์ ์ ์ฉํ๊ณ ๊ฐ์ ํ๊ณ ๊ณ ๋ฏผํ ์ ๋ค์ ๋ฆฌ๋ทฐํด๋ณด๊ณ ์ํฉ๋๋ค.
๐ฉ4์ฃผ์ฐจ ๋ชฉํ
- ์ฐ์ ์ ๋ ์ด๋ฒ ๋ฏธ์ ์์๋ ๋ค์๊ณผ ๊ฐ์ ๋ชฉํ๋ฅผ ๋์์ต๋๋ค.
- ์๊ตฌ์ฌํญ์ด ๋ง์์ง ๋งํผ, ๋ช ์ธ์ ๊ผผ๊ผผํ๊ฒ ํ์ธํ๊ณ ๊ตฌํํ๊ธฐ
- ๊ฐ์ฒด๋ฅผ ๊ฐ์ฒด์ค๋ฝ๊ฒ ์ฌ์ฉํ๊ธฐ
- ๋๋ฉ์ธ๊ณผ ๋๋ฉ์ธ ์ฌ์ด ์์กด๊ด๊ณ๋ฅผ ๋์ง ์๊ธฐ
- ๊ฐ์ฒด ์์ฑ์ ๋ค๋ฅธ ๋๋ฉ์ธ์ ๊ฐ์ด ํ์ํ ๊ฒฝ์ฐ ๋ฉ์์ง๋ฅผ ํตํด ์ฐ๊ฒฐ๊ณ ๋ฆฌ๋ฅผ ๋ง๋ค์ด ์์ฑํจ์ผ๋ก์จ, ์์ง๋๋ฅผ ๋ฎ์ถ์.
- getter ์ง์, TDA(Tell, Don't Ask) ์์น ์ ์ฉ : ๊ฐ์ฒด๊ฐ ํ ์ ์๋ ์ผ์ ๊ฐ์ฒด์๊ฒ ๋ฌผ์ด๋ณด์ง ์๊ณ ์ํค๋๋ก ํ์.
- ๊ฐ์ฒด๊ฐ ํ ์ ์๋ ์ผ์ด๋ผ ํจ์ ๊ฐ์ฒด์ ํ๋๊ฐ์ ๋ํ ํธ๋ค๋ง(๊ฒ์ฆ, ๊ณ์ฐ)
- View์์ ๋ถ๋์ดํ๊ฒ ๊ฐ์ฒด์ ํ๋๊ฐ์ ์ถ๋ ฅํด์ผ ํ๋ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๊ณ getter๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก ํ๊ธฐ.
- ๋๋ฉ์ธ๊ณผ ๋๋ฉ์ธ ์ฌ์ด ์์กด๊ด๊ณ๋ฅผ ๋์ง ์๊ธฐ
- ๋ค์ด๋ฐ์ ์กฐ๊ธ ๋ ์ ๊ฒฝ์ฐ๊ธฐ
- ์๋๋ฅผ ํด์น์ง ์์๊ณผ ๋์์ ํ ๋์ ์์๋ณผ ์ ์๋ ํค์๋ ์ค์ฌ์ผ๋ก ์๋ช ํ์.
- ์ต์ข
์ฝ๋ฉ ํ
์คํธ์์ ์๊ฐ ๋ด์ ๊ตฌํํ ์ ์๋ ์ฝ๋๋ฅผ ๋ง๋ค์.
- ๋น์ฆ๋์ค ํ์ฅ์ฑ์ ๊ณ ๋ คํด ํ์ฌ ์ฌ์ฉํ์ง ์๋ ์ฝ๋์ ๋ํด ๋ถํ์ํ๊ฒ ๋ณผ๋ฅจ์ ํค์ฐ๊ธฐ๋ณด๋ค, ์ต์ข ์ฝ๋ฉ ํ ์คํธ์์ ๋ด๊ฐ ๊ตฌํํ ์ ์๋ ์ฝ๋๋ฅผ ๊ตฌํํ์.
- ๋ฌด๋ฆฌํ ํ์ฅ์ ๊ฐ๋ ์ฑ์ ์ ํ์ํฌ ์ฐ๋ ค๊ฐ ํฌ๋ค. ํ์ฅ์ฑ์ ๊ณ ๋ คํ ์๊ฐ์ ์ฐจ๋ผ๋ฆฌ ๊ฐ์ฒด์งํฅ์ค๊ณ์ ํ์ ์์.
ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ๊ณผ ๊ธฐ๋ฅ ์๊ตฌ์ฌํญ์ ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๐ฉํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ
โก๏ธ ์ถ๊ฐ๋ ์๊ตฌ ์ฌํญ
- ์๋ ์๋ `InputView`, `OutputView` ํด๋์ค๋ฅผ ์ฐธ๊ณ ํ์ฌ ์
์ถ๋ ฅ ํด๋์ค๋ฅผ ๊ตฌํํฉ๋๋ค.
- ์ ๋ ฅ๊ณผ ์ถ๋ ฅ์ ๋ด๋นํ๋ ํด๋์ค๋ฅผ ๋ณ๋๋ก ๊ตฌํํฉ๋๋ค.
- ํด๋น ํด๋์ค์ ํจํค์ง, ํด๋์ค๋ช , ๋ฉ์๋์ ๋ฐํ ํ์ ๊ณผ ์๊ทธ๋์ฒ๋ ์์ ๋กญ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
public class InputView {
public int readDate() {
System.out.println("12์ ์ค ์๋น ์์ ๋ฐฉ๋ฌธ ๋ ์ง๋ ์ธ์ ์ธ๊ฐ์? (์ซ์๋ง ์
๋ ฅํด ์ฃผ์ธ์!)");
String input = Console.readLine();
}
}
public class OutputView {
public void printMenu() {
System.out.println("<์ฃผ๋ฌธ ๋ฉ๋ด>");
// ...
}
// ...
}
๐ฉ๊ธฐ๋ฅ ์๊ตฌ ์ฌํญ ์ ๋ฆฌ
โก๏ธ ๋ฉ๋ด
<์ ํผํ์ด์ >
์์ก์ด์ํ(6,000), ํํ์ค(5,500), ์์ ์๋ฌ๋(8,000)
<๋ฉ์ธ>
ํฐ๋ณธ์คํ ์ดํฌ(55,000), ๋ฐ๋นํ๋ฆฝ(54,000), ํด์ฐ๋ฌผํ์คํ(35,000), ํฌ๋ฆฌ์ค๋ง์คํ์คํ(25,000)
<๋์ ํธ>
์ด์ฝ์ผ์ดํฌ(15,000), ์์ด์คํฌ๋ฆผ(5,000)
<์๋ฃ>
์ ๋ก์ฝ๋ผ(3,000), ๋ ๋์์ธ(60,000), ์ดํ์ธ(25,000)
โก๏ธ ํ ์ธ
์ค๋ณต๋ ํ ์ธ + ์ฆ์ ์ผ๋ก ์ด๋ฒคํธ ๊ธฐ๊ฐ : '๋๋ฐ์ด ํ ์ธ'์ ์ ์ธํ ๋ชจ๋ ์ด๋ฒคํธ๋ 12์ 1์ผ ~ 31์ผ๊น์ง ์ ์ฉํ๋ค.
1. ๋๋ฐ์ด ํ ์ธ : 1000์์ผ๋ก ์์ํด์ ํ ์ธ๊ธ์ก์ด 100์์ฉ ์ฆ๊ฐํ๋ค.
- ex) 12์ 1์ผ 1000์, 2์ผ์ 1100์, 25์ผ์ 3400์
- ์ด๋ฒคํธ ๊ธฐ๊ฐ : ํ ์ธ์ 12์ 1์ผ๋ถํฐ 25์ผ๊น์ง
2. ํ์ผ ํ ์ธ (์ผ์์ผ~๋ชฉ์์ผ) : ๋์ ํธ ๋ฉ๋ด๋ฅผ ๋ฉ๋ด 1๊ฐ๋น 2023์ ํ ์ธ
3. ์ฃผ๋ง ํ ์ธ (๊ธ์์ผ,ํ ์์ผ) : ๋ฉ์ธ ๋ฉ๋ด๋ฅผ ๋ฉ๋ด 1๊ฐ๋น 2023์ ํ ์ธ
4. ํน๋ณ ํ ์ธ : ์ด๋ฒคํธ ๋ฌ๋ ฅ์ ๋ณ์ด ์์ผ๋ฉด ์ด ์ฃผ๋ฌธ ๊ธ์ก์์ 1000์ ํ ์ธ
5. ์ฆ์ ์ด๋ฒคํธ : ํ ์ธ ์ ์ด ์ฃผ๋ฌธ ๊ธ์ก์ด 120,000์์ธ ๊ฒฝ์ฐ โถ๏ธ "์ดํ์ธ 1๊ฐ" ์ฆ์
โก๏ธ ๋ฐฐ์ง
์ด ํํ ๊ธ์ก์ด 5000์ ์ด์ โถ๏ธ "๋ณ" ๋ฐฐ์ง ์ฆ์
์ด ํํ ๊ธ์ก์ด 1๋ง์ ์ด์ โถ๏ธ "ํธ๋ฆฌ" ๋ฐฐ์ง ์ฆ์
์ด ํํ ๊ธ์ก์ด 2๋ง์ ์ด์ โถ๏ธ "์ฐํ" ๋ฐฐ์ง ์ฆ์
โก๏ธ ์ฃผ์ ์ฌํญ
- ์ด ์ฃผ๋ฌธ ๊ธ์ก 10,000์ ์ด์ ๋ถํฐ ์ด๋ฒคํธ๋ฅผ ์ ์ฉํฉ๋๋ค.
- ์๋ฃ๋ง ์ฃผ๋ฌธ ์ ์ฃผ๋ฌธ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.
- ๋ฉ๋ด๋ ํ ๋ฒ์ ์ต๋ 20๊ฐ๊น์ง๋ง ์ฃผ๋ฌธ๊ฐ๋ฅํฉ๋๋ค.
- (e.g. ์์ ์๋ฌ๋-1, ํฐ๋ณธ์คํ ์ดํฌ-1, ํฌ๋ฆฌ์ค๋ง์คํ์คํ-1, ์ ๋ก์ฝ๋ผ-3, ์์ด์คํฌ๋ฆผ-1์ ์ด๊ฐ์๋ 7๊ฐ)
โก๏ธ ์ถ๋ ฅ
- "12์ ์ค ์๋น ์์ ๋ฐฉ๋ฌธ ๋ ์ง๋ ์ธ์ ์ธ๊ฐ์? (์ซ์๋ง ์
๋ ฅํด ์ฃผ์ธ์!)"
- ๋ฐฉ๋ฌธํ ๋ ์ง๋ 1 ์ด์ 31 ์ดํ์ ์ซ์
- 1 ์ด์ 31 ์ดํ์ ์ซ์๊ฐ ์๋ ๊ฒฝ์ฐ, "[ERROR] ์ ํจํ์ง ์์ ๋ ์ง์ ๋๋ค. ๋ค์ ์ ๋ ฅํด ์ฃผ์ธ์."๋ผ๋ ์๋ฌ ๋ฉ์์ง ์ถ๋ ฅ
- "์ฃผ๋ฌธํ์ค ๋ฉ๋ด์ ๊ฐ์๋ฅผ ์๋ ค ์ฃผ์ธ์. (e.g. ํด์ฐ๋ฌผํ์คํ-2,๋ ๋์์ธ-1,์ด์ฝ์ผ์ดํฌ-1)"
- ๋ฉ๋ดํ์ ์๋ ๋ฉ๋ด๋ฅผ ์ ๋ ฅํ๋ ๊ฒฝ์ฐ, "[ERROR] ์ ํจํ์ง ์์ ์ฃผ๋ฌธ์ ๋๋ค. ๋ค์ ์ ๋ ฅํด ์ฃผ์ธ์."๋ผ๋ ์๋ฌ ๋ฉ์์ง ์ถ๋ ฅ
- ๋ฉ๋ด์ ๊ฐ์๋ 1 ์ด์์ ์ซ์๋ง ์ ๋ ฅ๋๋๋ก ํด์ฃผ์ธ์. ์ด์ธ์ ์ ๋ ฅ๊ฐ์ "[ERROR] ์ ํจํ์ง ์์ ์ฃผ๋ฌธ์ ๋๋ค. ๋ค์ ์ ๋ ฅํด ์ฃผ์ธ์."๋ผ๋ ์๋ฌ ๋ฉ์์ง ์ถ๋ ฅ
- ๋ฉ๋ด ํ์์ด ์์์ ๋ค๋ฅธ ๊ฒฝ์ฐ, "[ERROR] ์ ํจํ์ง ์์ ์ฃผ๋ฌธ์ ๋๋ค. ๋ค์ ์ ๋ ฅํด ์ฃผ์ธ์."๋ผ๋ ์๋ฌ ๋ฉ์์ง ์ถ๋ ฅ
- ์ค๋ณต ๋ฉ๋ด๋ฅผ ์ ๋ ฅํ ๊ฒฝ์ฐ(e.g. ์์ ์๋ฌ๋-1,์์ ์๋ฌ๋-1), "[ERROR] ์ ํจํ์ง ์์ ์ฃผ๋ฌธ์ ๋๋ค. ๋ค์ ์ ๋ ฅํด ์ฃผ์ธ์."๋ผ๋์๋ฌ ๋ฉ์์ง ์ถ๋ ฅ
- ์ฃผ๋ฌธ ๋ฉ๋ด ์ถ๋ ฅ
- ์์๋ ์์ ๋กญ๊ฒ ์ถ๋ ฅ ๊ฐ๋ฅ
- ํ ์ธ ์ ์ด ์ฃผ๋ฌธ ๊ธ์ก ์ถ๋ ฅ
- ์ฆ์ ๋ฉ๋ด
- ํ ์ธ ํ ์์ ๊ฒฐ์ ๊ธ์ก(ํ ์ธ ์ ์ด์ฃผ๋ฌธ ๊ธ์ก - ํ ์ธ ๊ธ์ก)์ด 120,000์ ์ด์์ธ ๊ฒฝ์ฐ "์ดํ์ธ 1๊ฐ" ์ถ๋ ฅ
- ์ฆ์ ์ด๋ฒคํธ์ ํด๋นํ์ง ์๋ ๊ฒฝ์ฐ, ์ฆ์ ๋ฉ๋ด "์์"์ผ๋ก ์ถ๋ ฅ
- ํํ ๋ด์ญ
- ์ ์ฉ๋ ์ด๋ฒคํธ ๋ด์ญ’๋ง’ ์ถ๋ ฅ
- ์ ์ฉ๋ ์ด๋ฒคํธ๊ฐ ์๋ค๋ฉด ํํ ๋ด์ญ "์์"์ผ๋ก ์ถ๋ ฅ
- ํํ ๋ด์ญ์ ์ฌ๋ฌ ๊ฐ์ ์ด๋ฒคํธ๊ฐ ์ ์ฉ๋ ๊ฒฝ์ฐ, ์ถ๋ ฅ ์์๋ ์์ ๋กญ๊ฒ ์ถ๋ ฅ๊ฐ๋ฅ
- ์ดํํ ๊ธ์ก(ํ ์ธ ๊ธ์ก์ ํฉ๊ณ + ์ฆ์ ๋ฉ๋ด์ ๊ฐ๊ฒฉ) ์ถ๋ ฅ
- ์ด๋ฒคํธ ๋ฐฐ์ง
- ์ดํํ ๊ธ์ก์ ๋ฐ๋ผ ์ด๋ฒคํธ ๋ฐฐ์ง์ ์ด๋ฆ์ ๋ค๋ฅด๊ฒ ์ถ๋ ฅ
- ์ด๋ฒคํธ ๋ฐฐ์ง๊ฐ ๋ถ์ฌ๋์ง ์๋ ๊ฒฝ์ฐ, "์์"์ผ๋ก ์ถ๋ ฅ
๐ฉ ์ ๋ ฅ๊ฐ ํ์ฑ
๋ฐฉ๋ฌธ ๋ ์ง์ ๋ํ ์ ๋ ฅ์ InputValidtor์์ ์ซ์ ์ ๋ ฅ์ ๋ํ ๊ฒ์ฆ์ ๋ง์น ํ VisitDay๋ผ๋ Value Object(์ด์ ๋ถํฐ ์ค์ฌ VO๋ผ๊ณ ์นญํ๊ฒ ์ต๋๋ค)๋ฅผ ์์ฑํ๋, ์์ฑ์์์ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ์ฐ๊ด๋ ๊ฒ์ฆ์ ์ํํ๊ณ ๊ฒ์ฆ์ ํต๊ณผํ๋ฉด ์ ์์ ์ผ๋ก ์์ฑ์๊ฐ ๋์ํ๊ณ , ํต๊ณผํ์ง ๋ชปํ๋ฉด ์ปค์คํ ํ RuntimeException์ ๋์ง๋๋ก ๊ตฌํํ์์ต๋๋ค.
public VisitDay {
validate(day);
}
private void validate(final Integer day) {
if (!isInMonth(day)) {
throw new InvalidValueOfDayException();
}
}
private boolean isInMonth(final Integer day) {
if (day >= START_DAY_OF_MONTH && day <= END_DAY_OF_MONTH) {
return true;
}
return false;
}
์ฃผ๋ฌธ์ ๋ํ ์ ๋ ฅ์ "์์ ์๋ฌ๋-1, ํฐ๋ณธ์คํ ์ดํฌ-1, ํฌ๋ฆฌ์ค๋ง์คํ์คํ-1, ์ ๋ก์ฝ๋ผ-3, ์์ด์คํฌ๋ฆผ-1"์ ๊ฐ์ด ๊ฐ ๋ฉ๋ด๋ ","๋ก ๋ถ๋ฆฌํ๊ณ ๋ฉ๋ด์ ๋ํ ์๋์ "-"์ผ๋ก ๋ถ๋ฆฌํด์ผ ํฉ๋๋ค.
1. String์ ","์ ๊ธฐ์ ์ผ๋ก ์ฌ๋ผ์ด์ฑ
- ์ฐ์ ","์ ๊ธฐ์ ์ผ๋ก ์ ๋ ฅ๋ฐ์ String์ ์ฌ๋ผ์ด์ฑํํ์ฌ ์ฃผ๋ฌธ์ "๋ฉ๋ด-์๋"์ String ํํ๋ก List Collection์ ์ ์ฅํ์์ต๋๋ค.
2. "-"์ ๊ธฐ์ ์ผ๋ก ์ฌ๋ผ์ด์ฑํ์ฌ Map์ ์ฝ์
- 1๋ฒ ๊ณผ์ ์ ํตํด ์ ์ฅํ List<String>์ streamํ์ฌ "-"์ ๊ธฐ์ ์ผ๋ก ์ฌ๋ผ์ด์ฑํ์ฌ ๊ฐ๊ฐ์ ํ๋๊ฐ์ ํตํด VO๋ฅผ ๋ง๋ค์์ต๋๋ค.
3. VO๋ก ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ค์ Map์ ์ฝ์
2๋ฒ ๊ณผ์ ์ ํตํด ์ฌ๋ผ์ด์ฑํ String ๊ฐ๋ค์ Map์ VO(Food์ Quantity)๋ฅผ ๋ด์์ฃผ์์ต๋๋ค.
- ๋ง๋ค์ด์ง Map์ ์ ๋ณด๋ฅผ ํ ๋๋ก ์ฃผ๋ฌธ ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ์ฌ์ฉํ์์ต๋๋ค.
- Order ํด๋์ค๋ ๋น์ฆ๋์ค์ ์ฐ๊ด์ด ๊น์ ๋ชจ๋ธ๋ก์, ๊ธฐ๋ณธ ์์ฑ์๋ฅผ private์ผ๋ก ๋ง์์ฃผ๊ณ , ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ์ ์ฉํ์๊ณ , ๋ฐฉ๋ฌธ ์ผ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋๋ฉ์ธ ๋ด๋ถ์์ ๋น์ฆ๋์ค์ ์ฐ๊ด๋ ๊ฐ์ ๋ํ ๊ฒ์ฆ์ ์ํํด์ฃผ์์ต๋๋ค.
private Order(final Map<Food, Quantity> foodAndQuantity) {
validate(foodAndQuantity);
this.foodAndQuantity = foodAndQuantity;
}
public static Order create(final Map<Food, Quantity> foodAndQuantity) {
return new Order(foodAndQuantity);
}
private void validate(final Map<Food, Quantity> foodAndQuantity) {
if (isOrderOverMaxQuantity(foodAndQuantity)) {
throw new OverMaxQuantityOrderException();
}
if (isContainOnlyDrink(foodAndQuantity)) {
throw new OnlyDrinkOrderException();
}
}
๐ฉValue Object, record ๊ด๋ฆฌ ๊ธฐ์ค
์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ธ๊ฐ? ------------> Value object๋ก์ record๋ก ๊ด๋ฆฌ
else ------------> class๋ก ๊ด๋ฆฌ
์ ๋ ์์ ๊ฐ์ ๊ธฐ์ค์ ์ ๋๊ณ , VO์ ํํ์ฌ model ํจํค์ง ๋ด๋ถ์ vo ํจํค์ง๋ฅผ ๋๊ณ , record๋ก ๊ด๋ฆฌํ์ฌ ๊ตฌ๋ถํ์์ต๋๋ค.
Value Object๋ฅผ class๋ก ๊ด๋ฆฌํ๋ ๊ฒฝ์ฐ ๋ ํ๋ ๊ฐ์ด ๋์ผํ๋ฉด ๋๋ฑ, ๋์ผํ ๊ฐ์ฒด๋ก ํ๋จํ๋๋ก equals์ hashCode ๋ฉ์๋๋ฅผ ๋ณ๋๋ก ์์ฑํ์ฌ์ผ ํฉ๋๋ค. Value Object๋ก ๊ด๋ฆฌํ๋, ๋๋ ๋จ์ ์์๊ฐ์ ํฌ์ฅํ class๋ก ๊ด๋ฆฌํ๋, ์ด ๊ธฐ์ค์ ์ ์ด๋ป๊ฒ ๋์ด์ผ ํ ์ง ๊ณ ๋ฏผ์ด ๋ง์๋๋ฐ, ์ ๋ ํ์๊ฐ์ ์ ํ ๋ ์ค๋ณต ์์ด๋๋ฅผ ๊ฒ์ฌํ๊ฑฐ๋ ๋๋ ์์ ๊ฐ์ด ํ์ ์ ๋ณด๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ ๊ฒฝ์ฐ ๊ฐ์ record๋ก ๊ด๋ฆฌํ๋ฉด, ์ค๋ณต ๊ฒ์ฌ ๋ณ๋์ ๊ฒ์ฌ ๋ก์ง์ ๊ตฌํํ์ง ์์๋ ํ๋๊ฐ์ ๋ํด equals()์ hashCode()๊ฐ ์๋์ผ๋ก ์ ์ฉ๋๊ธฐ ๋๋ฌธ์ ์ด Value Object๋ฅผ record๋ก ๊ด๋ฆฌํจ์ผ๋ก์จ ์ฝ๋์ ๋ณต์ก๋๋ฅผ ๋ฎ์ถ ์ ์๊ธฐ ๋๋ฌธ์ ๊ฒฐ๋ก ์ ์ผ๋ก ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ ํํด์ record๋ก ๊ด๋ฆฌํ๋๋ก ๊ตฌํํ์์ต๋๋ค.
๋ฏธ์ ๊ณผ ์ฐ๊ด๋ Food record๋ฅผ ์๋ก ๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
Order ํด๋์ค๊ฐ ๊ฐ์ง๋ Map ํ๋์๋ ์์์ ์ด๋ฆ์ ๋ํ ํ๋๊ฐ์ ํฌ์ฅํ Food record์ ์๋์ ๋ํ ํ๋๊ฐ์ ํฌ์ฅํ Quantity๊ฐ ๋ด๊น๋๋ค. ํ์ง๋ง ์ฃผ๋ฌธ์๋ ์ค๋ณต๋ Food์ name์ ๊ฐ์ง ์ ์๋ค๋ ์๊ตฌ์ฌํญ์ด ์์ต๋๋ค.
eg) ํด์ฐ๋ฌผํ์คํ-1, ํด์ฐ๋ฌผํ์คํ-2 โถ๏ธ should throw RuntimeException
public class Food {
private final String name;
public Food(String name) {
validate(name);
this.name = name;
}
private void validate(final String name) {
if (!isContainInMenu(name)) {
throw new OrderNotInMenuException();
}
}
private boolean isContainInMenu(final String name) {
return Arrays.stream(Menu.values())
.anyMatch(menu -> menu.getSalesMenu().containsKey(name));
}
public boolean isDrink() {
return DRINK.getSalesMenu()
.containsKey(name);
}
public String getName() {
return name;
}
}
- ๋ง์ฝ Food record๋ฅผ ์์ ๊ฐ์ด ๋จ์ํ๊ฒ "์์์ ์ด๋ฆ"์ ์์๊ฐ์ ํฌ์ฅํ class๋ก ๊ด๋ฆฌํ๋ ๊ฒฝ์ฐ, equals์ hashCode๋ฉ์๋๋ฅผ ๋ณ๋๋ก ๊ตฌํํ์ง ์์ผ๋ฉด ์ค๋ณต๋ ์ด๋ฆ์ ๋ํด ๊ฒ์ฌํ๋ ์๋์ ์ฝ๋๊ฐ ์๋๋๋ก ๋์ํ์ง ์์ต๋๋ค.
private static Map<Food, Quantity> splitAndMapping(final List<String> menuItems) {
return menuItems.stream()
.map(item -> item.split(QUANTITY_DELIMITER))
.collect(Collectors.toMap(
foodAndQuantity -> getFood(Arrays.asList(foodAndQuantity)),
foodAndQuantity -> getQuantity(Arrays.asList(foodAndQuantity)),
(existing, replacement) -> {
throw new AlreadyExistsInOrderException();
}
));
}
- ๊ฐ์ด ๋์ผํ ๊ฒฝ์ฐ์๋ ๋์ผ, ๋๋ฑํ ๊ฐ์ฒด๋ก ํ๋จํ์ง ์๊ธฐ ๋๋ฌธ์ toMap์ mergeFunction์์ ์์ธ๊ฐ ์ ์์ ์ผ๋ก ๋ฐ์ํ์ง ์์ต๋๋ค.
public record Food(String name) {
public Food {
validate(name);
}
private void validate(final String name) {
if (!isContainInMenu(name)) {
throw new OrderNotInMenuException();
}
}
private boolean isContainInMenu(final String name) {
return Arrays.stream(Menu.values())
.anyMatch(menu -> menu.getSalesMenu().containsKey(name));
}
public boolean isDrink() {
return DRINK.getSalesMenu()
.containsKey(name);
}
}
- record๋ ์์๊ฐ์ ํฌ์ฅํ ๋ฟ๋ง ์๋๋ผ ๋ ์ฝ๋์ ๋์ผํ ํ๋๊ฐ์ ๋ํ ๋๋ฑ์ฑ, ๋์ผ์ฑ๊น์ง ๋ณด์ฅํด์ฃผ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ record๋ก ๊ด๋ฆฌํ๋ค๋ฉด, ์ด๋ฐ ๋ถ๋ถ๋ค์ ์ ๊ฒฝ์ฐ์ง ์์๋ ๋๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค..
ํจํค์ง๋ model ํจํค์ง ์ธ๋ถ์ ๋ณ๋์ vo ํจํค์ง๋ฅผ ๋์ด ๊ด๋ฆฌํ์๋, ๊ฐ ๊ฐ์ฒด ๋ํ ๋น์ฆ๋์ค์ ์ฐ๊ด์ฑ์ด ์๋ค๊ณ ํ๋จํด์ model ํจํค์ง ๋ด๋ถ์ vo ํจํค์ง๋ฅผ ๋์์ต๋๋ค.
๐ฉ enum ํ์ฉ
โก๏ธ enum ์์
์ง๋ ๋ฏธ์ enum์ ์ ์ฉํด๋ณธ ๊ฒฝํ์ด ์ด๋ฒ ๋ฏธ์ ์์ ์๋์ ์ผ๋ก ์ฝ๊ฒ ์ ์ฉํ๋๋ก ๋์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ง๋ ๋ฏธ์ ์์ ๋ฐ์ ํ ์ ์ด ์๋ค๋ฉด ์ง๋ ๋ฏธ์ ์์๋ ์ฐ๊ด์ฑ๋ณด๋ค๋ Type์ ๊ธฐ์ค์ผ๋ก enum์ผ๋ก ๋๋์ด ๊ด๋ฆฌํ๋ค๋ฉด, ์ด๋ฒ์๋ ์์๋ผ๋ฆฌ ์ฐ๊ด์ฑ์ด ์๋ ๊ฒฝ์ฐ์ ํํด์๋ง enum์ผ๋ก ๊ด๋ฆฌํ๋ค๋ ์ ์ ๋๋ค!
- 3์ฃผ์ฐจ ๋ฏธ์ ์์๋ ์ ์ผ์ชฝ ์ฝ๋์ ๊ฐ์ด ์ฐ๊ด์ฑ์ด ์์์๋ ๋ถ๊ตฌํ๊ณ ๊ฐ์ Integer Type์ด๋ผ๋ ์ด์ ํ๋๋ง์ผ๋ก LottoInfo enum์ผ๋ก ํ์ณ์ ๊ด๋ฆฌํ๋๋ฐ ์ด์ ๋์๋ณด๋ ์ด๋ ๊ฒ ๊ด๋ฆฌํ๊ฒ๋๋ฉด, ๋์ค์ ์ค๊ตฌ๋๋ฐฉ์ด ๋ ์ฐ๋ ค๊ฐ ์์์ต๋๋ค.
- 4์ฃผ์ฐจ์์๋ ์ ์ค๋ฅธ์ชฝ ์ฝ๋์ ๊ฐ์ด 'ํ ์ธ ๊ธ์ก์ ๋ํ ์ ๋ณด'๋ผ๋ ์ฐ๊ด์ฑ์ ๊ฐ์ง๋ ์์๋ค์ DiscountInfo๋ก ๋ฌถ์ด enum์ผ๋ก ๊ด๋ฆฌํ๊ณ , ์๋ ์ฝ๋์ ๊ฐ์ด ์ ๋ฌผ๊ณผ ๋ฐฐ์ง์ ๋ํ ์์๋ ์๋ก ์ฐ๊ด๋ ์ ๋ณด๋ฅผ ์ฌ๋ฌ ํ๋๋ก ๋ฌถ์ด ๊ด๋ฆฌํ์ต๋๋ค!
public enum GiftInfo {
ONE_CHAMPAGNE("์ดํ์ธ 1๊ฐ", 120000, 25000),
NONE_GIFT("์์", 0, 0);
private final String giftName;
private final Integer requiredAmount;
private final Integer giftAmount;
public enum BadgeInfo {
SANTA_BADGE("์ฐํ", 20000),
TREE_BADGE("ํธ๋ฆฌ", 10000),
STAR_BADGE("๋ณ", 5000),
NONE_BADGE("์์", 0);
private final String badgeName;
private final Integer requiredAmount;
- ๋ฉ๋ด๋ ๊ฐ ๋ฉ๋ด์ ์นดํ ๊ณ ๋ฆฌ์ ํจ๊ป ๊ฐ ๋ฉ๋ด์ ์ด๋ฆ๊ณผ ๊ฐ๊ฒฉ์ Map์ ํตํด ๊ด๋ฆฌํ๋๋ก ์ค์ ํ์ต๋๋ค!
public enum Menu {
APPETIZER(Map.of("์์ก์ด์ํ", 6000,
"ํํ์ค", 5500,
"์์ ์๋ฌ๋", 8000)),
MAIN(Map.of(
"ํฐ๋ณธ์คํ
์ดํฌ", 55000,
"๋ฐ๋นํ๋ฆฝ", 54000,
"ํด์ฐ๋ฌผํ์คํ", 35000,
"ํฌ๋ฆฌ์ค๋ง์คํ์คํ", 25000)),
DESSERT(Map.of(
"์ด์ฝ์ผ์ดํฌ", 15000,
"์์ด์คํฌ๋ฆผ", 5000)),
DRINK(Map.of(
"์ ๋ก์ฝ๋ผ", 3000,
"๋ ๋์์ธ", 60000,
"์ดํ์ธ", 25000));
๊ทธ ์ธ ์ฐ๊ด์ฑ์ด ์๊ณ , ํด๋์ค์์๋ง ์ฌ์ฉํ๋ ๋งค์ง๋๋ฒ๋ค์ static final ์์๋ก ๊ด๋ฆฌํ์์ต๋๋ค.
โก๏ธ enumMap
public class Discount {
private static final Integer NO_QUANTITY = 0;
private static final Integer NO_DISCOUNT_AMOUNT = 0;
private static final Integer PRESENT_YEAR = 2023;
private final Map<DiscountPolicy, DiscountAmount> discountDetails;
์ฌ์ฉ์์ ์ฃผ๋ฌธ์ ์ํด ์์ฑ๋ ํ ์ธ ์ ๋ณด๋ฅผ ๊ฐ๋ Discount ํด๋์ค์ ํ๋๋ฅผ ์๋์ ๊ฐ์ด DiscountPolicy๋ผ๋ enum์ ๋๊ณ ๊ฐ ํ ์ธ ๊ธ์ก์ ์์๊ฐ์ ํฌ์ฅํ DiscountAmount์ ํจ๊ป Map์ผ๋ก ๊ด๋ฆฌํ๋๋ก ๊ตฌํํ์์ต๋๋ค!
public enum DiscountPolicy {
WEEKDAY_DISCOUNT("ํ์ผ ํ ์ธ"),
WEEKEND_DISCOUNT("์ฃผ๋ง ํ ์ธ"),
D_DAY_DISCOUNT("ํฌ๋ฆฌ์ค๋ง์ค ๋๋ฐ์ด ํ ์ธ"),
GIFT_DISCOUNT("์ฆ์ ์ด๋ฒคํธ"),
SPECIAL_DISCOUNT("ํน๋ณ ํ ์ธ");
๐ฉ๊ฐ์ฅ ๊ณ ๋ฏผํ๋ ์ : ํ ์ธ์ ์ฑ ๋ถ๋ฆฌ
ํ ์ธ ํด๋์ค์ ๊ฐ ํ ์ธ ์ ์ฑ ์ ๋ถ๋ฆฌํ์ฌ ๊ด๋ฆฌํด์ผ ํ ์ง ๊ณ ๋ฏผ์ด ๋ง์์ต๋๋ค. ๋ถ๋ฆฌ๋ฅผ ๊ฐ์ฅ ๊ณ ๋ฏผํ๋ ์ด์ ๋ ํ ์ธ ๊ฐ์ฒด ์์ฑ์ ๋ฉ์๋๋ฅผ ๋ณด๋ฉด ์ฝ๋๊ฐ ์๋นํ ๊ธธ ๋ฟ๋ง ์๋๋ผ ๋งค๊ฐ๋ณ์๋ฅผ ๋ง์ด ๊ฐ์ง๊ณ ์์ด ํ ์คํธ๊ฐ ์ด๋ ค์์ง๊ณ , ๋ณ๊ฒฝ์ด ์ด๋ ค์์ง๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ๊ณ ์๊ธฐ ๋๋ฌธ์ด์์ต๋๋ค. ๊ฒฐ๋ก ์ ์ผ๋ก๋ ๋ถ๋ฆฌ๋ฅผ ์ ํํ์ง ์์์ต๋๋ค. ๊ทธ ์ด์ ๋
์ฒซ ๋ฒ์งธ, ํ์ฅ์ฑ์ ์๊ฐํ์ง ์๊ธฐ๋ก ํ ๋ชฉํ๋ฅผ ๊ณ ๋ คํด ์ฝ๋๋ฅผ ๋ณด์์ ๋, ๋ฌธ์ ๋ ๊ฒ์ด ์๋ค๊ณ ํ๋จํ์ต๋๋ค.
- ํ์ฌ ์๊ตฌ์ฌํญ์ผ๋ก๋ ํ ์ธ ์ ์ฑ ์ด ์ฃผ๋ง, ํ์ผ, ๋๋ฐ์ด, ์คํ์ ๋ฐ์ด, ์ฆ์ ์ด๋ฒคํธ ํ ์ธ ์ด 5๊ฐ์ง์ ํ ์ธ์ ์ฑ ์ด ์์ต๋๋ค.
- ์ถ๊ฐ์ ์ธ ํ ์ธ ์ ์ฑ ์ด ์๊ตฌ๋๋ ์์ ์ด๋, ํ ์ธ ์ ์ฑ ์ ๋ํ ์์ ์ด ๋น๋ฒํ๊ฒ ์ด๋ค์ง๋ ๊ฒฝ์ฐ์ ๊ด๋ฆฌ๋ฅผ ํธํ๊ฒ ํ๊ธฐ ์ํด ํด๋์ค ๋ถ๋ฆฌ๋ฅผ ์๋ํ๋ ๊ฒ์ด ์ฐจ๋ผ๋ฆฌ ๋ ์ข์ ์ ํ์ด๋ผ๊ณ ์๊ฐํ์ต๋๋ค.
๋ ๋ฒ์งธ, ๋ถ๋ฆฌ๋ฅผ ํ ๊ฒฝ์ฐ ๋ถํ์ํ ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ๋ค.
- ํ์ฌ Discount ํด๋์ค๋ "ํ ์ธ ์ ๋ณด๋ฅผ ์์ฑํ์ฌ ํ๋๋ก ๊ฐ์ง๋ ๊ธฐ๋ฅ, ์์ ์ ํ๋๊ฐ์ ํ ๋๋ก ํ ์ธ์ ์ด ๊ธ์ก์ ๊ณ์ฐํ์ฌ ๋ฉ์์ง๋ฅผ ๋ฆฌํดํ๋ ๊ธฐ๋ฅ, ์ฆ์ ์ด๋ฒคํธ์ ํ ์ธ ๊ธ์ก์ ๋ํ ๋ฉ์์ง๋ฅผ ๋ฆฌํดํ๋ ๊ธฐ๋ฅ"์ ๊ฐ์ง๋๋ค. Discount ํด๋์ค๊ฐ ์์ฑ์๋ฅผ ํตํ ๊ธฐ๋ฅ์ ์ ์ธํ๊ณ ๋ ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ๊ตณ์ด ๋ถ๋ฆฌ๋ฅผ ํ ํ์๊ฐ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค.
- ๋ง์ฝ Discount ํด๋์ค๊ฐ ์ด ๋ ๊ฐ์ง์ ๊ธฐ๋ฅ ์ธ์ ๋ค๋ฅธ ๊ธฐ๋ฅ๋ค๊น์ง ์ถ๊ฐ๋์ด์ผ ํ๋ ์์ ์์๋ ํ ์ธ ์ ์ฑ ๋ค์ ๋ถ๋ฆฌํจ์ผ๋ก์จ ๋ณต์ก์ฑ์ ๋ฎ์ถ๋ ๊ฒ์ ๊ณ ๋ คํด๋ณด์๊ฒ ์ง๋ง, ํ์ฌ๋ก์๋ ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ด private ๋ฉ์๋๋ฅด ๊ฐ์ง๋ค๊ฑฐ๋, ์ฝ๊ธฐ ์ด๋ ค์ด ์ฝ๋๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ํ ์ธ ์ ์ฑ ๋ค์ ๋น์ฅ ๋ถ๋ฆฌํด์ผ ํ ์ด์ ๊ฐ ์๋ค๊ณ ํ๋จ
public static Discount create(final Integer orderAmount, final Integer mainQuantity, final Integer dessertQuantity,
final VisitDay visitDay, final boolean isGiftReceived) {
Map<DiscountPolicy, DiscountAmount> discountDetails = new HashMap<>();
if (orderAmount < EVENT_ATTEND_MINIMUM_ORDER_AMOUNT.getAmount()) {
return new Discount(discountDetails);
}
putWeekDayDiscount(dessertQuantity, visitDay, discountDetails);
putWeekendDayDiscount(mainQuantity, visitDay, discountDetails);
putD_DayDiscount(visitDay, discountDetails);
putSpecialDayDiscount(visitDay, discountDetails);
putGiftDiscount(isGiftReceived, discountDetails);
return new Discount(discountDetails);
}
๐ฉ Review : ๊ฐ์ ํด์ผ ํ ์ ๋ค
โก๏ธ View๋ก ๊ฒ์ฆ ๋ก์ง ์ฎ๊ธฐ๊ธฐ
- ํ์ฌ Controller์์ discountDetails์ ์ ๋ณด๋ฅผ ํ๋จํ๊ณ , ํ๋จ์ ๋์ํ๋ ์ถ๋ ฅ๋ทฐ์ ๋ฉ์๋๋ฅผ ์คํํ๋๋ก ์์ฑ๋์ด ์๋๋ฐ, ์ด ๋ณด๋ค๋ ๋ทฐ์์ ์ ๋ณด๋ฅผ ํ๋จํ์ฌ ๋์ํ๋ ๋ฉ์๋๋ฅผ ์คํํ๋๋ก ์์ฑํ๋ ๊ฒ์ด ๋ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
private void showDiscountDetails(final Map<DiscountPolicy, DiscountAmount> discountDetails) {
outputView.printBenefitHeader();
if (discountDetails.isEmpty()) {
outputView.printNone();
outputView.printLine();
return;
}
discountDetails.forEach(
(policy, amount) -> outputView.printBenefit(policy.getPolicy(), amount.getAmount()));
outputView.printLine();
}
โก๏ธ ์ค๋ณต ๋ก์ง ์ ๊ฑฐ
public Integer getDessertQuantity() {
return foodAndQuantity.entrySet()
.stream()
.filter(order -> DESSERT.getSalesMenu().containsKey(order.getKey().name()))
.mapToInt(order -> order.getValue().amount())
.sum();
}
public Integer getMainQuantity() {
return foodAndQuantity.entrySet()
.stream()
.filter(order -> MAIN.getSalesMenu().containsKey(order.getKey().name()))
.mapToInt(order -> order.getValue().amount())
.sum();
}
- Orderํด๋์ค์์ ๋ฉ์ธ ๋ฉ๋ด ์ฃผ๋ฌธ๋๊ณผ, ๋์ ํธ ๋ฉ๋ด ์ฃผ๋ฌธ๋์ ๋ฆฌํดํ๋ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์๋๋ฐ, ์ฝ๋์ ์ค๋ณต๋๋ ๋ถ๋ถ๋ค์ด ์๊ธฐ ๋๋ฌธ์ ์ด ๋ ๋ฉ์๋๋ฅผ ์๋์ ๊ฐ์ด ํ๋์ ๋ฉ์๋๋ก ๋ณ๊ฒฝํ๋ค๋ฉด ๋ ์ข์ ์ฝ๋๊ฐ ๋ ๊ฒ ๊ฐ์ต๋๋ค.
public Integer getFoodQuantity(Menu menu) {
return foodAndQuantity.entrySet()
.stream()
.filter(order -> menu.getSalesMenu().containsKey(order.getKey().name()))
.mapToInt(order -> order.getValue().amount())
.sum();
}
โก๏ธ ๋ค์ด๋ฐ ๋ณ๊ฒฝ
public Integer getAmount() {
return foodAndQuantity.keySet().stream()
.mapToInt(food -> Menu.getPriceOfFood(food) * foodAndQuantity.get(food).amount())
.sum();
}
- Order ํด๋์ค์์ ์ด ์ฃผ๋ฌธ ๊ธ์ก์ ๋ฆฌํดํ๋ ๊ธฐ๋ฅ์ธ๋ฐ, getAmount๋ผ๋ ๋ค์ด๋ฐ์ ์ด ์ฃผ๋ฌธ ๊ธ์ก์ ์ค๋ช ํ๊ธฐ์ ๋ถ์กฑํ๋ค๊ณ ๋๊ปด์ง๋๋ฐ, getAmount๋ณด๋ค๋ getTotalAmount๋ getTotalOrderAmount์ ๊ฐ์ ๋ฉ์๋๋ช ์ด ๋ ์ด ๊ธฐ๋ฅ์ ์ ๋ํ๋ด๋ ์ด๋ฆ์ด๋ผ๊ณ ์๊ฐ๋ฉ๋๋ค.
๐ฉํ๋ฆฌ์ฝ์ค ์ดํ / ์์ผ๋ก์ ๊ณํ
ํ ๋ฌ ๋์์ ํ๋ฆฌ์ฝ์ค๋ ๊ธฐ๋ ์ด์์ผ๋ก ๋ง์ ๊ฒ์ ๋ฐฐ์ธ ์ ์์๊ณ , ์ฃผ์ฐจ๊ฐ ์งํ๋จ์ ๋ฐ๋ผ ๋ฐฐ์ด ์ง์์ด ์ฒดํ๋๋ ๊ณผ์ ์ ๊ฒฝํํ๊ฒ ๋์ด ๋งค์ฐ ์ ์ตํ ์๊ฐ์ด์์ต๋๋ค. ์ง๋ ํ ๋ฌ์ ๋์๋ณด๋ฉด ์ด๋ ค์ด ์๊ฐ๋ ์์์ง๋ง, ๋ถ๋ช ๋ด๊ฐ ์ข์ํ๋ ๋ถ์ผ์์ ๋ชจ๋ฅด๊ณ ์๋ ๊ฒ๋ค์ ๋ฐฐ์ฐ๊ณ ๋ ๋ง์ด ์๊ฒ ๋๋ ๊ณผ์ ์์ฒด๊ฐ ์ฆ๊ฑฐ์ ๋ ๋์ ์ด๋ฌํ ๋๊ธฐ๋ถ์ฌ๋ก ํ๋ฆฌ์ฝ์ค์ ๋์ฑ ๋ชฐ๋ํ ์ ์์๋ ๊ฒ ๊ฐ์ต๋๋ค. ํ๋ฆฌ์ฝ์ค๋ฅผ ํตํด ์ป์ ์ง์๊ณผ ์ฒดํ๋ ๊ฐ๋ฐ ์ต๊ด๋ค์ ์์ผ๋ก์ ๊ฐ๋ฐ ๊ฒฝ๋ ฅ์์ ํฐ ๋์์ด ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ข์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ง ๋ชปํ๋ค ํด๋, ๋ฏธ์ ์ ๋ํด ์ฌ๊ณ ํ๊ณ ๊ณ ๋ฏผํ๋ฉฐ ํด๊ฒฐํ๋ ๊ณผ์ ์์ ๋ฐฐ์ด ๊ฒ๋ค์ ์์คํ ๊ฒฝํ์ด์์ต๋๋ค.. ์์ผ๋ก ์ฝ ํ ๋ฌ๊ฐ์ ์๊ฐ ๋์์ ํ๋ฆฌ์ฝ์ค์์ ๋ฐฐ์ด ๋ด์ฉ์ ํ์คํ ์ฒดํํ๊ธฐ ์ํด ๊ฐ์ฒด์งํฅ๊ณผ ๊ด๋ จ๋ ๋์๋ฅผ ์ฝ๊ณ , ๋ฏธ์ ์ ๋ค์ ํ์ด๋ณด๊ณ ๋ฆฌํฉํ ๋งํ๋ฉฐ ์ค๋ ฅ์ ํฅ์์ํฌ ๊ณํ์ ๋๋ค. ํนํ, ๊ธฐ๋ฅ ๊ตฌํ ์๋๋ฅผ ํฅ์์ํค๊ธฐ ์ํด ์ง๋ ๊ธฐ์๋ค์ ์ต์ข ์ฝ๋ฉ ํ ์คํธ ๋ฌธ์ ๋ค์ ์๊ฐ์ ์ธก์ ํ์ฌ ํ์ด๋ณด๊ณ ์ฐ์ตํ ์์ ์ ๋๋ค. ์ข์ ๊ฒฐ๊ณผ๋ก ๋ค์ ํ๊ธฐ๋ฅผ ์ด์ด์ ์ผ์ผ๋ฉด ์ข๊ฒ ๋ค์.
๋ฏธ์ ์ ๊ดํ ์ ์ฝ๋๋ ์๋ ๋งํฌ์์ ํ์ธํ์ค ์ ์์ต๋๋ค..
'๐ Etc > Rev' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DND] 10๊ธฐ ํฉ๊ฒฉ ํ๊ธฐ (2) | 2023.12.29 |
---|---|
[์ฐ์ํํ ํฌ์ฝ์ค 6๊ธฐ] ํ๋ฆฌ์ฝ์ค ๋ถํฉ๊ฒฉ (0) | 2023.12.29 |
[์ฐ์ํํ ํฌ์ฝ์ค 6๊ธฐ] ํ๋ฆฌ์ฝ์ค 3์ฃผ์ฐจ ๋ก๋ ๋ฏธ์ ํ๊ธฐ (1) | 2023.11.15 |
[์ฐ์ํํ ํฌ์ฝ์ค 6๊ธฐ] ํ๋ฆฌ์ฝ์ค 2์ฃผ์ฐจ ์๋์ฐจ ๊ฒฝ์ฃผ ๋ฏธ์ ํ๊ธฐ (3) | 2023.11.02 |
[์ฐ์ํํ ํฌ์ฝ์ค 6๊ธฐ] ํ๋ฆฌ์ฝ์ค 1์ฃผ์ฐจ ์ซ์์ผ๊ตฌ ๋ฏธ์ ํ๊ธฐ (2) | 2023.10.20 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422