Spring ์ ๋ฌธ / 3. ํ์ ๊ด๋ฆฌ ์์ - ๋ฐฑ์๋ ๊ฐ๋ฐ
by rlaehddnd04221. ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ ์ ๋ฆฌ
๋ฐ์ดํฐ : ID, name
๊ธฐ๋ฅ : ๋ฑ๋ก ๋ฐ ์กฐํ
์ ์ : DB๋ ์ค์ ๋์ง ์์.
- ์ผ๋ฐ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ตฌ์กฐ
1. ์ปจํธ๋กค๋ฌ : ์น MVC์ ์ปจํธ๋กค๋ฌ ์ญํ
2. ์๋น์ค : ํต์ฌ ๋น์ฆ๋์ค ๋ก์ง ๊ตฌํ
3. ๋ฆฌํฌ์งํ ๋ฆฌ : DB์ ์ ๊ทผ, ๋๋ฉ์ธ ๊ฐ์ฒด๋ฅผ DB์ ์ ์ฅ ๋ฐ ๊ด๋ฆฌ
4. ๋๋ฉ์ธ : ๋น์ฆ๋์ค ๋๋ฉ์ธ ๊ฐ์ฒด
ex) ํ์, ์ฃผ๋ฌธ, ์ฟ ํฐ ๋ฑ๋ฑ ์ฃผ๋ก DB์ ์ ์ฅํ๊ณ ๊ด๋ฆฌ๋จ.
- ํด๋์ค ์์กด๊ด๊ณ
- DB๊ฐ ์ ์ ๋์ง ์์ ์ํฉ์ด๋ผ ์ฐ์ ์ธํฐํ์ด์ค๋ก ๊ตฌํ ํด๋์ค๋ฅผ ๋ณ๊ฒฝํ ์ ์๋๋ก ์ค๊ณ
- ๋ฐ์ดํฐ ์ ์ฅ์(DB)๋ RDB, NoSQL ๋ฑ๋ฑ ๋ค์ํ ์ ์ฅ์๊ฐ ์์ง๋ง ๊ณ ๋ฏผ์ค์ธ ์ํฉ
- ๊ฐ๋ฐ์งํ์ ์ํด์ ์ด๊ธฐ ๊ฐ๋ฐ ๋จ๊ณ์์๋ ๊ตฌํ์ฒด๋ก ๊ฐ๋ฒผ์ด ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ์ ๋ฐ์ดํฐ ์ ์ฅ์ ์ฌ์ฉ
2. ํ์ ๋๋ฉ์ธ๊ณผ Repository ์์ฑ
- ํ์ ๊ฐ์ฒด(๋๋ฉ์ธ) ์์ฑ
package kdo6301.spring0.domain;
public class Member {
private Long id;
private String name;
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
- ํ์ ๋ฆฌํฌ์งํ ๋ฆฌ ์ธํฐํ์ด์ค
์ ์ฅํ๊ธฐ ์ํ save ๋ฉ์๋, ๊ฒ์์ ์ํ findBy ๋ฉ์๋ ์ ์ธ
package kdo6301.spring0.repository;
import kdo6301.spring0.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();
}
โ๏ธ Optional์ด๋?
๊ฐ๋ฐ์ ํ ๋ ๊ฐ์ฅ ๋ง์ด ๋ฐ์ํ๋ ์์ธ ์ค ํ๋์ธ Null Pointer Exception ( NPE ) ๋ฅผ ํผํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ฌธ๋ฒ
Optional <T> ๋ null๊ฐ์ด ์ฌ ์ ์๋ ๊ฐ์ ๊ฐ์ธ๋ Wrapper ํด๋์ค๋ก , null์ด ๋ฐ์ ํ๋๋ผ๋ NPE๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋์์ค๋ค.
- ํ์ ๋ฆฌํฌ์งํ ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๊ตฌํ์ฒด
package kdo6301.spring0.repository;
import kdo6301.spring0.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));
store.put(member.getId(),member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
// store์ ํด๋นํ๋ id๊ฐ์ด ์์ผ๋ฉด ๋น ๊ฐ์ฒด ๋ฆฌํด
// ์์ผ๋ฉฐ ํด๋น ๊ฐ์ฒด ์์ฑํ์ฌ ๋ฆฌํด
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
public void clearStore()
{
store.clear();
}
}
- Map Collection
/ key, value๋ฅผ ์์ผ๋ก ๊ตฌ์ฑ๋๋ ์์๋ฅผ ๋ค๋ฃจ๋ ์ปฌ๋ ์
/ key๋ฅผ ํตํด value๋ฅผ ์ป์ด๋ธ๋ค.
/ ์ฝ์ : get() ๋ฉ์๋
/ ๊ฒ์ : put() ๋ฉ์๋
- ArrayList Collection
/ C++์ vector์ ๊ฐ์ด ๋ฐฐ์ด์ ํฌ๊ธฐ๊ฐ ๊ฐ๋ณ์ ์ผ๋ก ๋ณํจ
- HashMap Collection
/ Map Collection class์ ์ํ๋ ํด๋์ค
/ HashMap์ Map์ ๊ตฌํํ๋ค. key์ value๋ฅผ ๋ฌถ์ด ํ๋์ entry๋ก ์ ์ฅํ๋ค๋ ํน์ง์ ๊ฐ์ง
/ ๋ง์ฐฌ๊ฐ์ง๋ก key์ value์ ์์ผ๋ก ๊ตฌ์ฑ๋๋ ์์๋ฅผ ๋ค๋ฃจ๋ ์ปฌ๋ ์
/ ๋ง์ฐฌ๊ฐ์ง๋ก value๋ฅผ ๊ฒ์ํ๊ธฐ ์ํด์ key๋ฅผ ์ด์ฉ
/ ์ฝ์ : get() ๋ฉ์๋
/ ๊ฒ์ : put() ๋ฉ์๋
/ ํด์ ์๊ณ ๋ฆฌ์ฆ(hash algorithm)์ ์ฌ์ฉํ์ฌ ๋ง์ ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๋๋ฐ ๊ฒ์ ์๋๊ฐ ๋งค์ฐ ๋น ๋ฅด๋ค.
- ofNullable() method
of()๋ ofNullable() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ Optional ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค.
of() ๋ฉ์๋๋ null์ด ์๋ ๋ช ์๋ ๊ฐ์ ์ง๋๋ Optional ๊ฐ์ฒด๋ฅผ ๋ฆฌํด
-> of() ๋ฉ์๋๋ฅผ ํตํด ์์ฑ๋ ๊ฐ์ฒด์ null์ด ์ ์ฅ๋๋ฉด NPE ๋ฐ์
ofNullable() ๋ฉ์๋๋ ๋ช ์๋ ๊ฐ์ด null์ด ์๋๋ฉด ๋ช ์๋ ๊ฐ์ ๊ฐ์ง๋ Optional ๊ฐ์ฒด๋ฅผ ๋ฆฌํด,
๋ช ์๋ ๊ฐ์ด null์ด๋ฉด ๋น์ด์๋ Optional ๊ฐ์ฒด๋ฅผ ๋ฆฌํด
- stream / filter
stream์ ์ปฌ๋ ์ ์ ์ ์ฅ๋์ด ์๋ ์์๋ค์ ํ๋์ฉ ์ฐธ์กฐํ์ฌ ๋๋ค์์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋๋ก ํด์ฃผ๋ iterator
๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ์์ฑ ๊ฐ๋ฅํ๊ณ , inner iterator๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ณ๋ ฌ ์ฒ๋ฆฌ๊ฐ ์ฝ๋ค๊ณ ํ๋ค.
3. ํ์ Repository Test Case ์์ฑ
๊ฐ๋ฐํ ๊ธฐ๋ฅ์ ์คํํด์ ํ ์คํธ ํ ๋ ์๋ฐ์ main ๋ฉ์๋๋ฅผ ํตํด์ ์คํํ๊ฑฐ๋, ์ปจํธ๋กค๋ฌ๋ฅผ ํตํด์ ํด๋น ๊ธฐ๋ฅ์ ์คํํ๊ธฐ์๋ ์คํํ๋ ๋ฐ
์ค๋ ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ ํ ์คํธ๋ฅผ ํ๋ฒ์ ์คํํ๊ธฐ ์ด๋ ต๋ค๋ ๋จ์ ์ด ์๋ค.
์๋ฐ๋ JUnit์ด๋ผ๋ ํ๋ ์์ํฌ ํ ์คํธ๋ฅผ ์คํํด์ ์ด๋ฌํ ๋จ์ ์ ํด๊ฒฐํ๋ค.
- ํ์ ๋ฆฌํฌ์งํ ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๊ตฌํ์ฒด ํ ์คํธ
import kdo6301.spring0.domain.Member;
import kdo6301.spring0.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.assertj.core.api.Assertions;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
public class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach()
{
repository.clearStore();
}
@Test
public void save()
{
//given
Member member = new Member();
member.setName("spring1");
//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);
}
}
โ๏ธ @AfterEach
: ํ๋ฒ์ ์ฌ๋ฌ ๋ฉ์๋์ ํ ์คํธ๋ฅผ ์คํด์๋ฉด ๋ฉ๋ชจ๋ฆฌ DB์ ์ง์ ํ ์คํธ์ ๊ฒฐ๊ณผ๊ฐ ๋จ์ ์ ์๋ค.
์ด๋ ๊ฒ ๊ฒฐ๊ณผ๊ฐ ๋จ๊ฒ ๋๋ฉด ์ด์ ํ ์คํธ๊ฐ ๋ค์ ํ ์คํธ์ ์ํฅ์ ์ฃผ์ด์ ์คํจํ ๊ฐ๋ฅ์ฑ์ด ์๋ค.
AfterEach ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ๊ฐ ํ ์คํธ๊ฐ ์ข ๋ฃ๋ ๋ ๋ง๋ค ์ด ๊ธฐ๋ฅ์ ์คํํ๋๋ฐ, ๊ฐ ํ ์คํธ๊ฐ ๋๋๋ฉด store๋ฅผ ๋น์ฐ๋๋ก ์ค์ ํด ์ฃผ์๋ค.
โ๏ธโ๏ธ ํ ์คํธ๋ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋์ด์ผ ํ๋ค. ์์กด๊ด๊ณ๊ฐ ์๋ ํ ์คํธ๋ ์ข์ ํ ์คํธ๊ฐ ์๋.
4. ํ์ ์๋น์ค ๊ฐ๋ฐ
package kdo6301.spring0.service;
import kdo6301.spring0.domain.Member;
import kdo6301.spring0.repository.MemberRepository;
import kdo6301.spring0.repository.MemoryMemberRepository;
import java.util.List;
import java.util.Optional;
public class MemberService {
/*
private final MemoryMemberRepository memberRepository = new MemoryMemberRepository();
๋ก ์์ฑํ๋ฉด
ํด๋น ์ธํฐํ์ด์ค ๊ตฌํ ๊ฐ์ฒด๋ง ์ฌ์ฉํ ์ ์์ง๋ง,
private final MemberRepository memberRepository = new MemoryMemberRepository();
์ด๋ ๊ฒ ์์ฑํ๋ฉด ์ค๋ฅธ์ชฝ์ MemberRepository ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๋ค๋ฅธ ํด๋์ค๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค.
*/
private final MemberRepository memberRepository = new MemoryMemberRepository();
/*
ํ์๊ฐ์
*/
public Long join(Member member)
{
validateDuplicateMember(member); // ์ค๋ณตํ์ ๊ฒ์ฆ
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member)
{
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. ํ์ ์๋น์ค ํ ์คํธ
๊ธฐ์กด์๋ ํ์ ์๋น์ค ( MemberService ) ๊ฐ MemoryMemberRepository๋ฅผ ์ง์ ์์ฑํ๊ฒ ํด์ฃผ์๋ค.
public class MemberService {
private final MemberRepository memberRepository =
new MemoryMemberRepository();
}
*ํ์ ๋ฆฌํฌ์งํ ๋ฆฌ์ ์ฝ๋๊ฐ
ํ์ ์๋น์ค ์ฝ๋๋ฅผ DI ๊ฐ๋ฅํ๊ฒ ๋ณ๊ฒฝํ๋ค.
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
... }
}
package kdo6301.spring0.service;
import kdo6301.spring0.domain.Member;
import kdo6301.spring0.repository.MemberRepository;
import kdo6301.spring0.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 java.util.Optional;
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
void join() {
//given
Member member = new Member();
member.setName("Kim");
//when
Long saveId = memberService.join(member);
//then
Member One = memberService.findOne(saveId).get();
Assertions.assertThat(member.getName()).isEqualTo(One.getName());
}
@Test
void ์ค๋ณตํ์์์ธ()
{
// given
Member mem1 = new Member();
mem1.setName("Spring1");
Member mem2 = new Member();
mem2.setName("Spring1");
// when
memberService.join(mem1);
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(mem2));
Assertions.assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์ฌํ๋ ํ์์
๋๋ค.");
// try
// {
// memberService.join(mem2);
// fail();
// }catch(IllegalStateException e){
// Assertions.assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์ฌํ๋ ํ์์
๋๋ค.");
// }
// then
}
}
โ๏ธ@BeforeEach : ๊ฐ ํ ์คํธ ์คํ ์ ์ ํธ์ถ๋๋ค. ํ ์คํธ๊ฐ ์๋ก ์ํฅ์ด ์๋๋ก ํญ์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์์กด๊ด๊ณ๋ ์๋ก ๋งบ์ด์ค๋ค.
-> @AfterEach ์์จ์ฃผ์ด๋ ๋จ.
<์ฐธ๊ณ ์๋ฃ>
[๋ฌด๋ฃ] ์คํ๋ง ์ ๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์ - ์ธํ๋ฐ | ๊ฐ์
์คํ๋ง ์ ๋ฌธ์๊ฐ ์์ ๋ฅผ ๋ง๋ค์ด๊ฐ๋ฉด์ ์คํ๋ง ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ์ ๋ฐ์ ๋น ๋ฅด๊ฒ ํ์ตํ ์ ์์ต๋๋ค., - ๊ฐ์ ์๊ฐ | ์ธํ๋ฐ...
www.inflearn.com
https://mangkyu.tistory.com/70
[Java] Optional์ด๋? Optional ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ - (1/2)
์ด๋ฒ์๋ Java8๋ถํฐ ์ง์ํ๋ Optional ํด๋์ค์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. 1. Optional์ด๋? Optional ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ [ NPE(NullPointerException) ์ด๋? ] ๊ฐ๋ฐ์ ํ ๋ ๊ฐ์ฅ ๋ง์ด ๋ฐ์ํ๋ ์์ธ ์ค ํ๋๊ฐ ๋ฐ
mangkyu.tistory.com
[์๋ฐ ๊ธฐ๋ณธ ๊ฐ๋ ] ์ปฌ๋ ์ (Collection) - HashMap / ์์
1.4 HashMap-ํค(key)์ ๊ฐ(value)์ ์์ผ๋ก ๊ตฌ์ฑ๋๋ ์์๋ฅผ ๋ค๋ฃจ๋ ์ปฌ๋ ์ -๊ฐ์ ๊ฒ์ํ๊ธฐ ์ํด์๋ ๋ฐ๋์ ํค ์ด์ฉ-์์ ์ฝ์ : get() ๋ฉ์๋-์์ ๊ฒ์ : put() ๋ฉ์๋ public class _04HashMapDicEx { public static vo
mkil.tistory.com
https://devlogofchris.tistory.com/41
[JAVA]Map์ด๋? (HashMap, Hashtable, TreeMap)
Map ์ปฌ๋ ์ ํด๋์ค Map ์ธํฐํ์ด์ค๋ Collection ์ธํฐํ์ด์ค์๋ ๋ค๋ฅธ ์ ์ฅ ๋ฐฉ์์ ๊ฐ์ง๋๋ค. Map ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ Map ์ปฌ๋ ์ ํด๋์ค๋ค์ ํค์ ๊ฐ์ ํ๋์ ์์ผ๋ก ์ ์ฅํ๋ ๋ฐฉ์(key-value ๋ฐฉ์)์
devlogofchris.tistory.com
https://psychoria.tistory.com/765
[Java] ์๋ฐ ArrayList ์ฌ์ฉ ๋ฐฉ๋ฒ
ArrayList๋ ์๋ฐ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ง์ด ์ฌ์ฉ๋๋ ํด๋์ค์ ๋๋ค. ArrayList๋ ์๋ฐ์ List ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ์ ์ฌ๋ฌ ํด๋์ค ์ค ํ๋์ ๋๋ค. ์ผ๋ฐ ๋ฐฐ์ด๊ณผ ๋์ผํ๊ฒ ์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฌ์ฉํ๋ฉฐ ์ธ
psychoria.tistory.com
[Java] ์คํธ๋ฆผ(Stream) ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ / filter, map / iterator ๋น๊ต
[Java] Stream - ์๋ฐ ์คํธ๋ฆผ ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ ๐ก ์๋ฐ ์คํธ๋ฆผ (Stream ) ์๋ฐ์ ์คํธ๋ฆผ(Stream)์ Java 8์ ์ถ๊ฐ๋ ๊ธฐ๋ฅ์ด๋ค. ์ปฌ๋ ์ ์ ์ ์ฅ๋์ด ์๋ ์์๋ค์ ํ๋์ฉ ์ฐธ์กฐํ์ฌ ๋๋ค์์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋
devmoony.tistory.com
'๐ Backend' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring ์ ๋ฌธ / 6. DB ์ ๊ทผ ๊ธฐ์ (0) | 2023.01.19 |
---|---|
Spring ์ ๋ฌธ / 5. ํ์ ๊ด๋ฆฌ ์์ - ์น MVC ๊ฐ๋ฐ (1) | 2023.01.17 |
Spring ์ ๋ฌธ / 4. ์คํ๋ง ๋น๊ณผ ์์กด๊ด๊ณ (0) | 2023.01.17 |
Spring ์ ๋ฌธ / 2. Spring Web ๊ฐ๋ฐ ๊ธฐ์ด (0) | 2023.01.12 |
Spring ์ ๋ฌธ / 1. ํ๋ก์ ํธ ํ๊ฒฝ์ค์ (0) | 2023.01.12 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422