[Spring] 3.ํšŒ์›๊ด€๋ฆฌ ์˜ˆ์ œ - ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ

 

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

- ๋ฐ์ดํ„ฐ : ํšŒ์›ID, ์ด๋ฆ„

- ๊ธฐ๋Šฅ : ํšŒ์› ๋“ฑ๋ก, ์กฐํšŒ

- ์•„์ง ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ๊ฐ€ ์„ ์ •๋˜์ง€ ์•Š์Œ (๊ฐ€์ƒ์˜ ์‹œ๋‚˜๋ฆฌ์˜ค)

 

- ์ปจํŠธ๋กค๋Ÿฌ : ์›น MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ ์—ญํ• 

- ์„œ๋น„์Šค : ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ์„ ๊ฐ€์ง€๊ณ  ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ตฌํ˜„ (ํšŒ์› ์ค‘๋ณต๊ฐ€์ž… ์•ˆ๋˜๋Š” ๋กœ์ง ๋“ฑ) 

- ๋ฆฌํฌ์ง€ํ† ๋ฆฌ : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผ, ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ DB์— ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌ

- ๋„๋ฉ”์ธ : ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ ๊ฐ์ฒด, ex) ํšŒ์›, ์ฃผ๋ฌธ, ์ฟ ํฐ ๋“ฑ ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌ๋จ

 

- ์•„์ง ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ๊ฐ€ ์„ ์ •๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์šฐ์„  ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„

- ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ๋Š” RDB, NoSQL๋“ฑ ๋‹ค์–‘ํ•œ ์ €์žฅ์†Œ๋ฅผ ๊ณ ๋ฏผ์ค‘์ธ ์ƒํ™ฉ์œผ๋กœ ๊ฐ€์ •

- ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ดˆ๊ธฐ ๊ฐœ๋ฐœ ๋‹จ๊ณ„์—์„œ๋Š” ๊ตฌํ˜„์ฒด๋กœ ๊ฐ€๋ฒผ์šด ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋ฐ˜์˜ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ ์‚ฌ์šฉ

 

ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„

1) MemberService : ํšŒ์› ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ํšŒ์› ์„œ๋น„์Šค

2) MemberRepository : ํšŒ์› ์ €์žฅํ•˜๋Š” ๊ฒƒ์€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์„ค๊ณ„

3) MemoryMemberRespository : ๊ตฌํ˜„์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌํ˜„์ฒด๋กœ ๋งŒ๋“ฆ (๋ฉ”๋ชจ๋ฆฌ๋กœ ๋‹จ์ˆœํžˆ ์ €์žฅ)

 

๊ตฌ์ฒด์  ๊ธฐ์ˆ (DB)์ด ์„ ์ •์ด ๋˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ•„์š”

 

2. ํšŒ์› ๋„๋ฉ”์ธ๊ณผ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋งŒ๋“ค๊ธฐ

- java - hello.hellosp - domain package ๋งŒ๋“ฆ - Member ํด๋ž˜์Šค ์ƒ์„ฑ

package hello.hellosp.domain;

public class Member {
    private Long id;   // system ๋“ฑ๋กํ•  ๋•Œ id
    private String name;   // ๊ฐ€์ž…ํ• ๋•Œ ์ด๋ฆ„

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

- java - hello.hellosp - repository package ๋งŒ๋“ฆ - MemberRepository ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ

package hello.hellosp.repository;

import first.hellospring.domain.Member;

import java.util.List;

import java.util.Optional;

public interface MemberRepository {
    Member save(Member member); // ์ €์žฅ์†Œ์— ํšŒ์›์ด ์ €์žฅ
    Optional<Member> findById(Long id);   // ์ €์žฅ์†Œ์—์„œ ์ฐพ์•„์˜ค๋Š” ๊ฒƒ
    Optional<Member> findByName(String name);   // find by null ๋ฐ˜ํ™˜ํ• ๋•Œ optional๋กœ ๊ฐ์‹ธ์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด optional์˜ ๊ธฐ๋Šฅ

