SPRING

[์ธํ”„๋Ÿฐ/SPRING] ํšŒ์›๊ด€๋ฆฌํ”„๋กœ๊ทธ๋žจ - ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ Optional<T>/stream().Filter/findAny()/@AfterEach

merryna 2022. 8. 26. 22:10
๋ฐ˜์‘ํ˜•

๐Ÿ‘ฉํšŒ์› ๊ฐ์ฒด

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

๐Ÿ‘ฉํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค

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

 

๐Ÿ‘ฉํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌํ˜„์ฒด

 

package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.*;
/**
 * ๋™์‹œ์„ฑ ๋ฌธ์ œ๊ฐ€ ๊ณ ๋ ค๋˜์–ด ์žˆ์ง€ ์•Š์Œ, ์‹ค๋ฌด์—์„œ๋Š” ConcurrentHashMap, AtomicLong ์‚ฌ์šฉ ๊ณ ๋ ค
 */
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);
         store.put(member.getId(), member);
         return member;
     }
     
     @Override
     public Optional<Member> findById(Long id) {
     	return Optional.ofNullable(store.get(id));
     }
     
     @Override
     public List<Member> findAll() {
     	return new ArrayList<>(store.values());
     }
     
     @Override
     public Optional<Member> findByName(String name) {
         return store.values().stream()
         			.filter(member -> member.getName().equals(name))
         			.findAny();
     }
     
     public void clearStore() {
     	store.clear();
     }
}

 

๐ŸŽˆ๐ŸŽˆ๋™์‹œ์„ฑ ๋ฌธ์ œ : ConcurrentHashMap, AtomicLong

 

๐ŸŽˆ๐ŸŽˆOptional<T>

: null์ด ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ๊ฐ์‹ธ๋Š” Wrapper ํด๋ž˜์Šค.  NPE(NullPointerException)๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋„์™€์ค€๋‹ค.

 

๐ŸŽˆ๐ŸŽˆstream() 

: ์ŠคํŠธ๋ฆผ(Streams)์€ ๋žŒ๋‹ค๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ์ˆ  ์ค‘ ํ•˜๋‚˜.

 

-๋ฐฐ์—ด ๋˜๋Š” ์ปฌ๋ ‰์…˜ ์ธ์Šคํ„ด์Šค์— ํ•˜๋‚˜ ์ด์ƒ์˜ ํ•จ์ˆ˜๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„ํ„ฐ๋ง ๋ฐ ๊ฐ€๊ณต

-๋žŒ๋‹ค์‹ ํ™œ์šฉ > ๊ฐ„๊ฒฐ์„ฑ

-ํ•จ์ˆ˜ํ˜•์œผ๋กœ ์ฒ˜๋ฆฌ

 

- Filter

- findFirst() vs findAny()

 

1. Stream์„ ์ง๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•  ๋•Œ ์ฐจ์ด์  X

2. Stream์„ ๋ณ‘๋ ฌ(parallel())๋กœ ์ฒ˜๋ฆฌํ•  ๋•Œ

findFirst() : ์—ฌ๋Ÿฌ ์š”์†Œ๊ฐ€ ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•ด๋„ Stream์˜ ๊ฐ€์žฅ ์•ž์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๋ฆฌํ„ด

findAny() : Multi thread์—์„œ Stream์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ์ฐพ์€ ์š”์†Œ๋ฅผ ๋ฆฌํ„ด

 @Override
 public Optional<Member> findByName(String name) {
     return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
 }

์ด ์ž…๋ฌธ ์ฝ”๋“œ์—๋„ ๋ฐฐ์šธ๊ฒŒ ์ฐธ ๋งŽ๋‹ค..!


๐Ÿง›‍โ™‚๏ธํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ

package 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();
         member2.setName("spring2");
         repository.save(member2);
         //when
         Member result = repository.findByName("spring1").get();
         //then
         assertThat(result).isEqualTo(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);
     }
}

๐ŸŽˆ๐ŸŽˆ์ธํ…”๋ฆฌ์ œ์ด ๊ฟ€ํŒ shift+f6 ์ด๋ฆ„ ํ•œ๋ฒˆ์— ๋ฐ”๊พธ๊ธฐ

 

๐ŸŽˆ๐ŸŽˆ@AfterEach : ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ๋งˆ๋‹ค ์ด ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋ฉ”๋ชจ๋ฆฌ DB์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•œ๋‹ค. 

 

ํ…Œ์ŠคํŠธ๋Š” ๊ฐ๊ฐ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค. ํ…Œ์ŠคํŠธ ์ˆœ์„œ์— ์˜์กด๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ๊ฒƒ์€ ์ข‹์€ ํ…Œ์ŠคํŠธ๊ฐ€ ์•„๋‹ˆ๋‹ค

 

๐ŸŽˆ๐ŸŽˆRepository๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์„ค๊ณ„ : MemberRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ตฌํ˜„์ฒด์˜ ๋ณ€๊ฒฝ์ด ์‰ฝ๋‹ค.

 

Q. ์ž๋ฃŒํ˜• ๋ณ€๊ฒฝํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? (MemberRepository > MemoryMemberRepository)

A. MemberRepository๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ •์˜๋œ ๋ฉ”์†Œ๋“œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ์š”. ์ถ”๊ฐ€ํ•œ ๋ฉ”์†Œ๋“œ์ธ clearStore()๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‹Œ ์ด๊ฒƒ์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์— ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฐพ์ง€ ๋ชปํ•ด์„œ MemoryMemberRepository ํด๋ž˜์Šค๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ๋ฐ”๊ฟ”์ค€ ๊ฑฐ์—์š”.

(๋‹ต๋ณ€ ์ถœ์ฒ˜)

 

 

 

์ถœ์ฒ˜ : ์Šคํ”„๋ง ์ž…๋ฌธ - ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ, ์›น MVC, DB ์ ‘๊ทผ ๊ธฐ์ˆ 

๋ฐ˜์‘ํ˜•