DevKim

[01] 회원 관리 예제 - 비즈니스 요구 사항 정리 & domain과 repository 생성 &Test code 작성 본문

Spring Boot

[01] 회원 관리 예제 - 비즈니스 요구 사항 정리 & domain과 repository 생성 &Test code 작성

on_doing 2021. 5. 6. 15:59
728x90

[ 비즈니스 요구 사항 정리 ]

1. 데이터

: 회원ID (PK 값), 이름

 

2. 기능

: 회원 등록, 조회

 

3. 가상의 시나리오

: 아직 DB는 어떤걸 쓸지 정하지 않은 상황!!

 

→ 아직 데이터 저장소가 선정되지 않아서, 우선 인터페이스로 구현 클래스를 변경할 수 있도록 설계

→ DB는 정해지지 않았지만 개발을 진행하기 위해서,

초기 개발 단계에서는 구현테로 가벼운 메모리 기반의 데이터 저장소 사용


[ 일반적인 웹 계층 구조 ]

 

- controller : 웹 MVC의 컨트롤러 역할

- service : 핵심 비즈니스 로직 구현

(회원 아이디 중복 가입이 안됨..등)

- repository : DB에 접근, 도메인 객체를 DB에 저장하고 관리

- domain : 비즈니스 도메인 객체 (회원,주문,쿠폰 등등 주로 DB에 저장하고 관리되어짐)


[ 클래스 의존 관계 ]


[ 회원 도메인 생성 ]

domain/Member

Getter와 Setter은 lombok으로 선언하고 싶었지만,...

일단 이 강의의 목적은

base로 돌아가기 위함이므로 영한님 코드 방법대로 작성했다

(alt+insert 단축키로 생성 가능)


[ 리포지토리 생성 ]

repository/MemberRepository

repository에 4가지 기능을 만들어주었다.

spring data JPA를 먼저 접한 나로써는.. 복잡하다고 느껴진다

 

*Optional = null이 될 수도 있는 객체를 감싸는 일종의 특수 그릇


[ 회원 레포지토리 메모리 구현체 ]

- save 할 때 어딘가에 저장할게 필요한데, 여기에서는 hashmap을 사용해주었다

( 실무에서는 동시성 문제가 있을 수도 있어서 이렇게 공유되는 변수일때는

concurrent hashmap을 사용해야한다고한다)

 

- pk값을 생성하는 type을 Long으로 설정해줬는데,

실무에선 여러 문제 때문에 어텀롱을 사용한다고 한다

 

-Optional.ofNullable

→ null인지 아닌지 확신할 수 없는 객체를 담고 있는 Optional 객체를 생성

→ 해당 객체가 Null인지 아닌지 확신이 없다면, 이 메소드를 사용해야한다고 한다.

 

repository/ MemoryMemberRepository

public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long,Member> store = new HashMap<>();
    private static Long i=0L;
	
    //저장
    @Override
    public Member save(Member member) {
        member.setId(++i);
        store.put(member.getId(), member);
        return member;
    }
	
    //id로 찾기
    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }
	
    //name으로 찾기
    @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();
    }
}

[ 테스트 케이스 ]

- 테스트 할 때마다, 번거로움을 줄이기 위해 JUnit 프레임워크로 테스트를 진행한다.

실수에서 Test code 없이는 거의 작업이 불가능하다고 봐야 할 정도로 테스트 코드 작성은 중요하다고 한다.

 

보통 패키지 이름과 클래스..등 모두 같게 Test에도 설정해주는데, ctrl+shift+T 단축키로 바로 생성할 수 있음

이렇게 자동생성됨


[ 회원 repository 테스트 케이스 작성 ]

 

테스트 케이스는 기본적으로

given -> when -> then 패턴으로 작성하는 것이 좋다고 한다.

 

given : 이런 상황이 주어졌는데

when : 이것을 실행했을 때

then : 이런 결과가 나와야한다!

 

< save 테스트 >

<findByName 테스트>

<findAll 테스트>

2개가 잘 저장이 되었나 확인

 

* 이때, 테스트는 각각 독립적으로 실행되어야하고, 테스트 순서에 의존관계가 있는 것은 좋은 테스트가 아니다!!

 

따라서 @AfterEach를 사용하여 각 테스트가 종료될 때마다

이전의 테스트에 의해 메모리 DB에 저장된 데이터를 삭제해주어야한다.

 

 

*** 테스트 주도 개발 (TDD) ***

= 검증할 수 있는 테스트를 먼저 만들고, 구현 class를 만들어서 돌려보는 것

 

*자료 출처*

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 (김영한)

728x90
Comments