    List<Member> findAll();  // ์ง€๊ธˆ๊นŒ์ง€ ์ €์žฅ๋œ ๋ชจ๋“  ํšŒ์› ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜
}

- Optional : ์—†์œผ๋ฉด null๋กœ ๋ฐ˜ํ™˜๋˜๋Š”๋ฐ ๋ฐ˜ํ™˜๋  ๋•Œ optional๋กœ ๊ฐ์‹ธ์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฒƒ

 

 - java - hello.hellosp - repository package - M  emoryMemberRepository ํด๋ž˜์Šค ์ƒ์„ฑ

public class MemoryMemberRepository implements MemberRepository{

    // ์ €์žฅํ•  ๊ณณ
    private static Map<Long, Member> store = new HashMap<>(); // ์‹ค๋ฌด์—์„œ๋Š” ๋™์‹œ์„ฑ ๋ฌธ์ œ๋กœ concurrent hash ์จ์•ผํ•จ
    private static long sequence = 0L; // ์‹œํ€€์Šค๋Š” key ๊ฐ’ ์ƒ์„ฑํ•ด์ฃผ๋Š” ๊ฒƒ, ์‹ค๋ฌด์—์„œ๋Š” long๋ณด๋‹ค๋Š” atomic long

    @Override
    public Member save(Member member) {
        member.setId(++sequence);            // store ๋„ฃ๊ธฐ ์ „์— member ์•„์ด๋”” ๊ฐ’ ์„ธํŒ…
        store.put(member.getId(), member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));    //null ๋ฐ˜ํ™˜ ๊ฐ€๋Šฅ์„ฑ ์žˆ์–ด์„œ optional๋กœ ๊ฐ์‹ธ์คŒ
                                                      // ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๋กœ ์กฐ์ž‘๊ฐ€๋Šฅ
    }

    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream() // ๋ฃจํ”„ ๋Œ๋ฆผ
                .filter(member -> member.getName().equals(name))  //๊ฐ™์€์ง€ ํ™•์ธ
                .findAny(); // ํ•˜๋‚˜๋ผ๋„ ์ฐพ์œผ๋ฉด ๋ฐ˜ํ™˜, ๋๊นŒ์ง€ ์—†์œผ๋ฉด optional null
    }

    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());
    }
}

 

 

 

3. ํšŒ์› ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ

- ํ…Œ์ŠคํŠธ ํ•  ๋•Œ ์ž๋ฐ”์˜ main ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์‹คํ–‰

    -> ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์€ ๋ฒˆ๊ฑฐ๋กญ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค

- ์ž๋ฐ”์˜ JUnit ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ํ…Œ์ŠคํŠธ ์‹คํ–‰

 

`src/test/java` ํ•˜์œ„ํด๋”์— ํ…Œ์ŠคํŠธํ•  ํŒจํ‚ค์ง€์™€ ํด๋ž˜์Šค ์ƒ์„ฑ - hello.hellosp - repository package - MemoryMemberRepositorytest class

package hello.hellosp.repository;

import hello.hellosp.domain.Member;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.util.List;

class MemoryMemberRepositoryTest {
  MemoryMemberRepository repository = new MemoryMemberRepository();

  @AfterEach // ๋ฉ”์„œ๋“œ ์‹คํ–‰ ๋๋‚ ๋•Œ๋งˆ๋‹ค ๋™์ž‘ (์ฝœ๋ฐฑ ๋ฉ”์„œ๋“œ)
  public void afterEach() {
    repository.clearStore();
  }

