섹션 3: 회원 관리 예제 - 백엔드 개발

MineeHyun·2024년 7월 4일
0

구분선은 자르고 싶은 곳 아무데나 붙이고 큰 의미 없음


비즈니스 요구사항 정리

데이터: 회원 ID, 이름
기능: 회원 등록, 조회
아직 데이터 저장소가 선정되지 않았다는 시나리오

  • DB를 뭘로 할지 아직 정하지 않음

회원 도메인과 리포지토리 만들기

아래 코드들은 제가 따라 쓰고 캡쳐해서 필기한 것입니다 ...

  • generate 단축키 ALT + Insert
  • auto completion Ctrl + Space
  • smart auto completion Ctrl + shift + space

공부할 것


회원 리포지토리 테스트 케이스 작성

  • 리포지토리가 내가 원하는 대로 동작하나?
  • main 함수를 실행하거나 controller로 기능을 실행해보면 됨. 근데 이 방법들은 준비+실행에 시간이 오래 걸리고, 반복해서 실행하기 어렵고, 여러 종류의 실험을 하기 어렵다.
  • 자바는 JUnit이라는 프레임워크로 테스트를 실행해서 이러한 문제를 해결한다.


option + enter -> Add on-demand static import for (org. ...) 하면 Assertions 앞에 있는 구구절절이들이 import 된다. 이러고 나면 그냥 assertThat. ...로 쓸 수 있게 됨.
이렇게!

Assertion

Assert: 표명하다, 역설하다...
아무튼 뭔가 "강하게 말한다"는 의미가 있음.
Assertion은 프로그래머가 반드시 참 또는 거짓일 것이라고 가정하는 논리식이다. 해당 문장이 그 장소에서 항상 참 또는 거짓이라고 간주한다. 런타임 중에 이 논리식이 의도한 것과 다른 값 (참 -> 거짓/거짓 -> 참)으로 밝혀지면 assertion failure가 발생하고 일반적으로 실행이 중단된다. (참고)

TDD
test를 먼저 작성하고 (먼저 구성하고) 코드를 설계하는 방식을 TDD라고 한다.
test-driven development


회원 서비스 개발

package hello_spring.hello.service;

import hello_spring.hello.domain.Member;
import hello_spring.hello.repository.MemberRepository;
import hello_spring.hello.repository.MemoryMemberRepository;

import java.util.List;
import java.util.Optional;

public class MemberService {

    private final MemberRepository memberRepository = new MemoryMemberRepository();
    public Long join(Member member) {
        // 회원 가입
        // 같은 이름이 있는 회원은 안 됨
        validateDupliacateMember(member);
        memberRepository.save(member);
        return member.getId();
    }

    private void validateDupliacateMember(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);
    }
}

extract method
코드를 쓰는데 기능이 많고 로직이 길어지면 method로 추출할 수 있다.
Ctrl + Alt + M

  • Optional<> 타입의 객체를 만들어서 리턴을 받는 건 별로 권장되지 않는다.
  • Optional<> 타입을 까서 쓰는 것도 그다지 권장되지는 않음. (Optional 안에는 보통 nullable한 것들이 들어가는데, Optional을 까고 나면 처리하기가 까다로워짐.)
  • 그래서 아래 코드처럼 반환된 인스턴스에다 바로 메서드를 갈기는 방법을 잘 쓴다.
memberRepository.findByName(member.getName()).ifPresent(m -> {
            throw new IllegalStateException("이미 존재하는 회원입니다.");

회원 서비스 테스트

테스트 코드를 직접 적지 않아도 테스트를 할 수 있다.

  • class에서 ctrl + shift + T
  • 아래 창에서 테스트할 method를 선택하고 OK 하면 됨.
  • 수업에서는 library로 JUnit5를 사용했음

    그러면 test 폴더에 똑같은 패키지를 만들어서 자동으로 껍데기가 태어납니다~
package hello_spring.hello.service;

import hello_spring.hello.domain.Member;
import hello_spring.hello.repository.MemberRepository;
import hello_spring.hello.repository.MemoryMemberRepository;

import java.util.List;
import java.util.Optional;

public class MemberService {

    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    public Long join(Member member) {
        // 회원 가입
        // 같은 이름이 있는 회원은 안 됨
        validateDupliacateMember(member);
        memberRepository.save(member);
        return member.getId();
    }

    private void validateDupliacateMember(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);
    }
}
  • test를 할 때 마다 MemberRepository 인스턴스를 새로 만들면, 사실 실제 MemberService에서 쓰는 것과 다른 인스턴스이므로 완전히 다른 것으로 테스트하게 된다. (내용 등이 쉽게 바뀔 수 있음. -> 테스트 통과해도 실제로는 안전하지 않을 수 있다.)
  • 이를 해결하기 위해서 MemberService에서 memberRepository를 생성할 때 "외부에서 만든 객체를 주입하도록" 한다. 이렇게 하면 테스트와 실제 코드에서 일관성을 유지할 수 있다.
  • 이것을 의존성 주입 (Dependency Injection)이라고 한다. .....

이모저모

  • 1월쯤 스프링 깔짝거릴 때 DI가 뭔지는 알겠는데 이것이 왜 테스트를 용이하게 하고 안전성을 증대시키는가? 라고 아는 개발자에게 물어봤더니 "님이 얼라라서 이해 못하는 것이다"라고 했었는데 대충 뭔소린지 이제 알겠음
  • 자바 공부를 열심히 해야겠다

0개의 댓글