You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
일반적인 웹 애플리케이션 계층은 보통 컨트롤러, 서비스, 리포지토리, 도메인 개체, 데이터베이스로 구성 됨
컨트롤러 : 웹 MVC의 컨트롤러 역할
서비스 : 핵심 비즈니스 로직을 구현 (ex, 회원은 중복 가입이 불가능함), 비즈니스 도메인 객체를 가지고 핵심 비즈니스 로직이 동작하도록 구현한 객체
리포지토리 : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
도메인 : 데이터 베이스에 주로 저장하고 관리되는 비즈니스 도메인 객체 (ex, 회원, 주문, 쿠폰 등)
MemberService : 회원 비즈니스 로직 (서비스)
MemberRepository : 회원을 저장하는 것은 인터페이스로 구현
아직 데이터 저장소가 선정되지 않았다는 시나리오에 의해, 회원 리포지터리 인터페이스를 만들고 구현체를 MemoryMemberRepository 메모리 모드로 단순하게 저장한다. (**)
회원 도메인과 리포지트리 만들기
domain/member
package hello.hellospring.domain;
public class Member {
// 요구사항에 명시되어있는 2가지 정보
private Long id; // 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/MemberRepository
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); // id로 회원을 조회한다.
Optional<Member> findByName(String name); // name으로 회원을 조회한다.
List<Member> findAll(); // 저장된 모든 회원 리스트를 모두 반환한다.
}
repository/MemoryMemberRepository
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.put(member.getId(), member); // store에 저장
return member; // 저장된 결과 반환
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
// null이 반환될 가능성도 있기 때문에 Optional을 이용한다.
// Optional.ofNullable로 감싸서 null일때의 처리를 함
}
@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());
}
}
회원 리포지트리 테스트 케이스 작성
코드가 정상동작하는지 해당 기능을 실행해보아야 한다.
자바는 JUnit이라는 프레임워크를 제공하여 테스트를 실행할 수 있게 한다.
test/java/hello/hellospring/repository/MemoryMemberRepositoryTest
테스트하는 코드는 test 폴더에 생성해야하며, 테스트하는파일이름 뒤에 Test를 붙여 생성하는 것이 관례이다.
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.*;
public class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach(){
repository.clearStore(); // 테스트가 실행이 되고 끝날 때마다 한 번씩 저장소를 다 치운다.
}
@Test
public void save(){
Member member = new Member();
member.setName("spring");
repository.save(member);
Member result = repository.findById(member.getId()).get();
assertThat(member).isEqualTo(result); // member와 result와 같은지 ?
}
@Test
public void findByName(){
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
Member result = repository.findByName("spring1").get();
assertThat(result).isEqualTo(member1);
}
@Test
public void findAll() {
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
}
각각의 테스트 케이스를 돌리고 모두 정상 작동이 되는 것을 확인한 후에 한꺼번에 테스트를 돌려보았을 때 갑자기 에러가 나는 이유 ?
데스트의 순서는 보장이 되지 않는다. 모든 테스트는 순서와 상관없이 메소드별로 다 따로 동작하게끔 설계를 해야한다. 따라서, 테스트가 하나 끝나고나면 데이터를 클리어 해줘야 한다.
repository/MemoryMemberRepository에 메서드 추가 작성
public void clearStore(){
store.clear(); // store를 비운다.
}
회원 서비스 개발
회원 리포지토리와 도메인을 활용하여 실제 비즈니스 로직을 작성하는 부분
main/hello/hellospring/service/MemberService
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import java.util.List;
import java.util.Optional;
public class MemberService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
// 회원가입
public Long join(Member member){
// 같은 이름이 있는 중복 회원 X
validateDuplicateMember(member); // 중복 회원 검증
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
// 전체 회원 조회
public List<Member> findMembers(){
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId){
return memberRepository.findById(memberId);
}
}
보통 서비스는 비즈니스에 의존적으로 설계를 하고, 리포지토리는 서비스보다는 단순히 기계적으로 개발스러운 용어들을 사용한다. (단순히 데이터를 넣고 빼는 것)
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemoryMemberRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Optional;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
// 각 테스트를 실행하기 전에
@BeforeEach
public void beforeEach(){
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
@AfterEach
public void afterEach(){
memberRepository.clearStore(); // 테스트 각각 실행될 때마다 메모리 클리어
}
@Test
void 회원가입() {
// given -> 무언가가 주어졌는데
Member member = new Member();
member.setName("spring");
// when -> 이것을 실행했을 때
Long saveId = memberService.join(member);
// then -> 이러한 결과가 나와야 한다.
Member findMember = memberService.findOne(saveId).get();
assertThat(member.getName()).isEqualTo(findMember.getName()); // static import 단축키 - command + enter
}
@Test
public void 중복_회원_예외() {
// given
Member member1 = new Member();
member1.setName("spring");
Member member2 = new Member();
member2.setName("spring");
// when
memberService.join(member1);
// memberService.join(member2); // 중복회원을 임의로 넣어본다.
/* try {
memberService.join(member2);
fail();
} catch (IllegalStateException e){
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
}*/
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
// then
}
@Test
void findMembers() {
}
@Test
void findOne() {
}
}
main/java/hello/hellospring/service/MemberService 내의 코드 수정
private final MemberRepository memberRepository;
// new하지 않고, 외부에서 메모리멤버 리포지토리를 넣어준다.
// -> DI(Dependency Injection)
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
3_회원 관리 예제 - 백엔드 개발
비즈니스 요구사항 정리
MemberService: 회원 비즈니스 로직 (서비스)MemberRepository: 회원을 저장하는 것은 인터페이스로 구현MemoryMemberRepository메모리 모드로 단순하게 저장한다. (**)회원 도메인과 리포지트리 만들기
domain/memberrepository/MemberRepositoryrepository/MemoryMemberRepository회원 리포지트리 테스트 케이스 작성
코드가 정상동작하는지 해당 기능을 실행해보아야 한다.
자바는 JUnit이라는 프레임워크를 제공하여 테스트를 실행할 수 있게 한다.
test/java/hello/hellospring/repository/MemoryMemberRepositoryTest테스트하는 코드는 test 폴더에 생성해야하며, 테스트하는파일이름 뒤에 Test를 붙여 생성하는 것이 관례이다.
각각의 테스트 케이스를 돌리고 모두 정상 작동이 되는 것을 확인한 후에 한꺼번에 테스트를 돌려보았을 때 갑자기 에러가 나는 이유 ?
repository/MemoryMemberRepository에 메서드 추가 작성회원 서비스 개발
회원 리포지토리와 도메인을 활용하여 실제 비즈니스 로직을 작성하는 부분
main/hello/hellospring/service/MemberService보통 서비스는 비즈니스에 의존적으로 설계를 하고, 리포지토리는 서비스보다는 단순히 기계적으로 개발스러운 용어들을 사용한다. (단순히 데이터를 넣고 빼는 것)
회원 서비스 테스트
test/java/hello/hellospring/service/MemberServiceTestmain/java/hello/hellospring/service/MemberService내의 코드 수정Beta Was this translation helpful? Give feedback.
All reactions