본문 바로가기
[inflearn] 스프링 핵심 원리 - 기본편/섹션 2 - 예제 만들기

7. 회원 도메인 개발

by 슬픈 야옹이 2023. 9. 27.

지난 포스트의 설계를 바탕으로 실제 회원 도메인을 개발해본다.

설계가 잘 되었다면, 설계한대로 코드만 잘 작성해도 동작에 문제가 없어야 한다.

 

https://debuggingworld.tistory.com/83

 

5. 비즈니스 요구사항과 회원 도메인 설계

다음 정의된 비즈니스 요구사항에 따라 도메인을 설계하고 개발해본다. 비즈니스 요구사항 회원 회원을 가입하고 조회할 수 있다. 회원은 일반과 VIP 두 가지 등급이 있다. 회원 데이터는 자체 DB

debuggingworld.tistory.com

 

 

1. 패키지 생성

core 패키지 하위에 member 패키지를 생성한다.

member 패키지 생성

 

이제부터 회원과 관련된 클래스들은 member 패키지에 생성하고 관리할 것이다.

 

 

2. 회원 도메인 설계

지난 포스트에 따르면, 회원 도메인 요구사항, 협력관계, 클래스 다이어그램은 다음과 같다.

  • 회원 도메인 요구사항
    • 회원을 가입하고 조회할 수 있다.
    • 회원은 일반과 VIP 두 가지 등급이 있다.
    • 회원 데이터는 자체 DB를 구축할 수 있고, 외부 시스템과 연동할 수 있다. (미확정)

회원 도메인협력관계
회원 클래스 다이어그램

 

 

 

3. 회원 도메인 개발

 

3-1. 회원 엔티티

회원 등급과 회원 엔티티 클래스를 생성한다.

 

도메인 요구사항에 따르면, 회원 등급은 일반과 VIP 두 등급으로 나뉜다.

enum으로 생성한다.

Grade.java

 

Grade.java

package hdxian.hdxianspringcore.member;

public enum Grade {
    BASIC,
    VIP
}

 

 

회원 클래스를 생성한다.

회원은 id, 이름, 등급 세 가지의 속성을 가지고,  getter와 setter를 가진 간단한 클래스다.

Member.java

 

Member.java

package hdxian.hdxianspringcore.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;
    }

}

 

 

3-2. 회원 저장소

도메인 요구사항에 따르면, 회원 가입과 조회 기능을 제공해야 한다.

 

회원 저장소 인터페이스를 생성한다.

회원 정보를 저장하는 기능과 Id 기반 조회 기능을 제공하는 간단한 인터페이스다.

MemberRepository.java

 

MemberRepository.java

package hdxian.hdxianspringcore.member;

public interface MemberRepository {
    void save(Member member);
    Member findById(Long memberId);
}

 

 

회원 저장소의 구현체를 생성한다.

회원 정보를 어디에서 관리할지 아직 정해지지 않았으므로, 테스트 용도로 MemoryMemberRepository 클래스를 생성한다.

MemoryMemberRepository는 개발 및 테스트 용도의 가장 단순한 저장소로, 나중에 다른 구현체로 대체될 것이다.

 

 

MemoryMemberRepository.java

 

MemoryMemberRepository.java

package hdxian.hdxianspringcore.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);
    }

}

 

+) 동시성 문제와 HashMap

회원 저장소 같은 경우 여러 곳에서 동시에 데이터를 접근할 가능성이 높다.

이러한 경우 저장소의 데이터 접근에 대한 동시성 문제를 고려해야 하는데. HashMap은 이를 고려하지 않는 자료구조다.

따라서, 동시성 문제를 해결하기 위해서는 HashTable, concurrentHaspMap 등을 사용해야 한다.

하지만 이 클래스는 단순 테스트 용도이기 때문에 본 예제에서 적용하지 않았다.

 

 

 

3-3. 회원 서비스

도메인 협력 관계에 따르면 회원 서비스는 회원 저장소를 통해 회원 가입과 조회 기능을 제공한다.

 

이를 바탕으로 회원 서비스 인터페이스를 생성한다.

MemberService.java

 

MemberService.java

package hdxian.hdxianspringcore.member;

public interface MemberService {

    void join(Member member);
    Member findMember(Long memberId);

}

 

 

회원 서비스 구현체도 생성한다.

memberRepository 참조변수를 통해 MemoryMemberRepository 객체에 접근하여 회원 가입 및 조회 기능을 제공한다.

MemberServiceImpl.java

 

MemberServiceImpl.java

package hdxian.hdxianspringcore.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);
    }
}

 

 

다음 포스트에서는 개발한 회원 도메인을 테스트해본다.