DevLog ๐Ÿ˜ถ

[Spring] ์ˆœ์ˆ˜ ์ž๋ฐ”๋กœ ํšŒ์›-์ฃผ๋ฌธ ์„œ๋น„์Šค ๊ฐœ๋ฐœํ•˜๊ธฐ ๋ณธ๋ฌธ

Back-end/Spring

[Spring] ์ˆœ์ˆ˜ ์ž๋ฐ”๋กœ ํšŒ์›-์ฃผ๋ฌธ ์„œ๋น„์Šค ๊ฐœ๋ฐœํ•˜๊ธฐ

dolmeng2 2022. 8. 6. 19:27

- ๊น€์˜ํ•œ ๋‹˜์˜ '์Šคํ”„๋ง ํ•ต์‹ฌ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ'์„ ๋ณด๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค ๐Ÿ˜Š

 

์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

์Šคํ”„๋ง ์ž…๋ฌธ์ž๊ฐ€ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋ฉด์„œ ์Šคํ”„๋ง์˜ ํ•ต์‹ฌ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ , ์Šคํ”„๋ง ๊ธฐ๋ณธ๊ธฐ๋ฅผ ํ™•์‹คํžˆ ๋‹ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., - ๊ฐ•์˜ ์†Œ๊ฐœ | ์ธํ”„๋Ÿฐ...

www.inflearn.com


| ๊ธฐ๋ณธ ์„ค๊ณ„

<ํšŒ์› ๋„๋ฉ”์ธ>

- ๊ธฐ๋ณธ์ ์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค-ํด๋ž˜์Šค ํ˜•ํƒœ๋กœ ์„ค๊ณ„ํ•˜๊ธฐ.

    - ๋ฌผ๋ก , ์‹ค๋ฌด์—์„œ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฐ”๋กœ ํด๋ž˜์Šค๋กœ ๋“ค์–ด๊ฐ€๋„ ์ข‹๋‹ค. ์ง€๊ธˆ์€ ์—ฐ์Šต์ด๋‹ˆ๊นŒ!

- ํšŒ์›์€ id, ์ด๋ฆ„, ๋“ฑ๊ธ‰ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

    - ์ด๋•Œ, ๋“ฑ๊ธ‰ ์ •๋ณด๋Š” BASIC / VIP ์œ ์ €๋กœ ๋‚˜๋ˆ„์–ด์ ธ ์žˆ๋‹ค.

- ํšŒ์› ์„œ๋น„์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

    - ํšŒ์›๊ฐ€์ž…

    - ํšŒ์› ์กฐํšŒ

- ํšŒ์› ์ €์žฅ์†Œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ €์žฅ์†Œ, DB ์ €์žฅ์†Œ, ์™ธ๋ถ€ ์‹œ์Šคํ…œ ์—ฐ๋™ ์ €์žฅ์†Œ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์„ค๊ณ„ํ•œ๋‹ค.


 

- Spring ๋‚ด๋ถ€์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ณ„๋‹ค๋ฅธ dependency ์ถ”๊ฐ€๋Š” ์ง„ํ–‰ํ•˜์ง€ ์•Š์•˜๋‹ค.

 

| Member

โœ” Domain

[Member.java]


  
public class Member {
private Long id;
private String name;
private Grade grade;
public Member(Long id, String name, Grade grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
}

- ์ฝ”๋“œ ๊ธธ์ด์ƒ getter / setter๋Š” ์ƒ๋žตํ•˜์˜€๋‹ค.

 

[Grade.java]


  
public enum Grade {
BASIC, VIP
}

 

โœ” Repository

[MemberRepository.java]


  
public interface MemberRepository {
void save(Member member);
Member findById(Long memberId);
}

[MemoryMemberRepository.java]


  
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new ConcurrentHashMap<>();
@Override
public void save(Member member) {
store.put(member.getId(), member);
}
@Override
public Member findById(Long memberId) {
return store.get(memberId);
}
}

- ๋™์‹œ์„ฑ ์ด์Šˆ ๋•Œ๋ฌธ์— ConcurrentHashMap์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค. 

 

 

โœ” Service

[MemberService.java]


  
public interface MemberService {
void join(Member member);
Member findMember(Long memberId);
}

[MemberServiceImpl.java]


  
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository = new MemoryMemberRepository();
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}

 

 

โœ” Test