  @Test
  public void save() {   // test๋กœ ๋ฉ”์„œ๋“œ ์‹คํ–‰๋จ
    Member member = new Member();  // ๋ฉ”์ธ ๋ฉ”์„œ๋“œ ์„ธํŒ…ํ•ด์ฃผ๋Š”๊ฑฐ๋ž‘ ๋น„์Šท
    member.setName("JoonieKim");

    repository.save(member);  // ์ €์žฅํ• ๋•Œ ์•„์ด๋”” ์„ธํŒ…๋จ

    Member result = repository.findById(member.getId()).get();  // ์˜ต์…”๋„์—์„œ ๊ฐ’ ๊บผ๋ƒ„, get์œผ๋กœ ๊บผ๋‚ด๋Š”๊ฒŒ ์ข‹์€๊ฑด ์•„๋‹˜
    // Assertions.assertEquals(member, result); // ์ €์žฅํ•œ ๋ฉค๋ฒ„์™€ ๊ฒฐ๊ณผ๊ฐ’์ด ๊ฐ™์€์ง€ ๋น„๊ต -> ๋…น์ƒ‰๋ถˆ์ด ๋œธ(์„ฑ๊ณต)
    // ์š”์ฆ˜์—” ์•„๋ž˜๊ป„ ๋” ๋งŽ์ด ์”€ (assert J)
    Assertions.assertThat(member).isEqualTo(result); // ๋ฉค๋ฒ„๊ฐ€ result๋ž‘ ๋˜‘๊ฐ™์€์ง€ ๋น„๊ตํ•ด์ฃผ๋Š” ๊ฒƒ
    // Assertions์„ static import๋กœ ํ•ด์„œ (์˜ต์…˜ + ์—”ํ„ฐ) assertThat ์‚ฌ์šฉ๊ฐ€๋Šฅ
  }

  @Test
  public void findByName() {
    Member member1 = new Member();
    member1.setName("spring1");
    repository.save(member1);

    Member member2 = new Member();
    member2.setName("spring2");
    repository.save(member2);

    Member result = repository.findByName("spring1").get();
    Assertions.assertThat(result).isEqualTo(member2); 
  }

  @Test
  public void findAll() {
    Member member1 = new Member();
    member1.setName("spring1");
    repository.save(member1);

    Member member2 = new Member();
    member2.setName("spring2");
    repository.save(member2);

    List<Member> result = repository.findAll();
    Assertions.assertThat(result.size()).isEqualTo(2);
  }
}

 

- ๋”ฐ๋กœ ๋Œ๋ฆฌ๊ฑฐ๋‚˜ ํ…Œ์ŠคํŠธ ์ „์ฒด ๋Œ๋ฆฌ๋Š” ๊ฒƒ ๋ชจ๋‘ ๊ฐ€๋Šฅ

 

[ํ•œ๋ฒˆ์— ๋Œ๋ ธ์„ ๋•Œ ์˜ค๋ฅ˜]

WHY?

- ๋ฌด์ž‘์œ„๋กœ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „์— ์ €์žฅ๋œ ๊ฐ์ฒด (findall ํ…Œ์ŠคํŠธ ๋•Œ ์ €์žฅ๋œ ๊ฐ์ฒด)๊ฐ€ findbyname์— ๋ถˆ๋ ค์˜ด

- ๊ทธ๋ ‡๋‹ค๋ฉด ํ•˜๋‚˜์˜ @Test ํ•˜๋‚˜๊ฐ€ ๋๋‚˜๋ฉด ํ…Œ์ดํ„ฐ ํด๋ฆฌ์–ด ํ•ด์ค˜์•ผํ•จ

 

MemoryMemberRepository ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ„์— ์ถ”๊ฐ€

public void clearStore() {
        store.clear();
    }

 

ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ (TDD) : ํ…Œ์ŠคํŠธ ๋จผ์ € ์„ค๊ณ„ํ•˜๊ณ  ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•

 

์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์งˆ์ˆ˜๋ก ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์—†์ด ๊ฐœ๋ฐœ ๋ถˆ๊ฐ€๋Šฅ! 

ํ…Œ์ŠคํŠธ ๊ณต๋ถ€ ๊นŠ์ด์žˆ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”!

 

4. ํšŒ์› ์„œ๋น„์Šค ๊ฐœ๋ฐœ

- java - first package - service package ์ƒ์„ฑ - MemberService ํด๋ž˜์Šค ์ƒ์„ฑ

package first.hellospring.service;

import first.hellospring.domain.Member;
import first.hellospring.repository.MemberRepository;
import first.hellospring.repository.MemoryMemberRepository;

import java.util.List;
import java.util.Optional;

public class MemberService {
    private final MemberRepository memberRepository= new MemoryMemberRepository();

