[Spring] 2.์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ ์ดํ•ด1 - ์˜ˆ์ œ ๋งŒ๋“ค๊ธฐ

 

1. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

- java11, Intelli J

- ์Šคํ”„๋ง ๋ถ€ํŠธ https://start.spring.io

  Gradle / Java / ๋ฒ„์ „(๊ฐ€์žฅ์•ˆ์ •ํ™”๋œ ์ตœ์‹ ๋ฒ„์ „) -> ์˜ค๋ฅ˜๋‚˜์„œ 2.7 ๋ฒ„์ „๋Œ€๋กœํ•จ

  group(hello) 

  artifact(core) - ํ”„๋กœ์ ํŠธ ์ด๋ฆ„

  packaging (jar war ์ค‘์— jar) 

  java 11

  dependcies ์„ ํƒ X

  -> generate

 

> ์••์ถ•ํ’€๊ณ  Application ์‹คํ–‰ํ•˜๊ธฐ

> Preferences - Gradle - build and run using / run tests using ๋‘˜ ๋‹ค ์ธํ…”๋ฆฌ์ œ์ด๋กœ ๋ฐ”๊ฟ”์ฃผ๊ธฐ (ํŒ)


2. ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ์„ค๊ณ„

ํšŒ์›

- ํšŒ์› ๊ฐ€์ž… ์กฐํšŒ ๊ฐ€๋Šฅ

- ํšŒ์› ๋“ฑ๊ธ‰ ์ผ๋ฐ˜/VIP
- ํšŒ์› ๋ฐ์ดํ„ฐ๋Š” ์ž์ฒด DB ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ณ  ์™ธ๋ถ€์‹œ์Šคํ…œ๊ณผ ์—ฐ๋™ ๊ฐ€๋Šฅ (๋ฏธํ™•์ •)

 

์ฃผ๋ฌธ๊ณผ ํ• ์ธ ์ •์ฑ…

- ํšŒ์›์€ ์ƒํ’ˆ์„ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํšŒ์› ๋“ฑ๊ธ‰์— ๋”ฐ๋ผ ํ• ์ธ ์ •์ฑ…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํ• ์ธ ์ •์ฑ…์€ ๋ชจ๋“  VIP๋Š” 1000์›์„ ํ• ์ธํ•ด์ฃผ๋Š” ๊ณ ์ • ๊ธˆ์•ก ํ• ์ธ์„ ์ ์šฉํ•ด๋‹ฌ๋ผ

- ํ• ์ธ ์ •์ฑ…์€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ ๋†’๋‹ค -> ์ตœ์•…์˜ ๊ฒฝ์šฐ ํ• ์ธ ์ ์šฉ ์•ˆํ• ์ˆ˜๋„์žˆ๋‹ค. (๋ฏธํ™•์ •)

 

์š”๊ตฌ์‚ฌํ•ญ์„ ๋ณด๋ฉด ์ง€๊ธˆ ์ •ํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ๋“ค์ด ์žˆ๋‹ค.

-> ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„ ๋ฐฉ๋ฒ• ํ™œ์šฉ

 

<< ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ ์—†์ด ์ฝ”๋”ฉ >>


3. ํšŒ์› ๋„๋ฉ”์ธ ์„ค๊ณ„

ํšŒ์› ๋„๋ฉ”์ธ ์š”๊ตฌ์‚ฌํ•ญ

- ํšŒ์›์„ ๊ฐ€์ž…ํ•˜๊ณ  ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํšŒ์›์€ ์ผ๋ฐ˜๊ณผ vip ๋“ฑ๊ธ‰ ๋‘ ๊ฐœ

- ํšŒ์› ๋ฐ์ดํ„ฐ๋Š” ์ž์ฒด DB ๊ตฌ์ถ•ํ• ์ˆ˜๋„์žˆ๊ณ , ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ๋‹ค. (๋ฏธํ™•์ •)

 

[ํšŒ์› ๋„๋ฉ”์ธ ํ˜‘๋ ฅ ๊ด€๊ณ„]

[ํšŒ์› ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ]

[ํšŒ์› ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ]


4. ํšŒ์› ๋„๋ฉ”์ธ ๊ฐœ๋ฐœ

[ํšŒ์› ์—”ํ‹ฐํ‹ฐ]

