스프링

스프링 기본원리 - 김영한 (Entity/Repository/Interface)

ho코딩 2024. 2. 12. 20:40

스프링을 접하면서 너무 많은 개념들과 메서드,기술들이 사용되고 정리가 되지 않아서 

강의를 통한 학습을 하면서 개념과 동작 원리에 대해서 기술 해놓으려고 합니다. 

 

개인적인 공부를 하며 깨닫고 배운 점을 작성하기 때문에 잘못 이해한 부분은 틀릴 수도 있습니다. 

 

 

강의는 인프런 내 - (김영한) 스프링 부트 핵심원리를 수강하였으며 이 강의에서는 

회원이 있는 상점 프로젝트를 진행하였습니다. 

 

<JAVA 17 / Gradle을 사용하였으며 IDE는 Intelij입니다. > 

 

 

 

먼저 회원과 관련된 전체적인 설계도는 이렇습니다. 

 

1) 회원 도메인 설계 

- 회원 서비스는 '회원가입'/'회원조회' 기능으로 이루어져있습니다.

-회원 정보를 저장할 저장소는 '메모리 방식' / '외부 DB 방식'을 구현 해놓고 의존관계 설정에 따라 변경토록 했습니다. 

 

2)회원 클래스 

-회원과 관련된 메서드들을 정의하는 인터페이스와 그 구현체인 "MemberServiceImpl"이 있습니다. 

-구현체는 MemberRepository를 사용합니다. 

 

인터페이스라는 '껍데기'와 구현체라는 '내용물'을 분리하여 진행합니다. 

 

3) 프로젝트 요구사항 

- 회원가입 / 회원 조회가 가능하다.

-회원은 VIP와 일반 두 등급으로 나뉘어있다. 

-회원 데이터는 자체 DB를 구축할 수도 있고, 외부 시스템과 연동할 수 있다. (미정)

 

-회원은 상품을 주문할 수 있다. 

-회원 등급에 따라 할인 정책을 적용할 수 있다. 

-할인 정책은 '정률 할인 정책'/ '정액 할인 정책'으로 나뉜다. 

 

이렇게 세팅이 되어 있고, 본격적으로 코드를 짜보기 시작하겠습니다 . 

 

 

 

Entity(엔터티)  

 

엔터티는 주로 데이터베이스 테이블과 매핑되는 자바 객체를 나타냅니다. 

스프링 프레임워크에서는 주로 객체-관계 매핑(ORM)을 지원하며,

자바 객체와 DB간의 매핑을 쉽게할 수 있도록 도와줍니다 

 

스프링에서는 주로 JPA(Java Persistence API)를 활용하여 DB와의 상호 작용을 처리합니다. 

그리고 JPA는 자바 객체와 DB간의 매핑을 지원하며, 이를 엔터티를 통해 정의합니다. 

 

그러므로 먼저 회원 데이터를 저장할 엔터티부터 정의해봅니다. 

MemberEntity

 

회원이 가지는 정보는 id/ name/ grade 로 설정하였습니다. 

 

또한 Member 생성자를 사용하여 기본적으로 Member 객체를 생성시 id/name/grade 속성을 가질 수 있도록 합니다. 

Member 객체를 생성하고 매개변수로 들어온 값들을 생성된 Member 객체의 값으로 사용하게 됩니다. 

 

아래에는 후에 사용하겠지만 @Getter @Setter 어노테이션이 하는 역할을 수동으로 풀어놓은 것 입니다. 

 

 

 

레포지토리 

다음은 Repository 입니다.

리포지토리는 도메인 객체와 DB간의 상호 작용을 쉽게 관리하기 위한 인터페이스를 제공합니다.

또한, CRUD와 관련된 작업을 수행하는 메서드들을 선언합니다. 

 

즉, CRUD 등 도메인 객체와 DB간의 상호작용을 쉽게 하기 위한 인터페이스 입니다. 

 

