본문 바로가기

[스프링 부트 + JPA + MySQL] 간단한 회원관리 예제로 알아보는 스프링 부트 -3탄 Service 만들기

ironwhale 2022. 11. 15.

서비스 부분은 앞서 만든 Repository를 이용하여 회원가입, 회원조회 등 실제 서비스를 구현하는 부분입니다. 사실 Repository와 Service부분을 합쳐도 되는거 아니야 라고 생각을 했지만 김영한님의 스프링 강의를 쭉 들어보니 각각의 기능들을 구분하고 분리해놔야 유지보수가 쉽다는 것을 알았습니다. 예를 들어 입문 강의에서 JDBC 템플릿에서 JPA로 바꾸는 과정에서 repository와 service가 합쳐져 있으면 바꿔 끼우는것이 어려웠을텐데 코드 한줄만 바꾸면 쉽게 교체가 되었습니다. 자세한 내용은 인프런 스프링 부트 입문 강의를 들어보시면 알수 있습니다.

 

[무료] 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com


서비스 만들기

repository에서 만든 기능들을 조합하여 실제 필요한 서비스를 구현하는 부분입니다. 회원 가입하는 부분에서는 repository에 save와 findByName을 이용하여 회원가입과 중복확인을 구현하였습니다.

MemberRepository 객체를 생성자를 통해 주입을 하였는데 클래스 간의 이런 느슨한 결합이 코드를 더 유연하게 해준다라고 강의에서 들었던거 같습니다. 이부분 역시 설정을 통해 주입할 예정입니다.

  • join: 회원가입
  • validateDuplicateMember : 중복확인
  • findMembers: 전체 회원 조회
  • findOne: 멤버 pk로 회원 조회
package com.example.demo.service;

import com.example.demo.domain.Member;
import com.example.demo.repository.MemberRepository;

import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;

@Transactional
public class MemberService {

    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    public Long join(Member member) {

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

Spring에 MemberService 설정하기

이전 repository와 같이 @Bean을 통해 스프링에 MemberService가 있다고 알려주고 있습니다. 이렇게 말고 다른 방법도 있기만 이 방법의 장점은 그때 그때 내가 필요한 클래스로 교체하는 것이 용이하다는 점입니다.

package com.example.demo;

import com.example.demo.repository.JpaMemberRepository;
import com.example.demo.repository.MemberRepository;
import com.example.demo.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManager;

@Configuration
public class SpringConfig {
    private final EntityManager em;
    public SpringConfig(EntityManager em) {
        this.em = em;
    }

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        return new JpaMemberRepository(em);
    }
}

Service 테스트 해보기


테스트이기 때문에 복잡하게 생성자 주입을 사용하지 않고 @Autowired 이용해서 이렇게 필드로 주입을 한다고 하셨습니다. 그리고 테스트여서 함수도 그냥 한글로 하셨는데 이렇게 하니 오류가 나는 부분을 더 쉽게 알아 차릴수 있어 좋았습니다. 이렇게 테스트 돌려보면 스프링을 실제 구동 하지 않고도 이게 잘 되는지 않되는지 확인 가능하여 좋습니다.

package com.example.demo.service;

import com.example.demo.domain.Member;
import com.example.demo.repository.MemberRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.transaction.Transactional;

import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
@Transactional
class MemberServiceTest {

    @Autowired MemberRepository memberRepository;
    @Autowired MemberService memberService;

    @Test
    void 회원가입() {

        Member member = new Member();
        member.setName("Spring");


        Long id = memberService.join(member);

        Member findMember = memberRepository.findById(id).get();
        assertThat(findMember.getName()).isEqualTo(member.getName());


    }

    @Test
    void 중복회원예외확인(){
        Member member = new Member();
        member.setName("Spring");

        Member member1 = new Member();
        member1.setName("Spring");

        memberService.join(member);
        IllegalStateException e = assertThrows(IllegalStateException.class,
                                           ()->memberService.join(member1));
        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");


    }


}

이제 우리가 직접 사용하는 웹 화면까지 한단계 controller가 남았습니다.

댓글