[스프링 입문] 회원 관리(1)

2024. 8. 24. 15:27·Back-End/Spring

[작성일: 2023. 05. 11]

 

회원 관리

비즈니스 요구사항 정리

  • 데이터: 회원 ID, 이름
  • 기능: 회원 등록, 조회
  • 아직 데이터 장소가 선정되지 않음(가상의 시나리오)

 

출처: 김영한님

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

 

출처: 김영한님

  • 아직 데이터 저장소가 선정되지 않았다는 가상 시나리오가 있기 때문에 우선 인터페이스로 구현 클래스를 변경할 수 있도록 설계한다.
  • 데이터 저장소는 RDB, NoSQL 등 다양한 저장소를 고민 중인 상황으로 가정한다.
  • 개발을 진행하기 위해서 초기 개발 단계에서는 구현체(단순)로 가벼운 메모리 기반의 데이터 저장소를 사용한다.

 

 

 

 

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

회원 객체(Member.class)

  • id(데이터 구분을 위해 시스템이 저장하는 id)와 name 두 가지의 요구사항이 존재함.
package hello.hellospring.domain;

public class Member {

    private Long id;  // 임의의 값(시스템이 저장하는 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 인터페이스)

  • Optional 사용(결과 값이 null일 때 옵셔널로 감싸서 반환할 수 있음.)
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);
    Optional<Member> findByName(String name);
    List<Member> findAll();
}

 

 

 

MemoryMemberRepository.class

  • 해당 클래스가 제대로 동작하는지 확인하기 위에 테스트케이스를 작성해야 함.
package hello.hellospring.repository;

import hello.hellospring.domain.Member;

import java.util.*;

public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long, Member> store = new HashMap<>(); // save 할 때 저장할 공간
    private static long sequence = 0L;

    @Override
    public Member save(Member member) {  // save 하면 저장소에 저장
        member.setId(++sequence);
        store.put(member.getId(),member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }
    // 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();  // 스토어를 비움.
    }
}

 

 

 

 

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

  • 개발한 기능을 실행해서 테스트 할 때 자바의 main 메서드를 통해서 실행하거나, 웹 애플리케이션의 컨트롤러를 통해서 해당 기능을 실행한다.
  • 이러한 방법은 준비하고 실행하는데 오래 걸리고, 반복 실행하기 어려우며, 여러 테스트를 한 번에 실행하기 어렵다는 단점이 있다.
  • 자바는 JUnit이라는 프레임워크로 테스트를 실행해서 이러한 문제를 해결해 준다.

 

 

회원 리포지토리 메모리 구현체 테스트(src/test/java/repository)

  • test 쪽에 똑같은 이름의 패키지 폴더를 만들어준다.
  • MemoryMemberRepositoryTest.class
  • test 순서가 보장이 되지 않는다.
  • 하나의 테스트는 의존관계없이 설계되어야 한다.
  • 테스트가 한 번 끝나고 나면 클리어해줘야 한다. 
package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

public class MemoryMemberRepositoryTest {
    MemoryMemberRepository repository = new MemoryMemberRepository();

    // 하나의 테스트는 의존관계 없이 설계되어야 함.
    @AfterEach
    public void afterEach() {  // 메서드 실행이 끝날 때마다 호출됨.
        repository.clearStore();  // 테스트가 끝날때마다 저장소를 지움.
    }

    @Test // save 기능이 동작하는지 확인하려면 애너테이션 test를 붙이면 됨.
    public void save() {
        Member member = new Member();
        member.setName("spring");  // 이름을 spring으로 세팅
        repository.save(member);

        Member result = repository.findById(member.getId()).get();  // 옵셔널에서 값을 꺼낼 때 get 사용
        //    System.out.println("result = " + (result == member));  단순 확인 ver
        assertThat(member).isEqualTo(result);  // 요즘은 assertThat을 많이 사용함.
        // member와 result와 같은지 확인. 다른 값이라면 빨간 불이 뜸.

    }

        @Test
        public  void findByName() {
           Member member1 = new Member();
           member1.setName("spring1");
           repository.save(member1);  // member1 저장

           Member member2 = new Member();
           member2.setName("spring2");
           repository.save(member2);  // 정교한 테스트를 위해 member2 저장

          Member result = repository.findByName("spring1").get();
          assertThat(result).isEqualTo(member1);
        }

        @Test
        public void findAll() {
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("spring1");
        repository.save(member2);

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

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

        }
    }

 

 

 

AfterEach

  • 한 번에 여러 테스트를 실행하면 메모리 DB에 직전 테스트의 결과가 남을 수 있다.
  • 이렇게 되면 이전 테스트 때문에 다음 테스트가 실패할 가능성이 있다.
  • @AfterEach를 사용하면 각 테스트가 종료될 때마다 메모리 DB에 저장된 데이터를 삭제해준다.
  • 테스트는 각각 독립적으로 실행되어야 하며, 테스트 순서에 의존 관계가 있는 것은 좋은 테스트가 아니다.

 

 

 

 

 

 

 

 

 

 


🐣 출처: 인프런 김영한님 강의


이 글은 인프런의 김영한님 스프링 강의를 보고 작성한 글입니다.

강의를 들으면서 정리한 글이므로 틀린 내용이나 오타가 있을 수 있습니다.

 

저작자표시 비영리 변경금지 (새창열림)
'Back-End/Spring' 카테고리의 다른 글
  • [스프링 입문] 스프링 빈과 의존관계(1)
  • [스프링 입문] 회원 관리(2)
  • [스프링 입문] 스프링 웹 개발 기초
  • [스프링 입문] 스프링 로드맵
뚜비
뚜비
1년차 백엔드&iOS 개발자의 감자 탈출 블로그 🥔🥔
  • 뚜비
    뚜비의 개발로그
    뚜비
  • 전체
    오늘
    어제
  • 글쓰기     관리
    • Devlog
      • Back-End
        • Java
        • Spring
        • JPA
        • HTTP
        • Security
        • Back-End
        • Front-End
      • 알고리즘
      • iOS
        • Swift
      • Database
      • Tips
        • Git & GitHub
        • A to Z
      • 프로젝트
      • 생각정리
  • 태그

    html
    Database
    김영한
    성능최적화
    Swift
    자바스크립트
    백준
    HTTP
    알고리즘
    스프링
    jsp
    spring
    데이터베이스
    게시판만들기
    객체
    자바
    DB
    의존성주입
    Java
    프로그래머스
    Spring Security
    생성자
    MVC
    javascript
    JPA
    최주호
    다형성
    변수
    sql
    Security
  • hELLO· Designed By정상우.v4.10.0
뚜비
[스프링 입문] 회원 관리(1)
상단으로

티스토리툴바