Java / Spring
Web 기초 설계 본문
Spring, Web 개발 기초
1. 웹 어플리케이션 계층 구조를 설계 한다.
(기본적인 어플리케이션 설계 시 컨트롤러, 서비스, 리포지토리, 도메인으로 설계 한다. (*DB 미선정 상태 가정))
- 컨트롤러 : 웹 MVC의 컨트롤러 역할
- 서비스 : 핵심 비즈니스 로직 구현
- 리포지토리 : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
- 도메인 : 비즈니스 도메인 객체, ex ) 회원, 주문, 쿠폰 등등 데이터베이스에 저장하고 관리됨.
2. 클래스와 의존 관계
- 아직 DB 미선정으로, 인터페이스로 구현 클래스를 변경할 수 있도록 설계 할 예정이다.
(메모리를 인터페이스를 통해 넣고, 뺄 수 있는 기능)
3. 도메인 (domain)
- id 와 name 을 정의할 도메인 Member 클래스 설계 (getter & setter)
public class Member {
private String name;
private Long id; // 시스템이 저장하는 id (임의)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
4-1. 저장소 (Repository) - Interface 설계 (기능 정의)
- 인터페이스를 설계하고 총 4가지의 기능을 정의 하였다.
1) 회원 이름을 저장하는 기능 : save();
2) DB 에서 회원 아이디를 찾는 기능 : findById();
3) DB 에서 회원 이름을 찾는 기능 : findByName();
4) DB 에서 저장된 모든 데이터 조회 : findAll();
public interface MemberRepository {
Member save(Member member); // save : 회원이 저장
Optional<Member> findById(Long id); // 저장소에서 회원 아이디 찾기
Optional<Member> findByName(String name); // 저장소에서 회원이름 찾기
List<Member> findAll(); // 저장소에서 회원 리스트 전체 반환
}
* Optional<> : nullPointException 을 처리하기 위해 findById 와 findByName 을 Optional 이라는 클래스로 감싸서 정의 하였다.
사용 예)
Optional.ofNullable(store.get(id));
@Override
// 저장된 id를 꺼내오는 찾는 기능 (꺼냄)
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id)); // id를 꺼낼 때 NPE 를 방지하기 위해 Optional.ofNullable 로 get(id) 를 감싸준다.
}
4-2. 저장소(Repository) - Interface 에서 정의한 기능을 구현할 class 설계
@Repository
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L; // key 값을 생성해주는 변수
@Override
// id를 setting 을 하고 store 에 저장 해주는 기능
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
// 저장된 id를 찾는 기능 (꺼냄)
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id)); // id를 꺼낼 때 NPE 를 방지하기 위해 Optional.ofNullable 로 get(id) 를 감싸준다.
}
@Override
// 저장된 name 을 꺼내오는 기능
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();
}
}
5. 회원 서비스 클래스 설계 (실제 비즈니스 로직 작성) - 회원 가입, 조회, 이벤트 발생 로직 처리
(중복 가입 시 별도의 메세지 출력 등)
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class MemberService {
private final MemberRepository memberRepository;
// Dependency Injection (의존성 주입) ??..
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
/**
* 회원 가입 로직
*/
public Long join(Member member) {
// 같은 이름이 있는 중복 회원 불가
validateDuplicateMember(member); // 하위 메서드로부터 정의된 중복회원 검증 기능을 join 시 호출 하여 수행
memberRepository.save(member);
return member.getId();
}
// 중복회원 검증 기능을 별로의 메서드(validateDuplicateMember)로 구현
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
/**
* 전체 회원 조회 로직
*/
public List<Member> findMembers() {
return memberRepository.findAll();
}
// id를 조회 했을 때
public Optional<Member> findOne(Long memberId) {
return memberRepository.findById(memberId);
}
}
'Spring > Framwork' 카테고리의 다른 글
DI (Dependency Injection) (1) | 2024.05.01 |
---|---|
2. Web 기초 설계 - Controller 설계와 Spring Bean & 의존 관계 (0) | 2024.04.30 |
BeanFactory & ApplicationContext 간단 설명 (0) | 2024.03.28 |
IoC 란? (0) | 2024.03.28 |
DI 컨테이너 란? (0) | 2024.03.26 |