    /** ํšŒ์›๊ฐ€์ž„ **/
    public Long join(Member member) {
        //๊ฐ™์€ ์ด๋ฆ„์ด ์žˆ๋Š” ์ค‘๋ณต ํšŒ์› ์•ˆ๋จ
        validateDuplicateMemeber(member); // ์ค‘๋ณตํšŒ์›๊ฒ€์ฆ
        /* ๋กœ์ง์ด ๋‚˜์˜ค๋Š” ๊ฒฝ์šฐ๋Š” ๋ฉ”์„œ๋“œ๋กœ ๋ฝ‘๋Š” ๊ฒƒ์ด ์ข‹์Œ */
        memberRepository.save(member);
        return member.getId();
    }

    private void validateDuplicateMemeber(Member member) {
        memberRepository.findByName(member.getName())
                .ifPresent(member1 -> { // ๋ฉค๋ฒ„ ๊ฐ’์ด ์žˆ์œผ๋ฉด ๋กœ์ง ๋™์ž‘ (Optional์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅ) ๊ณผ๊ฑฐ : if null
                    // get ๊ถŒ์žฅํ•˜์ง„ ์•Š์Œ, orElseGet๋„ ์žˆ์Œ (์žˆ์œผ๋ฉด ๊บผ๋‚ด)
                    throw new IllegalStateException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");
                 });

        /* ์ข€๋” ์‰ฌ์šด ์ฝ”๋“œ
        memberRepository.findByName(member.getName())
           .ifPresent(m -> {
               throw new IllegalStateException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.")
         }) */
    }

    /** ์ „์ฒด ํšŒ์› ์กฐํšŒ **/
    public List<Member> findMembers() {
        return memberRepository.findAll();
    }

    public Optional<Member> findOne(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

 

 

 

 

5. ํšŒ์› ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ (JUnit)

- ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•˜๋Š” ๋ฒ•

-> MemberService ํด๋ž˜์Šค์— ctrl + shift + t = test ์ƒ์„ฑ

- test๋Š” ๋‚ด๋ถ€์—์„œ ๋ณด๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•œ๊ธ€๋กœ๋„ ๊ฐ€๋Šฅ (๋นŒ๋“œํ•  ๋•Œ ํฌํ•จ๋˜์ง€ ์•Š์Œ)

[given - when - then ๋ฌธ๋ฒ•]

package first.hellospring.service;

import first.hellospring.domain.Member;
import first.hellospring.repository.MemoryMemberRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;


    // ํ…Œ์ŠคํŠธ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ๋ฉ”๋ชจ๋ฆฌ๋ฉค๋ฒ„ repo ๋งŒ๋“ค๊ณ  ๊ทธ๊ฑฐ๋ฅผ ๋ฉค๋ฒ„ repo์— ๋„ฃ๊ณ 
    // ๋ฉค๋ฒ„ repo๋ฅผ memberservice์— ๋„ฃ์–ด์ฃผ๋ฉด ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ๋ฉค๋ฒ„ repo ์‚ฌ์šฉ
    // = DI (dependency injection) ์˜์กด์„ฑ ์ฃผ์ž…
    @BeforeEach
    public void beforeEach() {
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }

    @AfterEach
    public void afterEach() {
        memberRepository.clearStore();
    }

    @Test
    void signUp() {
        // given - when - then ๋ฌธ๋ฒ•
        // given
        Member member = new Member();
        member.setName("hello");

        // when
        Long saveId = memberService.join(member);

        // then
        Member findMember = memberService.findOne(saveId).get();
        Assertions.assertThat(member.getName()).isEqualTo(findMember.getName());
    }


    /** ์ค‘๋ณต ํšŒ์› ์˜ˆ์™ธ ๊ฒ€์ฆ์ด ๋” ์ค‘์š” **/
    @Test
    public void duplicatedCheck() {
        //given
        Member member1 = new Member();
        member1.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");
        //when
//        try {
//            memberService.join(member2);
//            // ์ด๊ฒŒ ๋ฉ€์ฉกํžˆ ๋„˜์–ด๊ฐ€๋ฉด fail ์ธ๊ฒƒ์ž„
//            fail();
//        } catch (IllegalStateException e) {
//            // exception ํ„ฐ์ ธ์„œ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰ํ•œ ๊ฒƒ
//            Assertions.assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");
//        }
        // ์ข€ ๋” ์ข‹์€ ๋ฌธ๋ฒ•
        memberService.join(member1);
        assertThrows(IllegalStateException.class, () -> memberService.join(member2));
        // ๋’ค์— ์žˆ๋Š” member~ ๋กœ์ง ์‹คํ–‰ํ• ๊ฑด๋ฐ ์•ž์— ์˜ˆ์™ธ๊ฐ€ ํ„ฐ์ ธ์•ผํ•œ๋‹ค.

        // ๋ฉ”์„ธ์ง€ ๊ฒ€์ฆ -> cmd option v -> e๊ฐ’์— ์ €์žฅํ•˜๊ณ  ํ™•์ธ
//        memberService.join(member1);
//        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
//        Assertions.assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");
    }

    @Test
    void findMembers() {
    }

    @Test
    void findOne() {
    }
}

 

์˜์กด์„ฑ ์ฃผ์ž…

MemberService ํด๋ž˜์Šค

//    private final MemberRepository memberRepository= new MemoryMemberRepository();
    // ๋ฉค๋ฒ„ ์„œ๋น„์Šค์˜ new MemoryMemberRepository์™€ Testcase์˜ ๊ทธ๊ฒƒ์ด ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค์ž„. (static์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ์•ˆ๋˜์ง€๋งŒ ์•„๋‹ˆ๋ผ๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Œ)
    // ๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ repository๋กœ ํ…Œ์ŠคํŠธํ•˜๋ ค๊ณ  ํ•˜๋Š”๊ฑด๋ฐ ์ง€๊ธˆ ๋‹ค๋ฅธ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ๋กœ ํ…Œ์ŠคํŠธ ๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ

