회원관리 예제
오늘 회원관리라는 예제를 통해 벡엔드 개발을 해보면서 spring을 본격적으로 학습하는 첫걸음을 내딛게 되었다. 회원관리 서비스를 구현하기 위해서는
다음과 같은 스테이지를 거쳐야했다. 먼저 비즈니스 요구사항이라함은 실제로 어떤 DB들이 입력되고 산출될것인가에 대한 선정 이슈와 어떠한 기능을 제공할것인지에 대한 선정 이슈였다. 본 예제는 간단한 서비스를 구현하는것이 목적이므로 회원ID와 이름 데이터로 구현이 가능하게끔 만들었다. 기능 또한 단순하게 회원을 등록하고 조회하는 식으로 동작 가능하도록 하였다. 또한 아직 데이터 저장소가 선정되지 않았음을 가정했다.
구현에 앞서 일반적인 웹 애플리케이션이 어떠한 계층 구조를 가지고 동작하는지를 학습하였다.
이를 통해 개발자는 이제 단순히 코딩만 하는것이 아니라 여러 도메인과 리포지토리의 관계, 서비스 측면에서 컨트롤러에 추가되어야할 기능 등등을 고려해야함을 알게 되었고, 이러한 스킬들을 가지고 능숙하게 해낼 수 있어야 좋은 프로그래머가 되지않을까란 생각을 해보았다.
각설하고
domain & repository
오늘 배운내용은 회원도메인과 리포지토리를 만드는 것이었다. 먼저 hello.hellospring package에 domain package를 생성하고 Member class를 생성한다.
그 후, Member class에 다음과 같이 비즈니스 요구사항에 따라 멤버변수를 정의한다.
package hello.hellospring.domain;
public class Member {
private Long id;
private String name;
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;
}
}
이 후, repository(저장소) package를 생성하고 다른 class에서도 가져다 쓸 수 있게끔 MemberRepository interface를 생성한다.
MemberRepository interface에 들어갈 내용은 다음과 같다.
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.List;
import java.util.Optional;
public interface MemberRepository {
Member save(Member member);
Optional<Member> findById(Long Id);
Optional<Member> findByName(String name);
List<Member> findAll();
}
MemberRepository interface의 멤버변수들을 설명하자면,
Member save(Member member);
-> 회원을 저장하는 용도 Optional <Member> findById(Long Id);
-> ID로 회원을 찾는 용도Optional<Member> findByName(String name);
-> 이름으로 회원을 찾는 용도List<Member> findAll();
-> 리스트에 해당하는 모든 회원을 찾음interface를 만들었으니, 실제로 구현체를 만들어보겠다. 먼저, repository package 안에 MemoryMemberRepository class를 생성한다.
그 후, class 파일 안에 들어갈 내용이다.
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.*;
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
@Override
public Member save(Member member) {
member.setId(++sequence); // store에 넣기전에 member에 Id값을 할당
// (이름은 이미 회원가입할때 입력받으므로 don't care)
store.put(member.getId(), member); //store에 저장 (Map에 저장됨)
return member;
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id)); // store.get(id). 즉,store에서 꺼내면됨
// but, null이 반환될 가능성이 있기 때문에 Optional로 감싼다.
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream() // loop를 돌게함
.filter(member -> member.getName().equals(name)) // 람다 사용
// (member.getName이 parameter로 넘어온 name과 같은지 체크)
.findAny(); // loop를 돌면서 Map에서 찾아지면 반환
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values()); // store의 멤버들을 반환해줌
}
}
주석들을 참고.
마무리하며....
이로써 모든 구현이 끝나고, Test case를 작성하는것은 다음 목표이다.
강의를 들으면서 학부때 공부했던 자바 백그라운드 지식들이 많이 등장했는데, 개념을 다시금 잡아야겠다는 생각이 들었다. HashMap이나 get, put과 같은 내용이 생소했다. 특히, Optional이라는 클래스는 이번기회에 새롭게 알게되었고 잘 숙지해야겠다.