웹개발

[스프링 입문 김영한 인프런] 섹션 3. 회원 관리 예제 - 회원 도메인과 리포지토리 만들기

하고파 2023. 10. 11. 21:47

 

 

[무료] 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다., 스프링 학습 첫 길잡이! 개발 공부의 길을 잃지 않도록 도와드립니다. 📣 확인해주세

www.inflearn.com

유명한 김영한님 스프링 입문 강의를 듣는 중이다.

너무 빠르게 지나가서..하나하나 코드 뜯어보려고 노력중이다.

<섹션 3. 회원 관리 예제 - 회원 도메인과 리포지토리 만들기>에서는 Member Class와 MemberRepository Interface, 그리고 MemoryMemberRepository Class를 생성하였다.

이 세 개의 관계성은 이전 게시물에서 볼 수 있는데, 간단히 또 정리하면

MemoryMemberRepository가 DB에 해당하는데, DB로 뭘 쓸지 아직 안 정해진 상황이라서 불확실한 MemoryMemberRepository를 함부로 쓸 수 없는 상황. 그래서 MemberRepository 인터페이스를 일단 사용하는 거다. 인터페이스를 통해 DB에 정보를 저장하고, 관리할 수 있으니까.

 

[스프링 입문 김영한 인프런] 섹션 3. 회원 관리 예제 - 비즈니스 요구사항 정리

데이터 회원ID, 이름 기능 회원 등록, 조회 추가) 아직 DB가 선정되지 않은 가상의 시나리오 설정이 있다 DB가 아직 선정이 안 되었으니 Memory MemberRepository 사용

kmina02.tistory.com

1. Member Class 생성

Member Class 안에는 회원의 정보가 들어간다.

    private Long id;
    private String name;
  변수명 자료형 접근 제한자
회원의 id id Long(정수) private
회원의 이름 name String private

Getter and Setter 메서드를 이용해서 id에 접근하고, 값을 가져오거나 설정한다.

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

getId() 메서드는 현재 객체의 id 값을 반환하고, setId(Long id) 메서드는 주어진 값을 객체의 id에 할당한다.

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}

getName() 메서드는 현재 객체의 name 값을 반환하고, setName(String name) 메서드는 주어진 값을 객체의 name에 할당한다.

2. MemberRepository Interface 생성

Member 객체를 저장하고 조회하는 인터페이스.쉽게 말해 회원정보를 저장하는 DB 역할 + 회원정보를 열람할 수 있는 기능

    Member save(Member member);

save니까 말 그대로 저장하는 메서드. 전달받은 Member 객체를 저장소(MemberRepository)에 저장하고, 저장된 Member 객체를 반환한다.

Optional<Member> findById(Long id);

findById, 즉 id값으로 Member 객체를 찾아 반환하는 메서드. Optional은 NULL값을 다루기 위한 것으로, Member가 존재하지 않을 경우 Optional.empty()를 반환한다.

Optional<Member> findByName(String name);

findByName, 즉 name값으로 Member 객체를 찾아 반환하는 메서드. Optional은 NULL값을 다루기 위한 것으로, Member가 존재하지 않을 경우 Optional.empty()를 반환한다.

List<Member> findAll();

모든 Member 객체의 리스트를 반환하는 메서드이다.

그래서! 결론을 말하자면 MemberRepository 인터페이스는 다른 종류의 저장소(여기서는 뒤에 나올 MemoryMemberRepository)에서 회원 정보를 관리하기 위해 사용되는 일종의 계약서라고 생각하면 된다.

MemberRepository에서는 멤버 정보를 저장하고 조회하는 역할을 한다.

계약서에는 지시사항들이 적혀있으니..그 지시사항들을 따라서 다른 종류의 저장소인 MemoryMemberRepository에서 회원 정보를 관리하면 된다.

3. MemoryMemberRepository Class 생성

여기부분은..설명이 너무 빨라서 솔직히 무슨 소리인지 하나도 모르겠다..

나를 구원해주는 건 오직 생성형 AI뿐.

일단 이 클래스는 앞에서 만든 MemberRepository 인터페이스를 구현한 클래스이고,
메모리 상에서 멤버 정보를 저장하고 조회하는 역할을 수행한다.

3-1.  Member 객체를 저장하기 위한 HashMap을 만든다.

private static Map<Long, Member> store = new HashMap<>();

Map은 "키-값" 쌍으로 이루어져 있는데, 여기서 키(Key)는 Long 타입의 id가 사용되고, 값(Value)는 Member 객체가 사용된다.

3-2. 1씩 증가할 sequence 변수 설정

private static long sequence = 0L;

정수인 sequence 변수를 만드는데, 초기값을 0으로 설정한다. Long 타입이라 0뒤에 L이 붙는다. 
나중에 save() 메서드에서 호출될 때마다 1씩 증가하여 각 Member 객체에 고유한 id를 할당한다.
그러니까 각 사람별 아이디는 0, 1, 2 ...가 되는 셈이다.

3-3. @Override 어노테이션으로 MemberRepository 인터페이스에서 상속받은 메서드 재정의

@Override
public Member save(Member member) {
    member.setId(++sequence);
    store.put(member.getId(), member);
    return member;
}

여기서는 MemberRepository 인터페이스에 있던 save() 메서드를 재정의하고 있다.

member.setId(++sequence);

member에 setId를 적용해서 sequence+1만큼의 숫자를 id값에 집어넣는다.

즉, Member 객체의 id 값을 sequence+1로 설정하고 있다.

store.put(member.getId(), member);

해당 id와 이름(name)을 가진 member 객체를 저장소에 저장한다.

따라서 <sequence+1, name> 형태의 데이터가 member 객체에 저장되어 저장소(Repository)에 보관된다.

3-4. findById(Long id) 메서드를 구현

@Override
public Optional<Member> findById(Long id) {
    return Optional.ofNullable(store.get(id));
}

Long(정수) 타입의 id를 통해 그 id값에 해당하는 Member 객체를 찾는다.

- Optional.ofNullable() 메서드: 괄호 속 객체를 Optional 객체로 감싸주어 Optional 객체로 만들어 반환한다.

지금 여기서는 괄호 속 객체가 store.get(id)이다.

즉 store.get(id)를 통해 가져온 Member 객체를 Optional 객체로 만들어 반환한다.

3-5. findAll() 메서드 재정의

@Override
public List<Member> findAll() {
    return new ArrayList<>(store.values()); }

findAll() 메서드를 재정의(Override)하고 있다. 여기서 findAll() 메서드가 List<Member>를 반환한다.
이 메서드는 store라는 변수에 있는 키-값 중 모든 값들을 가져와 새로운 ArrayList에 담아 보관한다.

3-6. 멤버 객체 찾아서 반환

@Override
public Optional<Member> findByName(String name) {
    return store.values().stream()
            .filter(member -> member.getName().equals(name))
            .findAny();
}

findByName() 메서드의 입력값은 문자열 name이고, Member를 반환한다.
name이 같은 Member를 찾아서 반환한다.

3-7. clearStore() 메서드로 store라는 객체나 컬렉션을 지운다

public void clearStore() {
    store.clear();
}