본문 바로가기
Back-End/Spring

2.회원관리 예제

by 두두리안 2020. 12. 25.
728x90

2. 회원관리 예제

목차

  • 1.비즈니스 요구사항 정리
  • 2.회원 도메인과 리포지토리 만들기
  • 3.회원 리포지토리 테스트 케이스 작성
  • 4.회원 서비스 개발
  • 5.회원 서비스 테스트

1.비즈니스 요구사항 정리

  • Member(회원)에는 ID,Name
  • 회원등록 , 조회 기능

image

  • 컨트롤러 : 서비스 계층을 호출하고 결과를 뷰에 전달하는곳
  • 서비스 : 비즈니스 로직이 있고 트랜잭션을 시작 , 데이터 접근 계층인 리포지토리를 호출한다
  • Repository : JPA를 직접사용하는곳 , 엔티티 매니저를 사용해서 저장하고 조회한다
  • Domain : 엔티티가 모여있는곳

image

  • MemberRepository 인터페이스로 구현클래스를 변경할수 있도록 설계한다

2.회원 도메인과 리포지토리 만들기

Member(엔티티)

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

MemberRepository(Repository 템플릿 메소드)

public interface MemberRepository {

    Member save(Member member);  // Member 엔티티를 DB에 저장한다
    Optional<Member> findById(Long id);  // 엔티티 값의 id를 찾는다  where id =?
    Optional<Member> findByName(String name);  // 엔티티 값의 name을 찾는다 where name=?
    List<Member> findAll(); //엔티티의 값을 모두 조회  select * from Member

}

MemoryMemberRepository(Repository 구현클래스)

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) {
        //결과가 null인경우를 대비해서 Optional로 감싼다.
        return Optional.of(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(); //초기화 시켜준다
    }
}
  • HashMap을 통한 소스!

3.회원 리포지토리 테스트 케이스 작성

MemoryMemberRepositoryTest(Repository 테스트 코드!)

class MemoryMemberRepositoryTest {

    MemoryMemberRepository repository = new MemoryMemberRepository();

    @AfterEach
    public void afterEach(){
        repository.clearStore(); //모든 테스트가 끝난후에 실행 데이터 값을 초기화 
    }

    @Test
    void save() {
        //given
        Member member = new Member();
        member.setName("spring");

        //when
        repository.save(member);
        Member result = repository.findById(member.getId()).get();

        //then
        Assertions.assertEquals(result,member);
        assertThat(member).isEqualTo(result);

    }

    @Test
    void findByName() {
        //회원1
        Member member1=new Member();
        member1.setName("spring1");
        repository.save(member1);

        //회원2
        Member member2=new Member();
        member2.setName("spring2");
        repository.save(member2);

        Member result = repository.findByName("spring1").get();

        assertThat(result).isEqualTo(member1);

    }

    @Test
    void findAll() {
        //회원1
        Member member1=new Member();
        member1.setName("spring1");
        repository.save(member1);

        //회원2
        Member member2=new Member();
        member2.setName("spring2");
        repository.save(member2);

        List<Member> result = repository.findAll();

        assertThat(result.size()).isEqualTo(2);


    }
}
}
  • 테스트 코드를 통해서 Repository를 검증한다
  • 항상 테스트코드 를 작성하는 법이 중요!

4.회원 서비스 개발

MemberService(service)

public class MemberService {

    private final MemberRepository memberRepository = new MemoryMemberRepository();

    //회원가입
    public Long join(Member member){
        //같은 이름이 있는 중복회원 x

        /*//DB안의 name 을  Parameter getName넣어서 찾는다
        Optional<Member> result = memberRepository.findByName(member.getName());

        //값을 꺼내온다 (객체)
        Member member1 = result.get();

        //result의 값이 있을경우
        result.ifPresent(m -> {
            throw new IllegalStateException("이미 존재하는 회원입니다");
        } );*/


        //메소드로 뽑아서 쓴다 ctrl + alt + m
        //중복회원검증
        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(service 수정..!)

public class MemberService {

    //private final MemberRepository memberRepository = new MemoryMemberRepository();

    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;  // 생성자 주입을 통해서 같은 MemberRepository를 사용 (인터페이스!!)
    }

    //회원가입
    public Long join(Member member){
        //같은 이름이 있는 중복회원 x

        /*//DB안의 name 을  Parameter getName넣어서 찾는다
        Optional<Member> result = memberRepository.findByName(member.getName());

        //값을 꺼내온다 (객체)
        Member member1 = result.get();

        //result의 값이 있을경우
        result.ifPresent(m -> {
            throw new IllegalStateException("이미 존재하는 회원입니다");
        } );*/

    ...
}

MemberServiceTest(테스트코드)

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memoryMemberRepository;

    @BeforeEach
    public void beforeEach(){
        //같은 MemoryMemberRepository 를 사용한다 이럴경우 같은 DB를 공유한다
        memoryMemberRepository = new MemoryMemberRepository();
        memberService=new MemberService(memoryMemberRepository);
    }

    @AfterEach
    public void afterEach(){
        memoryMemberRepository.clearStore();  // DB값 초기화
    }

    @Test
    void 회원가입() {

        //given
        Member member = new Member();
        member.setName("spring");

        //when
        Long saveId=memberService.join(member);

        //then
        Member findMember = memberService.findOne(saveId).get();
        assertThat(member.getName()).isEqualTo(findMember.getName());

    }

    @Test
    void 중복회원예외() {

        //given
        Member member1 = new Member();
        member1.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");

        //when
        memberService.join(member1);


        //then
        IllegalStateException result = assertThrows(IllegalStateException.class,
                () -> memberService.join(member2));  // member2 가 회원가입할때 IllegalStateException 오류가 나옴
        assertThat(result.getMessage()).isEqualTo("이미 존재하는 회원입니다");

    }

    @Test
    void findMembers() {
    }

    @Test
    void findOne() {
    }
}
  • 생성자 주입을 통해서 같은 MemberRepository를 사용하게 만들어준다
  • DI 의존성을 주입시켜준다!
  • 결국 같은 MemoryMemberRepository 를 사용하게 되서 같은 데이터 베이스가 공유된다!
  • 다를 경우는 테이블이 2개가 생길수 있다!

참고자료

728x90

'Back-End > Spring' 카테고리의 다른 글

6.스프링 DB접근기술  (0) 2020.12.29
5.순수 JDBC 접근기술  (0) 2020.12.28
4.회원 관리 예제 - 웹 MVC개발  (0) 2020.12.28
3.스프링빈과 의존관계  (0) 2020.12.28
1.스프링부트 웹개발 기초  (0) 2020.12.25