섹션 4. 회원 관리 예제-백엔드 개발
비즈니스 요구사항 정리
데이터: 회원ID,이름
기능: 회원 등록,조회
아직 데이터 저장소가 선정되지 않음(가상의 시나리오)
컨트롤러: 웹 MVC의 컨트롤러 역할
서비스: 핵심 비즈니스 로직 구현
리포지토리: 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
도메인: 비즈니스 도메인 객체, 예) 회원, 주문, 쿠폰 등등 주로 데이터베이스에 저장하고 관리됨
DB: 실제 데이터들이 저장되는 곳
아직 데이터 저장소가 선정되지 않아 인터페이스로 구현클래스를 변경할 수 있도록 설계
데이터 저장소는 RDB,NoSQL 등 다양한 저장소 고민
초기 개발 단계에서 구현체로 가벼운 메모리 기반 DB사용
회원 도메인과 리포지토리 만들기
Member save(Member member): 회원 저장
Optional<Member> findById(Long id):ID로 회원을 찾음
Optional<Member> findByName(String name):회원 이름을 찾음
List<Member> findAll():저장소에 있는 모든 회원 목록 반환
값이 없을 수도 있는 경우 optional 사용
회원 리포지토리 테스트 케이스 작성
command+shift+enter: 바로 다음줄로 넘어가짐
package hello.hello.spring.repository;
import hello.hello.spring.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.*;
class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach() {
repository.clearStore();
}
@Test
public void save() {
//given
Member member = new Member();
member.setName("spring");
//when
repository.save(member);
//then
Member result = repository.findById(member.getId()).get();
assertThat(result).isEqualTo(member);
}
@Test
public void findByName() {
//given
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
//when
Member result = repository.findByName("spring1").get();
//then
assertThat(result).isEqualTo(member1);
}
@Test
public void findAll() {
//given
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
//when
List<Member> result = repository.findAll();
//then
assertThat(result.size()).isEqualTo(2);
}
}
MemoryMemberRepositoryTest는 MemoryMemberRepository 클래스의 단위 테스트를 위한 테스트 클래스
@AfterEach는 각 테스트가 끝난 후마다 실행되는 메서드를 지정
save() 메서드가 Member 객체를 제대로 저장하는지 테스트
findByName() 메서드가 제대로 동작하는지 테스트
findAll() 메서드가 저장된 모든 회원을 제대로 반환하는지 테스트
회원 서비스 개발
public Long join(Member member) {
validateDuplicateMember(member); //중복 회원 검증 memberRepository.save(member);
return member.getId();
}
중복되는 회원이 있는지 검증
public List<Member> findMembers() {
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId) {
return memberRepository.findById(memberId);
}
}
전체 회원 조회
회원 서비스 테스트
![]() |
![]() |
command+shift+t 테스트 생성 단축키
@BeforeEach
public void beforeEach() {
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
독립적 환경을 만들어줌
@AfterEach
public void afterEach() {
memberRepository.clearStore();
}
저장된 데이터를 삭제해서 다음 테스트가 이전 테스트에 영향을 주지 않도록 함
extract method를 할때 뭔가 잘못해서 오류가 떴었지만 수정을 한 뒤 잘 돌아가는 모오습~
섹션 5. 스프링 빈과 의존관계
컴포넌트 스캔과 자동 의존관계 설정
컨트롤러 파일 생성
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
생성자에 Autowired로 되어 있으면 멤버서비스를 스피링이 스프링 컨테이너에 있는 멤버 서비스를 가져다가 연결을 시켜줌
MemberService가 순수 자바코드기 때문
@Service를 위에 입력해주면 스프링컨테이너에 멤버 서비스를 등록해줌
의존성 주입 (Dependency Injection, DI)
의존성 주입(Dependency Injection)은 소프트웨어 디자인 패턴의 하나로 객체가 필요로 하는 의존성(다른 객체)을 직접 생성하거나 찾지 않고, 외부로부터 제공(주입)받는 방식을 의미. 이는 객체 간의 결합도를 낮추고 코드의 재사용성, 테스트 용이성, 유지보수성을 향상시키는 중요한 원칙이다.
@Autowired 어노테이션을 생성자에 붙여서 스프링 컨테이너에게 해당 타입의 빈을 찾아 생성 시점에 주입하도록 지시.
자바 코드로 직접 스프링 빈 등록하기
package hello.hello.spring.service;
import hello.hello.spring.repository.MemberRepository;
import hello.hello.spring.repository.MemoryMemberRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
DI에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있다. 의존관계가 실행중에 동적으 로 변하는 경우는 거의 없으므로 생성자 주입을 권장.
주의: @Autowired를 통한 DI는 helloController, memberService 등과 같이 스프링이 관리하 는 객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.
'WINK-(Web & App) > Spring Boot 스터디' 카테고리의 다른 글
[2025 1학기 스프링부트 스터디] 장민주 #4주차 (0) | 2025.05.06 |
---|---|
[2025 1학기 스프링부트 스터디] 여민호 #4주차 (0) | 2025.05.06 |
[2025 1학기 스프링부트 스터디] 정다은 #4주차 (1) | 2025.05.04 |
[2025 1학기 스프링부트 스터디] 이상래 #4주차 (0) | 2025.05.04 |
[2025 1학기 스프링부트 스터디] 고윤정 #4주차 (1) | 2025.05.04 |