[MemberServiceTest.java]


  
class MemberServiceTest {
MemberService memberService = new MemberServiceImpl();
@Test
public void join() throws Exception {
// given
Member member = new Member(1L, "hello", Grade.BASIC);
// when
memberService.join(member);
// then
Member findMember = memberService.findMember(1L);
Assertions.assertThat(findMember).isEqualTo(member);
}
}

- ํ…Œ์ŠคํŠธ๋Š” ์ž˜ ํ†ต๊ณผํ•œ๋‹ค. 

- ๊ทธ๋Ÿฌ๋‚˜, ๊ธฐ๋ณธ์ ์œผ๋กœ MemberService๋ฅผ ์„ ์–ธํ•  ๋•Œ MemberServiceImpl() ์ด๋ผ๋Š” ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค.

- ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๊ตฌ์ฒด์ ์ธ ๊ฒƒ์— ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์— DIP ์œ„๋ฐ˜, ์ดํ›„ ์„œ๋น„์Šค ์ •์ฑ…์„ ๋ณ€๊ฒฝํ•  ๋•Œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— OCP๊นŒ์ง€ ์œ„๋ฐ˜ํ•˜๊ฒŒ ๋œ๋‹ค.

 

- ์šฐ์„ , ์œ„ ๋ฌธ์ œ๋ฅผ ๊ธฐ์–ตํ•ด๋‘๊ณ  ์ฃผ๋ฌธ์— ๋Œ€ํ•œ ๋„๋ฉ”์ธ์„ ์„ค๊ณ„ํ•ด๋ณด์ž.


- ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์—ญํ• ๊ณผ ๊ตฌํ˜„์„ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด, ์ธํ„ฐํŽ˜์ด์Šค-ํด๋ž˜์Šค ํ˜•ํƒœ๋กœ ์„ค๊ณ„ํ•œ๋‹ค.

- ์ฃผ๋ฌธ์€ ํšŒ์› ID, ์ƒํ’ˆ๋ช…, ์ƒํ’ˆ ๊ฐ€๊ฒฉ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

    - ์—ฌ๊ธฐ์—, ์ถ”๊ฐ€์ ์œผ๋กœ ํ• ์ธ๋œ ๊ฐ€๊ฒฉ์„ ๋ฆฌํ„ดํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•  ์˜ˆ์ •์ด๋‹ค.

- ์ฃผ๋ฌธ ์„œ๋น„์Šค๋Š” ํšŒ์›์„ ์กฐํšŒํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ง€๋ถˆํ•  ๊ฐ€๊ฒฉ์„ ๊ณ„์‚ฐํ•œ๋‹ค. VIP๋Š” ํ• ์ธ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

    - ์ด๋•Œ, ํ• ์ธ ์ •์ฑ…์€ ์ •์•ก ํ• ์ธ ์ •์ฑ… (1000์›), ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์œผ๋กœ ๋‚˜๋‰œ๋‹ค.


 

| Discount

[DiscountPolicy.java]


  
public interface DiscountPolicy {
int discount(Member member, int price);
}

[FixDiscountPolicy.java]


  
public class FixDiscountPolicy implements DiscountPolicy{
private int fixDiscountPrice = 1000;
// 1000์›์„ ๊ณ ์ •์œผ๋กœ ํ• ์ธํ•ด์ฃผ๊ธฐ
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP) {
return fixDiscountPrice;
}
else {
return 0;
}
}
}

- ๋จผ์ € ์ •์•ก ํ• ์ธ ์ •์ฑ…์„ ๊ตฌํ˜„ํ•˜์˜€๋‹ค. ํ• ์ธ ๊ธˆ์•ก์€ 1000์›์ด๋‹ค.

 

 

| Order

โœ” Domain

[Order.java]


  
public class Order {
private Long memberId;
private String itemName;
private int itemPrice;
private int discountPrice;
public int realPrice() {
return itemPrice - discountPrice;
}
}

- ์ฝ”๋“œ์—์„œ๋Š” ์ƒ๋žตํ–ˆ์ง€๋งŒ, Getter/Setter, ๊ทธ๋ฆฌ๊ณ  toString์„ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.

- ์‹ค์ œ ์‚ฌ์šฉ์ž๊ฐ€ ์ง€๋ถˆํ•  ๊ฐ€๊ฒฉ์„ ๋ฆฌํ„ดํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ realPrice()๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

 

 

โœ” Service

[OrderService.java]


  
public interface OrderService {
Order createOrder(Long memberId, String itemName, int itemPrice);
}

[OrderServiceImpl.java]


  
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository
= new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member findMember = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(findMember, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}

