스프링 공부/인프런 김영한 스프링 핵심 원리 - 기본편 노트정리

2-4. 회원 도메인 개발

모항 2022. 8. 22. 05:51

 

 

 

 

Grade Enum 만들기

회원 등급을 열거하는 enum인 Grade를 만들자.

 

hello.core 하위에 member 패키지를 만든다.

 

 

그리고 그 안에 Grade라는 Enum을 만들어준다.

Enum... 처음 써본다... 떨린다.

 

 

회원 등급은 일반 회원과 VIP 회원 두 가지이므로 이렇게 채워주면 된다.

 

 

 

 

 

회원 엔티티 클래스 만들기

회원 정보라는 것의 구조를 정의하는 회원 엔티티 클래스를 만든다.

 

member 패키지 안에 Member 클래스를 만든다.

 

 

회원 정보에 포함되는 세 가지 필드인 id, name, grade를 적어준 다음,

generate 기능 (윈도우 버전 Alt + Insert 단축키) 을 이용해 Member의 생성자를 만들고 세 가지 필드의 getter, setter도 모두 만들어준다.

 

 

 

 

 

 

MemberRepository 인터페이스 만들기

회원 정보 리포지토리 구현체들의 바탕이 될 MemberRepository 인터페이스를 만든다.

 

역시 Member 패키지 안에 만들어준다.

 

 

요구사항을 되짚어보자.

회원 정보 관련 기능은 새 회원 정보 저장과 회원 정보 조회가 필요하다.

그러므로 이렇게 회원 정보 저장하는 기능과, ID를 기준으로 회원 정보를 조회하는 기능을 적어준다.

 

 

 

 

 

 

 

MemoryMemberRepository 클래스 만들기

MemberRepository를 구현하는 첫 번째 구현체 클래스이다.

PC의 로컬 메모리를 사용하는 (프로그램을 끄면 데이터가 휘발되는) 구현체다.

 

원래는 인터페이스와 구현체를 서로 다른 패키지에 구분해 넣는 것이 정석인데,

이번 예제에서는 편의를 위해 그냥 같은 패키지에 넣으시겠다고 한다.

member 패키지에 만들어준다.

 

 

위와 같이 MemberRepository를 implement한다고 적어주고, implement methods를 눌러 메소드들을 받아온다.

 

 

회원 정보들을 담을 저장 공간인 HashMap store을 만들어준다.

Id를 기준으로 Member 객체를 찾아올 것이므로 Key는 Id의 타입인 Long으로, Value는 Member로 정해준다.

 

원래 실무에서는 HashMap이 아니라 멀티 스레드 환경에서 사용할 수 있는 ConcurrentHashMap을 사용해야 한다. 하지만 지금은 멀티 스레드 환경에 대응할 필요가 딱히 없는 단순한 예제를 만드는 중이고, 강의에서 ConcurrentHashMap에 대해 설명하려면 복잡하기 때문에 그냥 HashMap을 쓰시겠다고 한다.

 

 

메소드의 내용을 이렇게 채워준다.

store에 저장하는 내용, store에서 Id를 기준으로 Member 객체를 찾아오는 내용이다. 매우 간단하다.

 

 

 

 

 

 

MemberService 인터페이스 만들기

이번엔 회원 서비스 구현체들의 바탕이 될 MemberService 인터페이스를 만든다.

 

이것 역시 그냥 member 패키지 안에 만든다.

 

 

서비스에는 전 회차에서 본 회원 도메인 협력 관계에 나와있듯이 회원가입과 회원조회라는 두 가지 기능이 들어간다.

따라서 다음과 같이 적어준다.

 

 

 

 

 

 

MemberServiceImpl 클래스 만들기

MemberService를 바탕으로 한 구현체 클래스인 MemberServiceImpl 클래스를 만든다.

MemberRepository의 경우 여러 개의 구현체를 만들어 쓸 것이기 때문에 각 클래스의 특성을 나타내는 MemoryMemberRepository, DbMemberRepository 등의 이름을 사용할 것이지만,

MemberService의 구현체는 이것 단 하나만 만들 것이므로

이렇게 구현체가 하나뿐일 때의 관례에 따라

인터페이스 이름 뒤에 Impl을 붙인 이름을 사용한다.

 

member 패키지 안에 MemberServiceImpl 클래스를 만든다.

 

 

내용은 이렇게 채워준다.

 

먼저 DI를 해주지 않고 그냥 코드 자체적으로 어떤 MemberRepository 구현체를 사용할지 명시해주었다.

OCP와 DIP를 위반하지만 일단 이렇게 해도 프로그램은 작동하므로 지금은 이렇게 적는다.

(만약 구현체가 아예 지정되지 않은 상태라면 NullPointerException이 발생하므로 이렇게라도 구현체를 명확히 골라주어야 한다.)

 

그 다음 선언한 구현체를 가지고 join과 findMember 메소드를 완성했다.

 

자바의 다형성 덕분에,

join과 findMember 메소드 내에서 save와 findById가 호출되었을 때

MemberRepository 인터페이스의 추상화된 메소드들이 호출되는 것이 아니라

 

 

MemoryMemberRepository 구현체의 메소드들이 실행된다.

 

 

 

 

 

 

다음 회차에는 오늘 짠 코드들이 잘 동작하는지 테스트를 해볼 것이다.