본문 바로가기
JAVA & SPRING/Spring 핵심원리-기본

스프링 핵심 원리 기본편-2일차(스프링 핵심원리 이해1 - 회원 도메인)

by 눈오는1월 2023. 7. 24.
728x90

이번에는 스프링을 최대한 안쓰면서 개발을 진행했다. 

일단 버전은 Java11에 2.7.14 버전으로 스프링을 generate를 했다. 다른 dependencies는 아무것도 설정하지 않았다.

 

비지니스 요구사항은 

아직 DB나 할인 정책은 미확정이므로 인터페이스를 만들고 구현체를 바꿔낄 수 있게 끔 개발을 진행한다.

일단 hello.core에 member라는 패키지를 만든다.

패키지안에 Grade 이름으로 Enum 클래스를만든다. (Enum클래스를 이용해서 해당 클래스 내에 있는 값만 값을 들어오게할수있다.)

package hello.core.member;

public enum Grade {  // 열거형 클래스
    BASIC,
    VIP

}  // BASIC, VIP 라는 값만 들어올 수 있음

그 후 Member라는 클래스를 생성한다. 

package hello.core.member;

public class Member {

    private Long id;
    private String name;
    private Grade grade;

    public Member(Long id, String name, Grade grade) {
        this.id = id;
        this.name = name;
        this.grade = grade;
    }

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

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }
}

요구사항에 맞게끔 id, name, grade 변수를 만든다. (Enum 클래스를 통해서 grade에는 BASIC or VIP 값만 들어올 수 있음)

이제 회원 저장소를 만든다. 아직 DB가 확정이 아니기에 인터페이스를 만든뒤 구현체를 만들어서 진행한다. (추후에 구현체를 바꿔낄수 있게끔)

MemberRepository 인터페이스 생성

package hello.core.member;

public interface MemberRepository {

    void save(Member member); // 회원 저장

    Member findById(Long memberId); // 회원의 아이디 찾기

}

인터페이스 생성 후 해당 인터페이스를 상속받는 MemberRepository 클래스 구현

package hello.core.member;

import java.util.HashMap;
import java.util.Map;

public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long, Member> store = new HashMap<>();  // 동시성이슈가 있기에 실무에서는 ConcurrentHashMap 이용

    @Override
    public void save(Member member) {
        store.put(member.getId(), member);
    }
    @Override
    public Member findById(Long memberId) {
        return store.get(memberId);
    }
}

이제 회원 서비스를 만들어야한다

마찬가지로 인터페이스를 만들고 클래스를만들어서 역할과  구현을 나누자

MemberService 인터페이스를 만든다.

package hello.core.member;

public interface MemberService {

    void join(Member member);

    Member findMember(Long memberId);


}

이제 마찬가지로 MemberSerice 인터페이스를 상속받는 MemberServiceImpl를 만들어야한다.

package hello.core.member;

public class MemberServiceImpl implements MemberService{


    private final MemberRepository memberRepository = new MemoryMemberRepository();
    // 인터페이스를 의존하고 할당하는부분이 구현체를 의존한다. DIP 위반하고 있는거여서 변경할때 어려움이 있다.
    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

해당 실행이 잘 작동하는지 확인하기 위해 CoreApplication에 같은 경로에 MemberApp이라는 클래스를 만들어서 동작한다.

package hello.core;

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;

public class MemberApp {

    public static void main(String[] args) {
        MemberService memberService = new MemberServiceImpl();
        Member member = new Member(1L, "memberA", Grade.VIP);
        memberService.join(member);


        Member findMember = memberService.findMember(1L);
        System.out.println("new Member = " + member.getName());
        System.out.println("find member = " + findMember.getName());
    }
}

실행 결과

이렇게 자바를 돌리면서 테스트를 할 수 있지만 실행결과를 눈으로 확인을 해야하는 번거로움이 있다. 그래서 이번에 테스트 코드로 테스트를 확인해본다.

test로 가서 member패키지를 생성한 후 MemberServiceTest를 만들어서 테스트를 실행한다.

package hello.core.member;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

public class MemberServiceTest {

    MemberService memberService = new MemberServiceImpl();

    @Test
    void join() {
        //given
        Member member = new Member(1L, "memberA", Grade.VIP);


        //when
        memberService.join(member);
        Member findMember = memberService.findMember(1L);


        //then
        Assertions.assertThat(member).isEqualTo(findMember);

    }
}

해당 회원 도메인 같은경우 DIP를 잘 지키지 않고 있다. 위 주석에 있는 부분이 인터페이스 뿐만 아니라 구현까지 모두 의존하는 문제점이 존재한다.

 

728x90