๐ŸŽˆ ์—ฌ๊ธฐ์„œ DiscountPolicy๋ฅผ ์ฃผ์ž…ํ•˜๋Š” ๋ถ€๋ถ„์„ ์ž˜ ๋ณด์ž. ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค. (๋’ค์—์„œ ์„ค๋ช…ํ•  ์˜ˆ์ •)

- id๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํšŒ์›์„ ์ฐพ์•„์„œ, ํšŒ์›์— ๋”ฐ๋ฅธ ํ• ์ธ ๊ฐ€๊ฒฉ์„ ๋ฆฌํ„ด๋ฐ›๋Š”๋‹ค.

- ํ•ด๋‹น ํ• ์ธ๊ฐ€๊ฒฉ์ด ์ ์šฉ๋œ ์ƒˆ๋กœ์šด ์ฃผ๋ฌธ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

 

โœ” Test


  
class OrderServiceTest {
MemberService memberService = new MemberServiceImpl();
OrderService orderService = new OrderServiceImpl();
@Test
public void createOrder() throws Exception {
// given
Member member = new Member(1L, "hello", Grade.VIP);
memberService.join(member);
// when
Order itemA = orderService.createOrder(1L, "itemA", 10000);
// then
// 10000์›์—์„œ 1000์› ํ• ์ธ๋ฐ›์•˜์œผ๋‹ˆ๊นŒ 9000์›!
Assertions.assertThat(itemA.realPrice()).isEqualTo(9000);
}
}

- ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ๋งค์šฐ ์ž˜ ๋Œ์•„๊ฐ„๋‹ค.

- ๊ทธ๋Ÿฌ๋‚˜, ์œ„ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

- ๋˜ํ•œ, ์•„์ง ์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ… - ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์„ ์ ์šฉํ•˜์ง€ ์•Š์€ ์ƒํƒœ์ด๋‹ค.

    - ์ธํ„ฐํŽ˜์ด์Šค - ํด๋ž˜์Šค ์„ค๊ณ„ ๋•๋ถ„์— ์šฐ๋ฆฌ๋Š” ๊ทธ๋ƒฅ ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์— ๋Œ€ํ•œ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ ๋’ค, ์ ์šฉํ•ด์ฃผ๋ฉด ๋œ๋‹ค!

 


[RateDiscountPolicy.java]


  
public class RateDiscountPolicy implements DiscountPolicy{
private int discountPercent = 10; // 10% ํ• ์ธ
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP) {
return price * discountPercent / 100;
}
else
return 0;
}
}

- VIP์˜ ๊ฒฝ์šฐ 10% ํ• ์ธ์„ ์ง„ํ–‰ํ•ด์ค€๋‹ค.

 

 

โœ” Test

[RateDiscountPolicyTest.java]


  
class RateDiscountPolicyTest {
RateDiscountPolicy discountPolicy = new RateDiscountPolicy();
@Test
public void vip1() throws Exception {
// given
Member memberVIP = new Member(1L,"VIP", Grade.VIP);
Member memberBASIC = new Member(2L, "BASIC", Grade.BASIC);
// when
int disVIP = discountPolicy.discount(memberVIP, 10000);
int disBASIC = discountPolicy.discount(memberBASIC, 10000);
// then
Assertions.assertThat(disVIP).isEqualTo(1000);
Assertions.assertThat(disBASIC).isEqualTo(0);
}
}

- ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ…Œ์ŠคํŠธ๋Š” ์ž˜ ๋Œ์•„๊ฐ„๋‹ค.

 

- ๊ทธ๋Ÿฌ๋‚˜, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ํ• ์ธ์ •์ฑ…์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” OrderServiceImpl์˜ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

    - ์šฐ๋ฆฌ๊ฐ€ ๊ธฐ์กด์— ์งฐ๋˜ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ, DiscountPolicy๊ฐ€ ๊ตฌ์ฒด ํด๋ž˜์Šค์ธ FixDiscountPolicy๋ฅผ ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ.

    - ์ด๋Ÿฐ ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๋Š” ๊ฒƒ์€ OCP ์œ„๋ฐ˜์ด๋ฉฐ, ๊ตฌ์ฒด ํด๋ž˜์Šค ์˜์กด์œผ๋กœ ์ธํ•œ DIP ์—ญ์‹œ ์œ„๋ฐ˜์ด๋‹ค.

 

- ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ์˜ค์ง ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ด๋ณด์ž.

    - ๊ทธ๋Ÿฌ๋‚˜, ๋‹จ์ˆœํžˆ = new FixDiscountPolicy(); ๋ฅผ ์—†์• ๋ฒ„๋ฆฐ๋‹ค๋ฉด... NPE๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

    - ๋‹น์—ฐํ•˜๋‹ค. ๊ตฌํ˜„์ฒด๊ฐ€ ์—†๋Š”๋ฐ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์œผ๋‹ˆ๊นŒ.

 

- ์šฐ๋ฆฌ๋Š” ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ๋Œ€์‹  ์ƒ์„ฑํ•˜๊ณ  ์ฃผ์ž…ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ด์ฃผ๋Š” Configuration ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฒƒ์ด๋‹ค.

    - ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ๋ฅผ ์œ„ํ•ด, Configuration ์—ญ์‹œ ๋”ฐ๋กœ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ง„ํ–‰ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 


| ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ

- ์‹คํ–‰๋˜๋Š” ๊ฐ์ฒด๋“ค์€ ์–ด๋–ค ๊ตฌํ˜„์ฒด๊ฐ€ ์ฃผ์ž…๋˜๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์–ด์•ผ ํ•œ๋‹ค. ๊ทธ์ € ๊ฐ์ž์˜ ์—ญํ• ์— ์ถฉ์‹คํ•ด์•ผ ํ•œ๋‹ค.

 

 

[AppConfig.java]


  
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(
new MemoryMemberRepository(),
new FixDiscountPolicy()
);
}
}

- ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด, MemberServiceImpl์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ MemberRepository ๊ตฌํ˜„์ฒด๋ฅผ ์—ฌ๊ธฐ์—์„œ ์ฃผ์ž…ํ•˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    - ์‹ค์ œ ๋™์ž‘์— ํ•„์š”ํ•œ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค. ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋Š” ๊ฑด ๋ฌด์กฐ๊ฑด AppConfig์—์„œ ์ง„ํ–‰ํ•œ๋‹ค!

    - ์ด๋Ÿฐ ์‹์œผ๋กœ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ๋„ฃ์–ด์ฃผ๋Š” ๊ฑธ '์ƒ์„ฑ์ž ์ฃผ์ž…' ์ด๋ผ๊ณ  ํ•œ๋‹ค.

    - ์ด์ œ, AppConfig์— ์„ ์–ธ๋œ memberService()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

- orderService() ์—ญ์‹œ ์„ธ๋ถ€์ ์ธ MemberRepository์™€ DiscountPolicy์— ๋Œ€ํ•œ ๊ตฌํ˜„์ฒด๋ฅผ ์—ฌ๊ธฐ์—์„œ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.

 

๐ŸŽˆ ๊ทธ๋Ÿฌ๋‚˜, ํ˜„์žฌ ์ฝ”๋“œ์—์„œ MemoryMemberRepository()๋ฅผ 2๋ฒˆ ์„ ์–ธํ•˜๋Š” ๋“ฑ, ์ค‘๋ณต์ด ์กด์žฌํ•˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

     - ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋Š” ๋’ค์—์„œ ํ•ด๊ฒฐํ•ด๋ณด๋„๋ก ํ•˜์ž.


โœ” ๊ธฐ์กด์— ์„ ์–ธํ•˜์˜€๋˜ ์ฝ”๋“œ ์ˆ˜์ •

[MemberServiceImpl.java]


  
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}

- memberRepository = new MemoryMemberRepository()๋ฅผ ์‚ญ์ œํ•˜๊ณ , ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด memberRepository์— ์ฃผ์ž…๋ฐ›๋„๋ก ํ•˜์˜€๋‹ค.

- ์ด๋Ÿฌ๋ฉด, memberRepository๋Š” ๋” ์ด์ƒ ๊ตฌํ˜„์ฒด๋ฅผ ์˜์กดํ•˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค!

 

[OrderServiceImpl.java]


  
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member findMember = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(findMember, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}

- ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์—ˆ๋‹ค. OrderServiceImpl์€ ์–ด๋–ค ํ• ์ธ ์ •์ฑ…์ด ๋“ค์–ด์˜ค๋Š”์ง€, ์–ด๋–ค DB ์ ‘๊ทผ ๊ธฐ์ˆ ์ด ๋“ค์–ด์˜ค๋Š”์ง€ ๋ชจ๋ฅธ๋‹ค!

- ์ด์ œ, ๊ฐ Impl๋“ค์€ ์˜์กด๊ด€๊ณ„์— ๋Œ€ํ•œ ๊ฑด ์™ธ๋ถ€์— ๋„˜๊ธฐ๊ณ , ์˜ค์ง ๋กœ์ง๋งŒ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿšฉ ์ด๋ ‡๊ฒŒ, DIP๋ฅผ ๋งŒ์กฑํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. Impl๋“ค์€ ์˜ค์ง ์ถ”์ƒํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•œ๋‹ค.

 


