<๋ชฉ์ฐจ>
01. ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ ์ ๋ฆฌ
02. ํ์ ๋๋ฉ์ธ๊ณผ ๋ ํฌ์งํ ๋ฆฌ ๋ง๋ค๊ธฐ
03. ํ์ ๋ ํฌ์งํ ๋ฆฌ ํ ์คํธ ์ผ์ด์ค ์์ฑ
04. ํ์ ์๋น์ค ๊ฐ๋ฐ
05. ํ์ ์๋น์ค ํ ์คํธ
01. ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ ์ ๋ฆฌ
- ๋ฐ์ดํฐ: ํ์ID, ์ด๋ฆ
- ๊ธฐ๋ฅ: ํ์ ๋ฑ๋ก, ์กฐํ
- ์์ง ๋ฐ์ดํฐ ์ ์ฅ์๊ฐ ์ ์ ๋์ง ์์(๊ฐ์์ ์๋๋ฆฌ์ค)
์ผ๋ฐ์ ์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ณ์ธต ๊ตฌ์กฐ
- ์ปจํธ๋กค๋ฌ : ์น MVC์ ์ปจํธ๋กค๋ฌ ์ญํ
- ์๋น์ค : ํต์ฌ ๋น์ฆ๋์ค ๋ก์ง ๊ตฌํ
- ๋ ํฌ์งํ ๋ฆฌ : ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผ, ๋๋ฉ์ธ ๊ฐ์ฒด๋ฅผ DB์ ์ ์ฅํ๊ณ ๊ด๋ฆฌ
- ๋๋ฉ์ธ : ๋น์ฆ๋์ค ๋๋ฉ์ธ ๊ฐ์ฒด (ex. ํ์, ์ฃผ๋ฌธ, ์ฟ ํฐ ๋ฑ -> ์ฃผ๋ก DB์ ์ ์ฅํ๊ณ ๊ด๋ฆฌ๋จ)
ํด๋์ค ์์กด๊ด๊ณ
- ์์ง ๋ฐ์ดํฐ ์ ์ฅ์๊ฐ ์ ์ ๋์ง ์์์, ์ฐ์ ์ธํฐํ์ด์ค๋ก ๊ตฌํ ํด๋์ค๋ฅผ ๋ณ๊ฒฝํ ์ ์๋๋ก ์ค๊ณ
- ๋ฐ์ดํฐ ์ ์ฅ์๋ RDB, NoSQL ๋ฑ๋ฑ ๋ค์ํ ์ ์ฅ์๋ฅผ ๊ณ ๋ฏผ์ค์ธ ์ํฉ์ผ๋ก ๊ฐ์
- ๊ฐ๋ฐ์ ์งํํ๊ธฐ ์ํด์ ์ด๊ธฐ ๊ฐ๋ฐ ๋จ๊ณ์์๋ ๊ตฌํ์ฒด๋ก ๊ฐ๋ฒผ์ด ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ์ ๋ฐ์ดํฐ ์ ์ฅ์ ์ฌ์ฉ
02. ํ์ ๋๋ฉ์ธ๊ณผ ๋ ํฌ์งํ ๋ฆฌ ์์ฑ
ํ์ ๊ฐ์ฒด์ ํ์ ๋ ํฌ์งํ ๋ฆฌ ์ธํฐํ์ด์ค, ๋ ํฌํฐ๋ก์ด ๋ฉ๋ชจ๋ฆฌ ๊ตฌํ์ฒด๋ฅผ ์์ฑํ๋ค.
ํ์ ๊ฐ์ฒด(domain)
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;
}
}
ํ์ ๋ ํฌ์งํ ๋ฆฌ ์ธํฐํ์ด์ค(repository)
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); // null๊ฐ ์์ ๊ฒฝ์ฐ optional๋ก ๊ฐ์ธ์ ๋ฐํ
Optional<Member> findByName(String name);
List<Member> findAll();
}
๋ฐํ๊ฐ์ผ๋ก null๊ฐ์ด ๊ฐ๋ฅํ ๊ฒฝ์ฐ Optional๋ก ๊ฐ์ธ์ฃผ๋ฉด ์ข๋ค.
ํ์ ๋ ํฌ์งํ ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๊ตฌํ์ฒด(repository)
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.*;
public class MemoryMemberRepository implements MemberRepository{
// ๋์์ฑ ๋ฌธ์ ๊ณ ๋ ค X
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L; // ์ํ์ค ๊ฐ ์์ฑ(1, 2, 3...)
@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)); // null๊ฐ ๋์ฌ ์ ์๋ ๊ฒฝ์ฐ Optional.ofNullable๋ก ๊ฐ์ธ๊ธฐ
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny(); // ํ๋๋ผ๋ ์ฐพ๊ธฐ(Optional๋ก ๋ฐํ
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
public void clearStore(){
store.clear();
}
}
- Optional.ofNullable()์ ์ฌ์ฉํ๋ฉด null๊ฐ์ด ๋์ฌ ์ ์๋ ๊ฐ์ฒด๋ฅผ ์ค๋ฅ์์ด ๋ฐํํ ์ ์๋ค.
- ํ์ฌ HashMap๊ณผ Long์ ์ฌ์ฉํ๋๋ฐ, ์ค๋ฌด์์๋ ๋์์ฑ ๋ฌธ์ ๋๋ฌธ์ ConcurrentHashMap๊ณผ AtomicLong์ ์ฌ์ฉํ๋ค.
+ ๋๋ค์ ๊น๋จน์ด์ ๊ธํ๊ฒ ์ ๋ฆฌ https://dev-minji.tistory.com/19
03. ํ์ ๋ ํฌ์งํ ๋ฆฌ ํ ์คํธ ์ผ์ด์ค ์์ฑ
๊ฐ๋ฐํ ๊ธฐ๋ฅ์ ์คํํด์ ํ ์คํธ ํ ๋ ์๋ฐ์ main ๋ฉ์๋๋ฅผ ํตํด์ ์คํํ๊ฑฐ๋, ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ปจํธ๋กค๋ฌ๋ฅผ ํตํด์ ํด๋น ๊ธฐ๋ฅ์ ์คํํ๋ค. ์ด๋ฌํ ๋ฐฉ๋ฒ์ ์ค๋นํ๊ณ ์คํํ๋๋ฐ ์ค๋ ๊ฑธ๋ฆฌ๊ณ , ๋ฐ๋ณต ์คํํ๊ธฐ ์ด๋ ต๊ณ ์ฌ๋ฌ ํ ์คํธ๋ฅผ ํ๋ฒ์ ์คํํ๊ธฐ ์ด๋ ต๋ค๋ ๋จ์ ์ด ์๋ค. ์๋ฐ๋ JUnit์ด๋ผ๋ ํ๋ ์์ํฌ๋ก ํ ์คํธ๋ฅผ ์คํํด์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
https://dev-minji.tistory.com/66
- ํ ์คํธ ์ผ์ด์ค์ ์ฅ์ ์ ํด๋์ค ๋จ์(๋ ๋ฒจ)์์ ์คํ๊ฐ๋ฅํ๋ค๋ ์ ์ด๋ค.
- hello.hellospring ํจํค์ง์์ ์คํํ๋ฉด ์ ์ฒด ํด๋์ค ํ ์คํธ ๊ฐ๋ฅ
- test๋ ์ธ๋ถ์์ ์ ๊ทผํ ํ์๊ฐ ์์ผ๋ฏ๋ก, public์ด ์๋์ด๋ ๊ด์ฐฎ๋ค.
ํ์ ๋ ํฌ์งํ ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๊ตฌํ์ฒด ํ ์คํธ
src/test/java ํ์ ํด๋์ ์์ฑํ๋ค.
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);
}
}
01. ํ ์คํธ๋ฅผ ํ ๋ GIVEN / WHEN / THEN ์ธ ๋ถ๋ถ์ผ๋ก ๋๋์ด ์งํํ๋ค
- given : ์ฃผ์ด์ง ๋ฐ์ดํฐ๊ฐ ๋ฌด์์ธ์ง
- when : ๊ฒ์ฆ ์กฐ๊ฑด์ด ๋ฌด์์ธ์ง
- then : ๋์์ผ ํ๋ ๊ฒฐ๊ณผ๊ฐ ๋ฌด์์ธ์ง
@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);
}
02. @AfterEach(์ฝ๋ฐฑ ๋ฉ์๋)
/* main/java/repository/MemoryMemberRepository.java */
public void clearStore(){
store.clear();
}
/* test/java/repository/MemoryMemberRepositoryTest.java */
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach() {
repository.clearStore();
}
ํ๋ฒ์ ์ฌ๋ฌ ํ ์คํธ๋ฅผ ์คํํ๋ฉด ๋ฉ๋ชจ๋ฆฌ DB์ ์ง์ ํ ์คํธ์ ๊ฒฐ๊ณผ๊ฐ ๋จ์ ์ ์๋ค. ์ด๋ ๊ฒ ๋๋ฉด ๋ค์ ์ด์ ํ ์คํธ ๋๋ฌธ์ ๋ค์ ํ ์คํธ๊ฐ ์คํจํ ๊ฐ๋ฅ์ฑ์ด ์๋ค. @AfterEach ๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ ํ ์คํธ๊ฐ ์ข ๋ฃ๋ ๋ ๋ง๋ค ์ด ๊ธฐ๋ฅ์ ์คํํ๋ค. ์ฌ๊ธฐ์๋ ๋ฉ๋ชจ๋ฆฌ DB์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ค
03. ํ ์คํธ๋ ๊ฐ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋์ด์ผ ํ๋ค.
ํ ์คํธ ์์์ ์์กด๊ด๊ณ๊ฐ ์๋ ๊ฒ์ ์ข์ ํ ์คํธ๊ฐ ์๋๋ค.
๋๊ธ