회원관리 예제로 배우는 스프링 기본기(테스트 코드, Optional, 람다 등등)

2025. 8. 5. 15:36Spring

🐢 일반적인 웹 애플리케이션 계층 구조

 

  • Controller: 웹 요청 받고 응답 주는 창구 거북이 🐢📨
  • Service: 비즈니스 로직 담당하는 두뇌 거북이 🐢🧠
  • Repository (DAO): 데이터 저장/조회 담당하는 창고 거북이 🐢📦
  • Domain (Entity): 회원, 주문 같은 핵심 객체 → 실제 데이터 거북이 🐢

👉 요청 → 컨트롤러 → 서비스 → 리포지토리 → DB 순서로 흐름

 

*위에 일반적인 웹 애플리케이션 계층 구조

 

🐢 Optional.ofNullable null 방지 거북이 🐢

  • 값이 있으면 감싸서 Optional로 반환, 없으면 Optional.empty() 반환
  • Optional<Member> 이런 식으로 많이 씀
Optional<Member> member = Optional.ofNullable(repository.findByName("spring"));
member.ifPresent(m -> 
	System.out.println("회원 있음: " + m.getName())
);

👉 ifPresent 쓰면 값이 있을 때만 실행됨 → NullPointerException 걱정 안 함

 

🐢 틈새 자바 문법 (map, filter, 람다식)

✔️filter 조건 걸러내는 거북이 🐢

store.values().stream()
    .filter(member -> member.getName().equals(name))
    .findAny();

👉 filter(member -> ... ) 이름 같은 놈만 걸러냄 

 

✔️map 값 변환 거북이 🐢

Optional.ofNullable(member)
    .map(m -> m.getName())  // Member → String 변환
    .ifPresent(name -> System.out.println("이름: " + name));

👉 Stream이나 Optional에서 주로 쓰임

👉 내부에 있는 값을 꺼내서 변환한 다음, 다시 감싸서 반환하는거, 형 변환X 값 변환(데이터 변형)

 

✔️람다식

  • 익명 함수 간단하게 표현하는 문법
  • member -> member.getName().equals(name)이런거
  • 사실상 함수 한 줄 짜리 버전 
  • 코드 짧아지고 가독성 높아서 쓰는거

💯 테스트코드(JUnit)

1. @Test (테스트 메서드, 이거 붙이면 JUnit 자동 실행) 

@Test
public void 회원가입(){
    Member member = new Member();
    member.setName("spring");
    
    repository.save(member);
    Member result = repository.findById(member.getId()).get();
    Assertions.assertEquals(member, result); // JUnit 기본 제공
}

 

2. Assertions(검증 거북이 🐢)

  • Assertions.assertEquals(a, b) → 두 값이 같은지 확인
  • assertThat(a).isEqualTo(b) → 더 직관적인 문법 (AssertJ 라이브러리)

 

import static org.assertj.core.api.Assertions.assertThat;

assertThat(member).isEqualTo(result); // 이거 더 깔끔함

 

3. @AfterEach(테스트 끝날 때마다 실행되는 거북이 청소부 🐢)

 

  • 저장소 초기화 안 하면 테스트 간 데이터 꼬임
@AfterEach
public void afterEach(){
    repository.clearStore(); // 매번 청소
}

 

 

4. @BeforeEach(테스트 시작 전마다 실행되는 거북이 준비조 🐢)

  • 매번 fresh한 Repository 객체 만들어줌 
@BeforeEach
public void beforeEach(){
    repository = new MemoryMemberRepository();
}

 

🔥 정리 

MVC구조 : Controller(요청청구) -> Service(비즈니스 로직) -> Repository(DB저장) -> Domain(데이터 객체)

Optional.ofNullable: null 방지용, 값 없으면 empty, 있으면 Optional로 감싸줌

 

filter: 조건 맞는 값만 추려내는 거북이 (stream().filter(...))

map: 내부 값 꺼내 변환 후 다시 감싸줌 (형변환 아님, 값 변환임)

람다식: member -> member.getName() 같은 함수 한 줄 표현 문법