โœ” Test ์ฝ”๋“œ ์ˆ˜์ •

[MemberServiceTest.java]


  
class MemberServiceTest {
MemberService memberService;
@BeforeEach
public void beforeEach() {
AppConfig appConfig = new AppConfig();
memberService = appConfig.memberService();
}
@Test
public void join() throws Exception {
// given
Member member = new Member(1L, "hello", Grade.BASIC);
// when
memberService.join(member);
// then
Member findMember = memberService.findMember(1L);
Assertions.assertThat(findMember).isEqualTo(member);
}
}

- @BeforeEach๋ฅผ ํ†ตํ•ด, ๊ฐ ํ…Œ์ŠคํŠธ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— AppConfig๋ฅผ ์„ ์–ธํ•˜์—ฌ ๋‚ด๋ถ€์˜ memberService๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ํ•˜์˜€๋‹ค.

 

[OrderServiceTest.java]


  
class OrderServiceTest {
MemberService memberService;
OrderService orderService;
@BeforeEach
public void beforeEach() {
AppConfig appConfig = new AppConfig();
memberService = appConfig.memberService();
orderService = appConfig.orderService();
}
@Test
public void createOrder() throws Exception {
// given
Member member = new Member(1L, "hello", Grade.VIP);
memberService.join(member);
// when
Order itemA = orderService.createOrder(1L, "itemA", 10000);
// then
// 10000์›์—์„œ 1000์› ํ• ์ธ๋ฐ›์•˜์œผ๋‹ˆ๊นŒ 9000์›!
Assertions.assertThat(itemA.realPrice()).isEqualTo(9000);
}
}

- ๋‹ค ์ข‹์€๋ฐ, AppConfig๋ฅผ ์กฐ๊ธˆ ๋” ๊น”๋”ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•ด๋ณด์ž.

[AppConfig.java]


  
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(
memberRepository(),
discountPolicy()
);
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public DiscountPolicy discountPolicy() {
//return new FixDiscountPolicy();
return new RateDiscountPolicy();
}
}

- ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก MemberRepository์™€ DiscountPolicy์— ๋Œ€ํ•œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ถ€๋ถ„์„ ๋”ฐ๋กœ ํ•จ์ˆ˜๋กœ ๋บ๋‹ค.

    - ์ดํ›„ ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•˜๋”๋ผ๋„ memberRepository(), discountPolicy() ๋‚ด๋ถ€๋งŒ ๋ฐ”๊พธ์–ด ์ฃผ๋ฉด ๋œ๋‹ค!

- ์ด๋Š” ๊ณง, Service๋Š” Service๋งŒ, Repository๋Š” Repository๋งŒ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋˜์–ด ์กฐ๊ธˆ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์—ญํ• ๊ณผ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ํ•œ๋ˆˆ์— ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 


- ์ง€๊ธˆ๊นŒ์ง€ ์šฐ๋ฆฌ๋Š” SOLID๋ฅผ ๋งŒ์กฑํ•˜๊ธฐ ์œ„ํ•ด์„œ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์‹œ๋„๋ฅผ ํ–ˆ๋‹ค.

    - SRP : ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ๊ตฌํ˜„ ๊ฐ์ฒด์˜ ์ƒ์„ฑ ๋ฐ ์—ฐ๊ฒฐ์€ AppConfig์œผ๋กœ, ๊ฐ ๊ฐ์ฒด๋Š” ๋กœ์ง์—๋งŒ ์ง‘์ค‘ํ•˜๋„๋ก.

    - DIP : ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กดํ•˜์ง€ ์•Š๋„๋ก AppConfig๊ฐ€ ๋Œ€์‹  ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•˜์˜€๋‹ค.

    - OCP : Fix<->Rate๋กœ ํ• ์ธ ์ •์ฑ…์„ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์˜ ๋ณ€๊ฒฝ ์—†์ด AppConfig๋งŒ ์ˆ˜์ •ํ•˜์˜€๋‹ค.

 

- ์ด์ œ, ์ˆœ์ˆ˜ ์ž๋ฐ”๋งŒ์„ ์ด์šฉํ•˜์ง€ ์•Š๊ณ  ์Šคํ”„๋ง์„ ํ†ตํ•ด์„œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•ด๋ณด์ž!

 

Comments