๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring๐Ÿƒ/๊น€์˜ํ•œ์˜ ์Šคํ”„๋ง ์™„์ „์ •๋ณต

์Šคํ”„๋ง ์ž…๋ฌธ ๊ฐ•์˜ ๋…ธํŠธ ์ •๋ฆฌ (2) : ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ - ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ

728x90

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

์„œ๋น„์Šค : ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ตฌํ˜„

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

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

 

๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์„ค์ •ํ•œ ์ด์œ  : DB์— ๋Œ€ํ•œ ์„ ํƒ์„ ์•„์ง ํ•˜์ง€ ์•Š์•„ DB์— ๋”ฐ๋ผ ๊ตฌํ˜„์ฒด๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋งŒ๋“ ๋‹ค.

 

์‹ค์Šต ์š”๊ตฌ์‚ฌํ•ญ

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

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

์•„์ง ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ๊ฐ€ ์„ ์ •๋˜์ง€ ์•Š์€ ์‹œ์ 

 

๋„๋ฉ”์ธ๊ณผ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๋งŒ๋“ค๊ธฐ

1) Domian - Member

package hello.helloSpring.domain;

public class Member {

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

2) MemberRepository

package hello.helloSpring.repository;

import hello.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);
    List<Member> findAll();
}

3) MemoryMemerRepository

package hello.helloSpring.repository;

import hello.helloSpring.domain.Member;

import java.util.*;

public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long, Member> store = new HashMap<>();
    private static long sequence = 0L;

    @Override
    public Member save(Member member) { // ๋ฉค๋ฒ„ ๊ฐ์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๊ณ 
        member.setId(++sequence); // id๊ฐ’์„ ์ฆ๊ฐ€
        store.put(member.getId(), member); // store์— ์ €์žฅ
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
        // Optional ~ Null๊ฐ’์ด์–ด๋„ Optional ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๊ณ , ๊ทธ ๊ฒƒ์„ ๋ฐ”ํƒ•์œผ๋กœ
        // ์‚ฌ์šฉ์ž์˜ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•˜๋‹ค
    }

    @Override
    public Optional<Member> findByname(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                // ๋ฉค๋ฒ„์— ์ €์žฅ๋œ ์ด๋ฆ„์ด ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋“ค์–ด์˜จ ์ด๋ฆ„๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋งŒ filtering
                .findAny();
                // ํ•˜๋‚˜๋ผ๋„ ๊ฐ’์„ ์ฐพ์œผ๋ฉด Optional ํƒ€์ž…์— ์ €์žฅํ•˜์—ฌ ๋ฐ˜ํ™˜, ํ•˜๋‚˜๋„ ์—†๋‹ค๋ฉด null์„ ๋‹ด์•„ ๋ฐ˜ํ™˜
    }

    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());
        // store.values ~ member๋ฅผ ๋ฆฌ์ŠคํŠธ์— ์ €์žฅํ•˜๊ณ  ๊ทธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ˜•์‹
    }
    
	public void clearStore() {
    	store.clear();
 }
}

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

Junit ํ”„๋ ˆ์ž„์›Œํฌ ์‚ฌ์šฉ

 

Assertions ํด๋ž˜์Šค์˜ assert๋ฌธ์„ ํ†ตํ•ด ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค

*๋ชจ๋“  ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋Š” ์ˆœ์„œ์™€ ์ƒ๊ด€์—†์ด ์ž˜ ์ž‘๋™ํ•ด์•ผํ•œ๋‹ค(์„œ๋กœ ๊ฐ„ ์ˆœ์„œ์— ์˜์กด์„ฑ์ด ์—†์–ด์•ผ ํ•œ๋‹ค)

-> ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜๊ณ  ๋‚˜๋ฉด Clear๋ฅผ ํ•ด์•ผํ•œ๋‹ค : @AfterEach ํด๋ฆฌ์–ด ๋งค์†Œ๋“œ ์ž‘์„ฑํ•  ๊ฒƒ ~ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ, ๋ณธ ์ฝ”๋“œ ๋ชจ๋‘

pakage hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

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

import static org.assertj.core.api.Assertions.*;

class MemoryMemberRepositoryTest {

	MemoryMemberRepository repository = new MemoryMemberRepository();
    
    @AfterEach
    public void afterEach() {
    	repository.clearStore();
    }
    
    @Test
    public void save() {
    	// given
        Member member = new Member();
        member.setName("spring");
        
        // when
        repository.save(member);
        
        // then
        Member result = repository.findById(member.getId()).get();
        assertThat(result).isEqualTo(member);
    }
    
    @Test
    public void findByName() {
    	// given
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);
        
        Member member2 = new Member();
        memeber2.setName("spring2");
        repository.save(member2);
        
        // when
        Member result = repository.findByName("spring1").get();
        