    // ์˜์กด์„ฑ ์ฃผ์ž…
    private final MemberRepository memberRepository;
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

 

MemberServiceTest ํด๋ž˜์Šค

    // ํ…Œ์ŠคํŠธ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ๋ฉ”๋ชจ๋ฆฌ๋ฉค๋ฒ„ repo ๋งŒ๋“ค๊ณ  ๊ทธ๊ฑฐ๋ฅผ ๋ฉค๋ฒ„ repo์— ๋„ฃ๊ณ 
    // ๋ฉค๋ฒ„ repo๋ฅผ memberservice์— ๋„ฃ์–ด์ฃผ๋ฉด ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ๋ฉค๋ฒ„ repo ์‚ฌ์šฉ
    // = DI (dependency injection) ์˜์กด์„ฑ ์ฃผ์ž…
    @BeforeEach
    public void beforeEach() {
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }

 

* option + enter = ์ž๋™ import

* cmd + shift + enter = ๋ฐ”๋กœ ๋‚ด๋ ค๊ฐ€๊ธฐ

* shift + fn f6 = rename refactoring 

* cmd + option + V

memberRepository.findByName(member.getName()); // ์ด๊ฑฐ ํ•˜๊ณ  cmd + option + vํ•˜๋ฉด return ๊ฐ’ ์ €์žฅ
Optional<Member> result = memberRepository.findByName(member.getName());

* ctrl + T : refactoring ๊ด€๋ จ ๋‹จ์ถ•ํ‚ค -> method extract

* ctrl + shift + T : ํด๋ž˜์Šค์— ๋Œ€๊ณ  ํ•˜๋ฉด ํ•ด๋‹น ํด๋ž˜์Šค์— ๋Œ€ํ•œ test ์ƒ์„ฑ

* ctrl + R : ์ด์ „ Run ๋‹ค์‹œ ์‹คํ–‰ 

  • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
  • ๋„ค์ด๋ฒ„ ๋ฐด๋“œ์— ๊ณต์œ ํ•˜๊ธฐ
  • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
  • ์นด์นด์˜ค์Šคํ† ๋ฆฌ ๊ณต์œ ํ•˜๊ธฐ