ใ„ด hello.cored.member

 

ํšŒ์› ๋“ฑ๊ธ‰ (Enum)

public enum Grade {
  BASIC,
  VIP
}

ํšŒ์› ์—”ํ‹ฐํ‹ฐ(Class)

package hello.cored.member;

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;
  }

  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Grade getGrade() {
    return grade;
  }

  public void setGrade(Grade grade) {
    this.grade = grade;
  }
}

 

[ํšŒ์› ์ €์žฅ์†Œ]

ใ„ด hello.cored.member

 

ํšŒ์› ์ €์žฅ์†Œ ์ธํ„ฐํŽ˜์ด์Šค(Interface)

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

๋ฉ”๋ชจ๋ฆฌ ํšŒ์› ์ €์žฅ์†Œ ๊ตฌํ˜„์ฒด(Class)

public class MemoryMemberRepository implements MemberRepository{

  private static Map<Long, Member> store = new HashMap<>();

  @Override
  public void save(Member member) {
    store.put(member.getId(), member);
  }

  @Override
  public Member findById(Long memberId) {
    return store.get(memberId);
  }
}

 

[ํšŒ์› ์„œ๋น„์Šค]

ใ„ด hello.cored.member

 

ํšŒ์› ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค(Interface)

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

ํšŒ์› ์„œ๋น„์Šค ๊ตฌํ˜„์ฒด(Class)

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);
  }
}

5. ํšŒ์› ๋„๋ฉ”์ธ ์‹คํ–‰๊ณผ ํ…Œ์ŠคํŠธ

ํšŒ์› ๋„๋ฉ”์ธ - ํšŒ์› ๊ฐ€์ž… main

ใ„ด hello.cored

 

MemberApp(Class)

public class MemberApp {
  public static void main(String[] args) {
    MemberService memberService = new MemberServiceImpl();
    Member member = new Member(1L, "memberA", Grade.VIP);
    memberService.join(member);

    Member findMember = memberService.findMember(1L);
    System.out.println("findMember = " + findMember.getName());
    System.out.println("member = " + member.getName());
  }
}

-> ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์œผ๋กœ ์ด๋ ‡๊ฒŒ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋‹ค.

-> JUnit ํ…Œ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ž.

 

ํšŒ์› ๋„๋ฉ”์ธ - ํšŒ์› ๊ฐ€์ž… ํ…Œ์ŠคํŠธ

ใ„ด hello.cored.member (test์˜ ํ•˜์œ„ํด๋”)

 

MemberServiceTest(Class)

public class MemberServiceTest {

  MemberService memberService = new MemberServiceImpl();

  @Test
  void join() {
    // given
    Member member = new Member(1L, "memberA", Grade.VIP);

    // when
    memberService.join(member);
    Member findMember = memberService.findMember(1L);

    // then
    Assertions.assertThat(member).isEqualTo(findMember);

  }
}

* Assertions -> org.assertj.core.api ์‚ฌ์šฉํ•˜๋ฉด ๋จ 

ํšŒ์› ๋„๋ฉ”์ธ ์„ค๊ณ„์˜ ๋ฌธ์ œ์ 

- ์ด ์ฝ”๋“œ์˜ ์„ค๊ณ„์ƒ ๋ฌธ์ œ์ ์€ ๋ฌด์—‡์ผ๊นŒ์š”?
- ๋‹ค๋ฅธ ์ €์žฅ์†Œ๋กœ ๋ณ€๊ฒฝํ•  ๋•Œ OCP ์›์น™์„ ์ž˜ ์ค€์ˆ˜ํ• ๊นŒ์š”?
- DIP
๋ฅผ ์ž˜ ์ง€ํ‚ค๊ณ  ์žˆ์„๊นŒ์š”?
- ์˜์กด๊ด€๊ณ„๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ตฌํ˜„๊นŒ์ง€ ๋ชจ๋‘ ์˜์กดํ•˜๋Š” ๋ฌธ์ œ์ ์ด ์žˆ์Œ

- ์ฃผ๋ฌธ๊นŒ์ง€ ๋งŒ๋“ค๊ณ ๋‚˜์„œ ๋ฌธ์ œ์ ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ์„ ์„ค๋ช…


6. ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ์„ค๊ณ„