이 프로젝트에서는 회원과 관련하여 회원가입을 위한 save / 조회를 위한 findById를 사용할 것이므로 

리포지토리에 save와 findById를 선언합니다. 

 

 

구현체

 

이제 회원과 관련된 엔터티와 리포지토리를 만들었으므로 

리포지토리(인터페이스)를 구현할 '구현체'를 만듭니다. 

 

아까 설계/ 요구사항에서 언급했지만,

메모리를 '메모리 방식'으로 할지, '외부 DB' 방식을 사용할지 정해지지 않은 상태입니다.

그 중에서 먼저 '메모리 방식'을 사용한다고 가정하고, '메모리 방식'의 구현체를 만듭니다. 

 

 

MemberRepository의 구현체임을 나타내야하므로 아래가 추가됩니다. 

 

 MemoryMemberRepository implements MemberRepositoy 

-> MemoryMemberRepository 클래스는 MemberRepository 인터페이스를 구현하고 있다. 

 

Long 타입의 키와 Member 타입의 값을 저장하는 Map 자료구조를 사용합니다. 

HashMap은 Map 자료구조 중 Map 인터페이스를 구현한 클래스 중 하나입니다. 

 

즉, store라는 Long타입의 키와 Member타입의 값을 가지는 HashMap 객체를 생성합니다. 

 

또한 MemberRepository에서 회원과 관련된 CRUD 메서드인 save와 findById의 메서드도 

이곳에 구현합니다. 

 

save 메서드를 살펴보면 

 

먼저 @Overide는

아까 MemberReposioty 인 인터페이스 클래스에서 쓴 save를 여기에서 구현하며 해당 메서드를 재정의하고 있습니다. 

또한 put은 Map 인터페이스 중 하나로 , 특정 키와 값을 매핑하여 맵에 저장하는 역할을 합니다. 

즉, 여기서는 키 값으로는 member.getId() , 값으로는 member를 사용하게 됩니다. 

 

return 역시 동등합니다.

 

멤버 서비스 인터페이스

 

이제 회원과 관련된 기본적인 정보를 저장할 엔터티와 레포지토리, 그 구현체까지 설정했으므로 

 

비즈니스와 관련된 로직. 메서드들을 정의해야합니다. 

 

 

회원 서비스만을 담당할 인터페이스부터 만들어보겠습니다. 

 

 

회원가입과 회원조회 두가지 메서드가 사용됩니다. 

 

 

 

 

그에 대한 구현체 입니다.

MemberService를 구현하고 있는 구현체이고 memberRepository 객체를 생성하여 

생성한 구현체인 MemoryMemberRepository를 주입합니다. 

 

변수의 값이 외부에서 마음대로 재할당되지 않게 하기위해, private final을 설정합니다.

 

join과 findMember 메서드를 구현해줍니다. 

join 메서드는 memberRepository의 save 메서드를 사용하여 member 매개변수를 넘겨줍니다. 

findMember 메서드는 memberRepository의 findById를 사용하여 memberId를 매개변수로 넘깁니다. 

 

 

 

이제 간단한 구현을 마치고, main 클래스를 만들어 봅니다. 

 

 

빼놓은 점이 있는데, 회원의 등급인 BASIC, VIP를 설정할 Enum 파일을 만들어야합니다. 

 

강의 내용을 따라가며 리뷰하는 느낌으로 블로그를 작성하고 있는데, 강의 내용상 

처음에는 스프링이 제공하는 것은 사용하지 않고 온전히 JAVA를 이용하여 진행하고 있습니다. 

 

때문에 지금 작성한 글에서는 OCP 원칙 DIP 원칙 등 SOLID라는 불리는 객체지향 원리가 

제대로 적용되지 않고 있습니다. 

 

다음시간에는 어떤 원리, 원칙등이 제대로 지켜지지 않고 있는지에 대해서 다루어 보겠습니다