일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 멋사10기
- 멋사11기
- 멋사
- discord
- 기사 제목 크롤링
- ㅏㄴ
- 멋쟁이 사자처럼
- 멋쟁이사자처럼 서류
- 깃허브
- 멋사 합격
- 파이썬 크롤링
- 멋사 면접
- 멋쟁이사자처럼대학
- 디스코드봇
- API
- 백엔드
- 멋쟁이사자처럼11기
- 멋쟁이사자처럼
- 크롤링
- 멋사12
- django
- 멋쟁이사자처럼10기
- 멋사 10기
- 멋사 서류
- 코딩동아리
- 파이썬
- 알림봇
- IT동아리
- 멋사 서류평가
- 웹동아리
- Today
- Total
ACHO.pk devlog
[Springboot] 회원 도메인과 레포지토리 생성 본문
인프런 김영한 강사님의 "스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술"의 강의를 듣고 학습하였습니다.
비즈니스 요구사항 정리
• 데이터: 회원ID, 이름
• 기능: 회원 등록, 조회
• 아직 데이터 저장소가 선정되지 않음(가상의 시나리오)
➥ 단순하게 시작
일반적인 웹 애플리케이션 계층 구조
• 컨트롤러: 웹 MVC의 컨트롤러 역할, api 생성
• 서비스: 비즈니스 도메인 객체를 가지고 핵심 비즈니스 로직 구현(예: 회원 중복 가입 X)
• 리포지토리: 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
• 도메인: 비즈니스 도메인 객체, 예) 회원, 주문, 쿠폰 등등 주로 데이터베이스에 저장하고 관리됨
클래스 의존관계
• 아직 데이터 저장소가 선정되지 않아서, 우선 인터페이스로 구현 클래스를 변경할 수 있도록 설계
• 데이터 저장소는 RDB, NoSQL 등등 다양한 저장소를 고민중인 상황으로 가정
• 개발을 진행하기 위해서 초기 개발 단계에서는 구현체로 가벼운 메모리 기반의 데이터 저장소 사용
회원 도메인과 리포지토리 만들기
① 'domain' 이름의 패키지를 생성한다. (Controller와 같은 위치에 있음)
② domain 패키지 하위에 "Member" 클래스를 생성한다.
③ Member 클래스 내의 코드를 작성해준다.
*Member에는 id와 name이 있다. id는 시스템에 저장을 할 때 등록되며, name은 회원가입할 때 적는 이름이다.
회원 객체
package Springboot.study.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' 이름의 패키지를 생성한다. (Controller와 같은 위치에 있음)
⑤ repository 패키지 하위에 "MemberRepository" 클래스를 생성한다.
⑥ MemberRepository 클래스 내의 코드를 작성해준다.
회원 리포지토리 인터페이스
package Springboot.study.repository;
import Springboot.study.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); //가져온 값이 Null일 경우 Optinal로 감싸서 반환
List<Member> findAll();
}
▹Optional은 Java 8에 들어가있는 기능으로 가져온 값이 Null일 경우 Optinal로 감싸서 반환한다.
▹findAlll() : 모든 회원 반환
⑦ repository 패키지 하위에 "MemoryMemberRepository" 클래스를 생성한다.
⑧ Alt + enter한 후 implement interface 선택 후 코드를 작성한다.(MemberInterface를 implements하는 것임)
⑨ MemoryMemberRepository클래스 내의 코드를 작성해준다.
회원 리포지토리 메모리 구현체
package Springboot.study.repository;
import Springboot.study.domain.Member;
import java.util.*;
public class MemoryMemberRepository implements MemoryMemberRepository {
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
public void clearStore() {
store.clear();
}
}
중요한 코드를 살펴보자.
private static Map<Long, Member> store = new HashMap<>();
★동시성 문제가 고려되어 있지 않다. 공유되는 변수일때는 HashMap 대신 ConcurrentHashMap 사용 고려
private static long sequence = 0L;
★sequence는 0, 1, 2 ... key 값을 생성해준다. 공유되는 변수일때는 long 대신 AtomicLong 사용 고려
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
▹setId할 때 sequence 값을 하나 올려준다.
▹store에 넣기 전에 id를 설정하고, store에 저장을 한다. 스택에 따라 저장된 결과를 반환한다.
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
}
▹store에서 get해서 id를 넣으면 된다.
▹결과가 없을 때는 NULL이 반환될 가능성이 있으므로 Optinal로 감싸서 반환하면 된다.
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
▹ 람다(->)를 사용해서 Member에서 얻은 이름이 파라미터로 넘어온 name과 같은지 확인한다. 같은 경우에만 필터링이 된다.
▹findAny() 하나라도 찾는 것임.
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
▹store에 있는 Member가 반환된다. (여기서 values() == Member)
레포지토리에 작성한 코드가 제대로 동작하는지 검증하기 위해서는 "테스트 케이스 작성"이 중요하다.
'프레임워크 > Springboot' 카테고리의 다른 글
[Springboot] 회원 서비스 개발 및 테스트 (0) | 2023.01.19 |
---|---|
[Springboot] 회원 레포지토리 테스트 케이스 작성 (0) | 2023.01.18 |
[Springboot] 스프링 웹 개발 기초(정적, MVC, 템플릿 엔진, API) (0) | 2023.01.16 |
[Springboot] View 환경 설정 (0) | 2023.01.14 |
[Springboot] 라이브러리 살펴보기 (0) | 2023.01.13 |