์ฃผ๋ฌธ๊ณผ ํ• ์ธ ์ •์ฑ…

- ํšŒ์›์€ ์ƒํ’ˆ์„ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํšŒ์› ๋“ฑ๊ธ‰์— ๋”ฐ๋ผ ํ• ์ธ ์ •์ฑ…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํ• ์ธ ์ •์ฑ…์€ ๋ชจ๋“  VIP 1000์› ํ• ์ธ (๋‚˜์ค‘์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ)

- ํ• ์ธ ์ •์ฑ…์€ ๋ณ€๊ฒฝ๊ฐ€๋Šฅ์„ฑ ๋†’๋‹ค. ์•ˆํ• ์ˆ˜๋„์žˆ๋‹ค. (๋ฏธํ™•์ •)

 

[์ฃผ๋ฌธ ๋„๋ฉ”์ธ ํ˜‘๋ ฅ, ์—ญํ• , ์ฑ…์ž„]

1) ์ฃผ๋ฌธ ์ƒ์„ฑ : ํด๋ผ์ด์–ธํŠธ๋Š” ์ฃผ๋ฌธ ์„œ๋น„์Šค์— ์ฃผ๋ฌธ ์ƒ์„ฑ์„ ์š”์ฒญํ•œ๋‹ค.

2) ํšŒ์› ์กฐํšŒ : ํ• ์ธ์„ ์œ„ํ•ด์„œ๋Š” ํšŒ์› ๋“ฑ๊ธ‰์ด ํ•„์š” / ๊ทธ๋ž˜์„œ ์ฃผ๋ฌธ ์„œ๋น„์Šค๋Š” ํšŒ์› ์ €์žฅ์†Œ์—์„œ ํšŒ์›์„ ์กฐํšŒ

3) ํ• ์ธ ์ ์šฉ : ์ฃผ๋ฌธ ์„œ๋น„์Šค๋Š” ํšŒ์› ๋“ฑ๊ธ‰์— ๋”ฐ๋ฅธ ํ• ์ธ ์—ฌ๋ถ€๋ฅผ ํ• ์ธ ์ •์ฑ…์— ์œ„์ž„

4) ์ฃผ๋ฌธ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ : ์ฃผ๋ฌธ ์„œ๋น„์Šค๋Š” ํ• ์ธ ๊ฒฐ๊ณผ๋ฅผ ํฌํ•จํ•œ ์ฃผ๋ฌธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜

 

[์ฃผ๋ฌธ ๋„๋ฉ”์ธ ์ „์ฒด]

- ์—ญํ• ๊ณผ ๊ตฌํ˜„์„ ๋ถ„๋ฆฌ -> ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค๊ณ„  / ๋•๋ถ„์— ํšŒ์› ์ €์žฅ์†Œ, ํ• ์ธ ์ •์ฑ… ์œ ์—ฐ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

 

[์ฃผ๋ฌธ ๋„๋ฉ”์ธ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ]

[์ฃผ๋ฌธ ๋„๋ฉ”์ธ ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ1]

- ํšŒ์›์„ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์กฐํšŒํ•˜๊ณ  ์ •์•ก ํ• ์ธ ์ •์ฑ… (๊ณ ์ • ๊ธˆ์•ก)์„ ์ง€์›ํ•ด๋„ ์ฃผ๋ฌธ ์„œ๋น„์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

- ์—ญํ• ๋“ค์˜ ํ˜‘๋ ฅ ๊ด€๊ณ„๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ

 

[์ฃผ๋ฌธ ๋„๋ฉ”์ธ ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ2]

- ํšŒ์›์„ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•„๋‹Œ ์‹ค์ œ DB์—์„œ ์กฐํšŒ, ํ• ์ธ ์ •์ฑ…(์ฃผ๋ฌธ ๊ธˆ์•ก์— ๋”ฐ๋ผ %ํ• ์ธ)์„ ์ง€์›ํ•ด๋„ ์ฃผ๋ฌธ์„œ๋น„์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.


7. ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ๊ฐœ๋ฐœ

ํ• ์ธ

ใ„ดhello.cored.discount

 

ํ• ์ธ ์ •์ฑ… ์ธํ„ฐํŽ˜์ด์Šค(Interface)

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

