Springboot - 도메인, 리포지토리, 서비스

Mingi Shin·2023년 4월 9일
0
post-custom-banner

실습 참고: 링크

1. 도메인

  • 애플리케이션의 비즈니스 논리 및 데이터 관리를 정의. 비즈니스 로직과 데이터를 캡슐화한다.
package hello.hellospring.domain;

public class Member {

    private Long id;        //id 식별자. 고객이 정하는 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;
    }
}
  • Member 클래스는 member라는 엔티티(객체)를 나타내고 있다. id와 name이라는 속성이 있다.
  • id는 각 객체를 고유하게 식별하는데 사용되고 유저가 아닌 시스템이 설정한다. (시퀀스를 활용하는 등)
  • name은 문자열 타입 필드.
  • getter와 setter로 외부에서 각 필드에 접근할 수 있다.

2. 리포지토리

  • 데이터베이스에 접근하거나 도메인 엔티티를 저장하고 관리하는 역할.

interface

//MemberRepository [interface]

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); //저장소에서 id로 회원을 찾음
    Optional<Member> findByName(String name);
    List<Member> findAll(); //저장된 모든 회원 리스트 반환
}
  • 자바 인터페이스. Member class에 대한 액세스를 관리하기 위한 저장소의 basic contract.
  • save(): 리포지토리에 엔티티를 저장. 저장된 멤버 객체를 리턴.
  • findById(): id를 매개변수로 받아 멤버 객체를 리턴.
  • findByName(): name을 매개변수로 받아 맴버 객체를 리턴.
  • findAll(): repository에 저장된 모든 멤버 객체를 리스트로 리턴.

구현체

//MemoryMemberRepository [class]

package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.*;

public class MemoryMemberRepository implements MemberRepository{    //MemberRepository interface를 implement한다.

    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) {
        return Optional.ofNullable(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();
    }
}
  • 인터페이스를 구현한 클래스들.

  • store: 각 멤버 엔티티는 key-value 쌍으로 store에 저장된다. 키는 id, 값은 그에 대한 엔티티.

  • sequence: 각 인스턴스 생성에 쓰일 id.

  • save(): 멤버의 인스턴스를 가져와 setId(sequence)한다. 그 후, store에 저장하는데 매핑 규칙에 의해 (Id, member) 순으로 store에 put한다. 마지막으로 멤버 인스턴스 리턴.

  • findById(): id를 매개변수로 받는다. id가 store에 있는 경우, 해당 멤버 인스턴스를 리턴한다. 그런데 NULL이 리턴될 가능성이 있기 때문에 Optional로 감싼 것!

  • findByName(): name을 매개변수로 받는다. store에 name과 같은 멤버를 리턴한다.

    store.value(): store에 있는 모든 멤버 인스턴스를 리턴한다는 의미
    store.value().stream(): 컬렉션 크기에 따른 기존 반복문 처리의 성능 저하를 개선했다. 스트림은 컬렉션 데이터를 선언형으로 하여 중첩 없이 병렬적 처리도 가능하게 되었다. store.value().stream()은 store에 있는 모든 인스턴스에 대해 스트림을 사용하겠다는 의미.
    .flter(member -> member.getName().equals(name)): 스트림에 filter를 적용해 매개변수 name과 같은 name 필드에 대한 멤버 인스턴스를 뽑아냄.
    findAny(): Stream에서 가장 먼저 탐색되는 요소 리턴.

  • findAll(): store에 매핑된 멤버 객체들을 리스트화해서 리턴. values는 여기서 키-벨류. 키는 id, 벨류는 member임.

  • clearStore(): store를 비우는 것. 여러 메서드, 클래스를 테스트할 때 store 중복되는 경우 있어서 오류 뜨는 것을 방지.

3. 서비스

// MemberService

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;

import java.util.List;
import java.util.Optional;

public class MemberService {

    private final MemberRepository memberRepository = new MemoryMemberRepository();

    /*
     * 회원 가입
     */
    public Long join(Member member){
        validateDuplicateMember(member);    //중복 회원 검증
        memberRepository.save(member);
        return member.getId();
    }

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                .ifPresent(m -> {     //result가 있으면~, 존재하면~, == 널이 아니면
                    throw new IllegalStateException("이미 존재하는 회원입니다.");
                });
    }

    public List<Member> findMembers(){
        return memberRepository.findAll();
    }

    public Optional<Member> findOne(Long memberId){
        return memberRepository.findById(memberId);
    }
}
  • 웹 애플리케이션 서비스 레이어 클래스.
  • 비즈니스 로직 메서드를 정의한다.
  • join(): 멤버 객체를 매개변수로 받는다. 중복성 검사 후 멤버저장소에 추가한다.
  • validateDuplicateMember(): memberRepository 클래스의 findByName 메서드를 사용해 중복을 체크한다. 만약 중복이 있다면 exception을 throw한다.
  • findMembers(): memberRepository의 findById 메서드를 사용해 repository에 있는 모든 멤버를 List로 리턴한다.
  • findOne(): memberId를 매개변수로 받는다. 특정 Id에 대한 findById메서드를 실행해 해당 멤버를 리턴한다. 리턴이 null이 될 수 있기 때문에 optional로 감싸서 리턴.
profile
@abcganada123 / git:ABCganada
post-custom-banner

0개의 댓글