비즈니스 요구사항 정리
➡️ 데이터 : 회원ID, 이름
➡️ 기능 : 회원 등록, 조회
➡️ 아직 데이터 저장소가 선성되지 않음 (가상의 시나리오)

➡️ 컨트롤러 : 웹 MVC의 컨트롤러 역할
➡️ 서비스 : 핵심 비즈니스 로직 구현 ( ex: 회원은 중복가입이 안됨 등)
➡️ 리포지토리 : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
➡️ 도메인 : 비즈니스 도메인 객체 (ex : 회원, 주문, 쿠폰 등등 주로 데이터베이스에 저장하고 관리됨)

➡️ 아직 데이터 저장소가 선정되지 않았기 때문에 인터페이스로 구현 > 클래스 변경 가능하게 설계
➡️ 데이터 저장소는 RDB, NoSQL 등등 다양한 저장소를 고민중인 상황으로 가정
➡️ 개발을 진행하기 위해서 초기 개발 단계에서는 구현체로 가벼운 메모리 기반의 데이터 저장소 사용
회원 도메인과 리포지토리 만들기

package hello.hello_spring.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.hello_spring.repository;
import hello.hello_spring.domain.Member;
import java.util.List;
import java.util.Optional;
public interface MemberRepository {
Member save(Member member); //회원 저장 후 회원 반환
Optional<Member> findById(Long id); //저장소에서 id로 검색
Optional<Member> findByName(String name); //저장소에서 name으로 검색
List<Member> findAll(); //모든 회원 리스트 반환
}
➡️ 회원 리포지토리 인터페이스 생성
package hello.hello_spring.repository;
import hello.hello_spring.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); // sequence 하나씩 올리면서 id 부여
store.put(member.getId(), member); // store에 저장
return member; // 해당 member 리턴
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id)); //Optional 기능 이용해 null이 나와도 가능하게 저장소에서 회원 가져옴
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny(); // 파라미터의 name과 같은 member를 반환
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values()); //리스트형식으로 모든 member 리턴
}
public void clearStore(){
store.clear();
}
}
➡️ 회원 리포지토리 생성
회원 리포지토리 테스트 케이스 작성
➡️ 개발한 기능을 테스트 해보고 싶을 때 main메서드나 컨트롤러를 통해 해당 기능을 실행
➡️ 위의 방법은 시간이 오래걸리고 여러 테스트를 한번에 실행하기 어렵다는 단점.
➡️ JUnit이라는 프레임워크를 사용해 테스트를 실행하여 이러한 문제 해결 가능




package hello.hello_spring.repository;
import hello.hello_spring.domain.Member;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class MemorymemberRepositoryTest {
MemberRepository repository = new MemoryMemberRepository();
@Test
public void save(){
Member member = new Member();
member.setName("spring");
repository.save(member);
Member result = repository.findById(member.getId()).get();
Assertions.assertEquals(result, member); //둘이 같은 객체인지 확인
}
}
Assertions.assertThat(member).isEqualTo(result); // 같은 객체인지 확인
➡️save() test
➡️같은 객체인지 확인하는 두가지 방법 ( assertEquals / aseertThat.isEqualTo )
@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();
//.get() 메서드는 Optional을 한번 벗기고 꺼낼 수 있음
Assertions.assertThat(result).isEqualTo(member1);
}

➡️ findByname() test > 정상 실행
@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);
}

➡️ findAll() test > 정상 실행
class MemorymemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach // 메서드가 끝날때마다 해당 메서드 실행
public void afterEach(){
repository.clearStore();
}


➡️ test는 순서를 보장해주지 않기 때문에 의존성 문제를 꼭 없애줘야 함
➡️ 각 메서드마다 메모리를 초기화해주기 위해 @AfterEach를 통해 레파지토리 clear
➡️ (구현 > 테스트)의 순서가 아닌 (테스트 > 구현) 순서로, 테스트를 먼저 만들고 개발을 테스트에 맞춰서 하는 것을 TDD(Test-Driven Development / 테스트 주도 개발)라고 함
'프로그래밍 > - Spring' 카테고리의 다른 글
| [ 회원 관리 예제 - 웹 MVC 개발 ] 회원 웹기능 - 홈 화면 추가 / 등록 / 조회 (1) | 2025.02.04 |
|---|---|
| [ 스프링 빈과 의존관계 ] 컴포넌트 스캔과 자동 의존관계 설정 / 자바 코드로 직접 스프링 빈 등록하기 (1) | 2025.01.24 |
| [ 회원 관리 예제 - 백엔드 개발 ] 회원 서비스 개발 / 회원 서비스 테스트 (1) | 2025.01.23 |
| [ 스프링 웹 개발 기초 ] 정적 컨텐츠 / MVC와 템플릿 엔진 / API (3) | 2025.01.21 |
| [ 프로젝트 환경설정 ] 프로젝트 생성 / 라이브러리 살펴보기 / View 환경설정 / 빌드하고 실행하기 (2) | 2025.01.15 |