        // then
        assertThat(result).isEquals(member1);
    }
    
    @Test
    public void findAll() {
    	// given
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);
        
        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);
        
        // when
        List<Member> result = repository.findAll();
        
        // then
        assertThat(result.size()).isEqualTo(2);
    }
    
}

 

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

์˜ต์…”๋„ ํด๋ž˜์Šค : ๋‹ค์–‘ํ•œ ํƒ€์ž…์„ ์˜ต์…”๋„ ํด๋ž˜์Šค๋กœ ํ•œ๋ฒˆ ๊ฐ์ŒŒ๊ธฐ ๋•Œ๋ฌธ์—, ์˜ต์…”๋„ ํด๋ž˜์Šค์˜ ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

ex) ifPresent(x-> { throw new IllegalArgumentException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค");}); ~ ์˜ˆ์™ธ์ฒ˜๋ฆฌ

+ get().orElseGet()๋„ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค

-> ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋Šฅ์„ ๊ฐ€๋Šฅํ•œ ์ถ•์†Œ์‹œํ‚จ๋‹ค ~ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋กœ ๊ธฐ๋Šฅ์„ ๋…๋ฆฝ์‹œํ‚จ๋‹ค : ๋ฆฌํŒฉํ† ๋ง - ๋ฉ”์„œ๋“œ ์ถ”์ถœ ํ™œ์šฉ

-> ์„œ๋น„์Šค๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œ๊ธฐํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค ~ ๊ทธ๋ž˜์•ผ ์œ ์ง€๋ณด์ˆ˜ ๊ฐ„ ๋งคํ•‘์ด ํ›จ์”ฌ ์‰ฝ๋‹ค

(๋ ˆํฌ์ง€ํ† ๋ฆฌ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋ณด๋‹ค๋Š” SQL ์ฟผ๋ฆฌ ๋“ฑ, ๊ฐœ๋ฐœ ์šฉ์–ด์— ๊ฐ€๊น๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค)

package hello.helloSpring.service;

import hello.helloSpring.domain.Member;
import hello.helloSpring.repository.MemoryMemberRepository;

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

public class MemberService {

    private final MemoryMemberRepository repository = new MemoryMemberRepository();

    public Long join(Member member) {
        vaildateDuplicateMember(member);
       	
        repository.save(member);
        return member.getId();
    }

    private void vaildateDuplicateMember(Member member) {
        // ์ค‘๋ณต ํšŒ์› ๊ธˆ์ง€
        repository.findByname(member.getName())
            .ifPresent(m ->{ // ์˜ต์…”๋„๋กœ ํ•œ๋ฒˆ ๊ฐ์ŒŒ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ๊ฐ€๋Šฅ
            throw new IllegalArgumentException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค");
        });
        // get().orElseGet()๋„ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค
        // ๊ธฐ๋Šฅ์„ ๊ฐ€๋Šฅํ•œ ์ถ•์†Œ์‹œํ‚จ๋‹ค : ๋ฉ”์„œ๋“œ๋กœ ๋…๋ฆฝ์‹œํ‚จ๋‹ค
    }

    public List<Member> findMembers() {
        return repository.findAll();
    }

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

 

ํšŒ์› ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ

*ํ•„๋“œ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋™์ผํ•œ ํด๋ž˜์Šค ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ ํ…Œ์ŠคํŠธ ๋“ฑ์—์„œ ๋งค๋ฒˆ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ!

~ ๊ฐ’์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜๋„ ์žˆ๋‹ค

-> ๊ทธ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์„ ์–ธํ•˜๊ณ  ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ์“ฐ๋Š” ๊ฒƒ์ด DI, IoC.

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemoryMemberRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

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

class MemberServiceTest {
	MemberService memberService;
    MemoryMemberRepository memberRepository;
	
    @BeforeEach
    public void beforeEach() {
    	memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }
 
 	@AfterEach
 	public void afterEach() {
    	memberRepository.clearStore();
 	}
    
 	@Test
 	public void ํšŒ์›๊ฐ€์ž…() throws Exception {
 		//Given
 		Member member = new Member();
 		member.setName("hello");
 		
        //When
 		Long saveId = memberService.join(member);
 		
        //Then
 		Member findMember = memberRepository.findById(saveId).get();
 		assertEquals(member.getName(), findMember.getName());
 	}
 
 	@Test
 	public void ์ค‘๋ณต_ํšŒ์›_์˜ˆ์™ธ() throws Exception {
 		//Given
 		Member member1 = new Member();
 		member1.setName("spring");
 		
        Member member2 = new Member();
 		member2.setName("spring");
 
 		//When
 		memberService.join(member1);
 		IllegalStateException e = assertThrows(IllegalStateException.class, 
        () -> memberService.join(member2));//์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค.
 		assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");
 	}
}
728x90