hoon's bLog

Spring gradle project 환경설정 및 회원 가입 서비스 예제 만들기 본문

IT/Spring

Spring gradle project 환경설정 및 회원 가입 서비스 예제 만들기

개발한기발자 2024. 3. 21. 08:24
반응형


본 포스팅은 인프런에 있는 인터넷 강좌인,

김영한 강사님의 스프링 핵심 원리 기본편을 공부하며,

개인적으로 공부하고, 정리하는 용도로 포스팅을 해보겠다.

2. 스프링 핵심 원리 이해1 - 환경설정 및 회원 가입 서비스 예제 만들기

예제 만들기 전 간단하게 Spring 프로젝트 환경설정에 대해서 알아보자.

프로젝트 생성을 위한 Spec 사항은 다음과 같다.

  • Project : Gradle - Groovy Project Spring Boot: 3.x.x
    Language : Java
    Packaging : Jar
    Java : 17 또는 21(오류의 최소화를 위해 17 버전 사용)
  • Project Metadata
    groupId : hello
    artifactId : core
    Dependencies: 선택하지 않는다.

Spring Initalizr 공식 페이지에 들어가서 아래와 같이 선택 후 Generate 버튼을 눌러주면,

spring initializr에서 옵션 설정 후 Generate

 다운로드 폴더에 아래와 같이 demo.zip 파일이 생긴다.

그러고 나서 압축 파일을 해제하면 demo 프로젝트가 생긴다!

아래는 build.gradle 파일의 설정 값들이다.

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.1'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'hello'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

필자는 demo.zip 파일명을 core로 바꿔서 아래와 같이 프로젝트를 변경해서 아래와 같이 프로젝트가 구성되었다.

여기까지가 간단한 Spring Project 셋팅 완료!

비즈니스 요구사항과 설계

  • 회원
    • 회원을 가입하고 조회할 수 있다.
    • 회원은 일반과 VIP 두 가지 등급이 있다.
    • 회원 데이터는 자체 DB를 구축할 수 있고, 외부 시스템과 연동할 수 있다. (미확정)
  • 주문과 할인 정책
    • 회원은 상품을 주문할 수 있다.
    • 회원 등급에 따라 할인 정책을 적용할 수 있다.
    • 할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인을 적용해 달라. (나중에 변경될 수 있다.)
    • 할인 정책은 변경 가능성이 높다. 회사의 기본 할인 정책을 아직 정하지 못했고, 오픈 직전까지 고민을 미루고 싶다. 최악의 경우 할인을 적용하지 않을 수 도 있다. (미확정)
  • 요구사항을 보면 회원 데이터, 할인 정책 같은 부분은 지금 결정하기 어려운 부분이다
  • 그렇다고 이런 정책이 결정될 때 까지 개발을 계속 기다릴 수 도 없기 때문에, 인터페이스를 만들고 구현체를 갈아 끼울수 있도록 객체 지향 설계를 이용하면 된다!!!

회원 도메인 및 클래스/객체 다이어그램 설계

  • 위 요구사항을 설계하기 위해 각 협력 관계를 위한 도메인 다이어 그램을 만든다.

회원 등급 클래스

  • enum 클래스를 이용해 회원 등급별 일반 회원(BASIC)과 VIP 회원(VIP)을 정의
  • 이를 통해 회원 등급을 다른 클래스에서 상수처럼 사용할 수 있다.
package hello.core.member;

public enum Grade {
    BASIC,
    VIP
}

회원 정보 클래스

  • 회원의 id, 이름, 등급 정보를 담는 클래스를 생성
  • 각 정보를 가져오고, 설정할 수 있는 getter와 setter 메서드 생성
  • @Data Annotation을 사용하면 굳이 이렇게 다 작성하지 않아도 알아서 생성되어 사용할 수 있다!
package hello.core.member;

public class Member {
    private Long id;        // 회원 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;
    }
}

 

회원 저장소 인터페이스

  • 회원정보를 저장(save)하고 회원의 정보를 id로 조회(findMember)하는 역할의 인터페이스 생성
package hello.core.member;

public interface MemberRepository {
    // 회원 저장
    void save(Member member);

    // 회원 id로 찾기
    Member findById(Long memberId);
}

 

메모리 회원 저장소 인터페이스

  • 회원정보를 가입(join)하고 회원의 정보를 조회(findMember)하는 역할의 인터페이스 생성
  • 나중에 데이터베이스나 외부 저장소를 사용하는 Repository로 교체할 때 이 클래스를 대체할 수 있다
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<>();

    @Override
    public void save(Member member) {
        store.put(member.getId(), member);
    }

    @Override
    public Member findById(Long memberId) {
        return store.get(memberId);
    }
}

 

회원 서비스 인터페이스

  • 회원정보를 가입(join)하고 회원의 정보를 조회(findMember)하는 역할의 인터페이스 생성
package hello.core.member;

public interface MemberService {
    // 회원 가입
    void join(Member member);
    // 회원 조회
    Member findMember(Long memberId);
}

회원 서비스 구현체

  • MemberService 인터페이스의 규약에 따라 회원 가입과 회원 조회 기능을 가지고 있는 구현 클래스 생성
  • 실제로는 MemoryMemberRepository를 사용하여 회원 정보를 메모리에 저장하고 조회한다.
package hello.core.member;

public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository = new MemoryMemberRepository();

    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

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

이제 구현한 인터페이스와 구현 클래스를 이용해서 테스트 코드를 만들면 다음과 같다.

회원가입 테스트 코드

package hello.core.member;

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

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

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);
    }
}
  • MemberServiceTest 클래스는 MemberService의 구현체인 MemberServiceImpl을 테스트한다.
  • line 15 : 가입할 회원 객체 생성
  • line 18 : join 메서드를 호출하여 회원 가입
  • line 22 :  findMember() 메서드를 호출하여 가입된 회원을 조회한 후에, assertThat()을 사용하여 예상한 값과 실제 값이 일치하는지를 검증

우선 이 정도로 회원 도메인 다이어그램을 인터페이스와 구현 클래스로 설계해 봤다.

다음 포스팅에는 이어서 주문/할인 도메인 설계에 대해 알아보겠다.

728x90
반응형