Spring - 회원 관리 예제

김춘식·2023년 1월 20일

Spring

목록 보기
1/3
post-thumbnail

비즈니스 요구사항 정리

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

일반적인 웹 애플리케이션의 계층 구조

  • 컨트롤러 : 웹 MVC의 컨트롤러 역할
  • 서비스 : 핵심 비즈니스 로직 구현
  • 리포지토리 : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
  • 도메인 : 비즈니스 도메인 객체

이 예제에서의 클래스 의존관계

  • 아직 데이터 저장소 선정X -> 우선 인터페이스로 구현, 클래스를 변경할 수 있도록 설계(OCP 원칙)
  • 개발을 진행하기 위해서 초기 개발 단계에서는 구현체로 가벼운 메모리 기반의 저장소 사용(List)

회원 도메인(Member class)와 리포지토리 만들기

Class : Member

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

Interface : MemberRepositroy (저장소가 바뀔수 있으므로 인터페이스로 구현)

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

Class : MemoryMemberRepository

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<>();
 private static long sequence = 0L; // sequence는 0,1,2 key값을 생성해주는 역할
 @Override
 public Member save(Member member) {
 member.setId(++sequence);
 store.put(member.getId(), member);
 return member;
 }
 @Override
 public Optional<Member> findById(Long id) { // Optional의 사용으로 Null을 처리할수 있다
 return Optional.ofNullable(store.get(id));
 }
 @Override
 public List<Member> findAll() {
 return new ArrayList<>(store.values());
 }
 @Override
 public Optional<Member> findByName(String name) {
 return store.values().stream()
 .filter(member -> member.getName().equals(name))
 .findAny(); // 람다식 사용
 }
 public void clearStore() { // clearStore가 필요한것은 테스트를 위해서이다.
 store.clear();
 }
}

중요! Junit을 사용한 테스트 케이스 작성법

이제 도메인과 리포지토리를 만들었으니, 서비스를 작성해보도록 하겠다.
회원 서비스는 도메인과 리포지토리를 활용해서 실제 비즈니스 로직을 작성하는 쪽이다.

Class : MemberService

package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import java.util.List;
import java.util.Optional;
public class MemberService {
 private final MemberRepository memberRepository = new MemoryMemberRepository(); //회원 서비스를 만들려면 저장소가 필요하다.


 public Long join(Member member) { //회원 가입
 /*
 Optional<Member> result = memberRepository.findByName(member.getName());
 result.ifPresent(m ->{
            throw new IllegalStateException("이미 존재하는 회원입니다.");
            }); 
            // ifPresent는 값이 있으면 실행함, Member를 바로꺼내고싶으면 .get()을 사용해도됨
            // result로 꺼내는 방식보다 바로 .ifPresent를 쓰는 방식이 더 적절함 (밑코드 참조)
            // 이런 로직이 있는 경우에는 메소드로 뽑는게 적절함 (Ctrl+Alt+Shift+T -> Extract Method)
            // 실제로 이 예시에서는 validateDuplicateMember 라는 메소드를 생성하였음
*/
 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);
 }
}

오늘 내용은 사실상 스프링이라기 보다는
순수 자바코딩에 가까운 내용이다.

다음 포스트에서는

  • 의존관계 설정
  • 컨트롤러 생성

을 다뤄서 본격적으로 스프링을 배워보도록 할것이다

그럼이만! 🙌🙌


Ref.

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

profile
나도 화이팅 너도 화이팅 모두들 화이팅~

0개의 댓글