์ •์•ก ํ• ์ธ ์ •์ฑ… ๊ตฌํ˜„์ฒด(Class)

public class FixDiscountPolicy implements DiscountPolicy {
  private int discountFixAmount = 1000;

  @Override
  public int discount(Member member, int price) {
    if(member.getGrade() == Grade.VIP){
      return discountFixAmount;
    }
    return 0;
  }
}

 

์ฃผ๋ฌธ

ใ„ดhello.cored.order

 

์ฃผ๋ฌธ ์—”ํ‹ฐํ‹ฐ(Class)

public class Order {
  private Long memberId;
  private String itemName;
  private int itemPrice;
  private int discountPrice;

  public Order(Long memberId, String itemName, int itemPrice, int discountPrice) {
    this.memberId = memberId;
    this.itemName = itemName;
    this.itemPrice = itemPrice;
    this.discountPrice = discountPrice;
  }

  public int caculatePrice(){
    return itemPrice - discountPrice;
  }

  public Long getMemberId() {
    return memberId;
  }

  public void setMemberId(Long memberId) {
    this.memberId = memberId;
  }

  public String getItemName() {
    return itemName;
  }

  public void setItemName(String itemName) {
    this.itemName = itemName;
  }

  public int getItemPrice() {
    return itemPrice;
  }

  public void setItemPrice(int itemPrice) {
    this.itemPrice = itemPrice;
  }

  public int getDiscountPrice() {
    return discountPrice;
  }

  public void setDiscountPrice(int discountPrice) {
    this.discountPrice = discountPrice;
  }

  @Override
  public String toString() {
    return "Order{" +
            "memberId=" + memberId +
            ", itemName='" + itemName + '\'' +
            ", itemPrice=" + itemPrice +
            ", discountPrice=" + discountPrice +
            '}';
  }
}

- ์ตœ์ข… ๊ณ„์‚ฐ๋œ ๊ธˆ์•ก ๋ฐ˜ํ™˜ํ•˜๋Š” caculatePrice๊ฐ€ ์žˆ์Œ

- ๊ฒฐ๊ณผ ๋ณด๊ธฐ์‰ฝ๊ฒŒ toString @Override ํ•ด์ฃผ๊ธฐ (์ด๊ฒƒ๋„ cmd + N)

 

์ฃผ๋ฌธ ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค(Interface)

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

์ฃผ๋ฌธ ์„œ๋น„์Šค ๊ตฌํ˜„(Class)

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 member = memberRepository.findById(memberId);
    int discountPrice = discountPolicy.discount(member, itemPrice);

    return new Order(memberId, itemName, itemPrice, discountPrice);
  }
}

- SOLID ๋‹จ์ผ ์ฑ…์ž„ ์›์น™(SRP) ์ž˜ ์ง€์ผœ์ง„ ๊ฒƒ -> ํ• ์ธ์— ๋Œ€ํ•œ๊ฑฐ discount๊ฐ€ ๋‹ด๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— 


8. ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ์‹คํ–‰๊ณผ ํ…Œ์ŠคํŠธ

์ฃผ๋ฌธ๊ณผ ํ• ์ธ ์ •์ฑ… ์‹คํ–‰

 

OrderApp(Class)

public class OrderApp {
  public static void main(String[] args) {
    MemberService memberService = new MemberServiceImpl();
    OrderService orderService = new OrderServiceImpl();

    long memberId = 1L;

    Member member = new Member(memberId, "memberA", Grade.VIP);
    memberService.join(member);

    Order order = orderService.createOrder(memberId, "itemA", 10000);

    System.out.println("order = " + order);
  }
}

test

class OrderServiceTest {
  MemberService memberService = new MemberServiceImpl();
  OrderService orderService = new OrderServiceImpl();
  @Test
  void createOrder() {
    long memberId = 1L;
    Member member = new Member(memberId, "memberA", Grade.VIP);
    memberService.join(member);
    Order order = orderService.createOrder(memberId, "itemA", 10000);
    Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
  }
}
  • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
  • ๋„ค์ด๋ฒ„ ๋ฐด๋“œ์— ๊ณต์œ ํ•˜๊ธฐ
  • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
  • ์นด์นด์˜ค์Šคํ† ๋ฆฌ ๊ณต์œ ํ•˜๊ธฐ