회원 서비스 개발

구현할 내용

  1. 회원 가입 : 중복 회원 방지 익셉션 메서드 추가

  2. 회원 조회 : 회원 전체 조회, 회원 단건 조회

<메서드 구현>

  • join(Member member) : member.getId() 해도 값이 있다는 것이 보장된다! MemberRepository의 save()에서 em.persist(member)하는 순간 영속성 컨텍스트에 member객체를 넣을 때 영속성 컨텍스 (key,value)에서 key는 PK가 된다. Member 테이블의 PKid(name="member_id")이다. @GenerateValue는 DB마다 다른데, 어떤 것은 테이블을 아예 따로 만들어서 key를 가져오는 것도 있고, 어떤 것은 시퀀스를 만들어 넣는다. 그렇기 때문에 em.persist(member)할 때 id값이 항상 생성되있는 것이 보장된다! 왜냐하면 영속성 context할 때 값을 넣어야 하고, 그 때 구조는 (key,value)인데 key는 PK 값을 그대로 넣음과 동시에 Member 클래스 필드의 값도 채워준다.(DB에 들어가는 시점이 아니여도)

  • join 메서드에 중복 회원 체크 추가(메서드 추가 구현) 동시에 동일한 이름으로 회원가입하는 경우가 있다! 그러므로 멀티스레드 환경을 고려해서 DB에 member.getName()을 유니크 제약조건으로 잡아야한다! 최적화 : 단순히 갯수만을 체크해서 0보다 큰 조건으로 해줘도 된다!

  • findMembers() : 회원 전체 조회

    public List<Member> findMembers() {
      return memberRepository.findAll();
    }
  • findOne(Long memberId) : 회원 단건 조회

    public Member findOne(Long memberId) {
      return memberRepository.findOne(memberId);
    }

<기술 설명>

  1. MemberService 클래스에 @Transactional(readOnly = true)로 설정

MemberService 클래스에는 읽기 메서드가 많기 때문에 상위 클래스에 @Transactional(readOnly = true)로 해주고 쓰기 메서드인 join은 @Transactional로 해준다!(디폴트값은 readOnly=false) JPA 의 모든 데이터 변경이나 로직은 모두 트랜잭션 내에서 다 실행되어야 하기 때문에 @Transactional 애노테이션 필요! @Transactinal은 자바와 스프링에서 제공하는 2가지가 있는데 스프링에 의존적인 애플리케이션을 개발하는 것이기 때문에 스프링에서 제공하는 것을 선택해야 기본 기능 외에 확장된 기능까지 사용할 수 있다! @Transactinal을 전체 클래스 레벨에 적용하면 내부의 메서드들도 다 적용이 되는데, 이 @Transactional을 조회하는 메서드에 개별로 붙이고, redOnly=true를 넣어주면 JPA가 조회하는 것에 있어서 성능이 최적화된다! 그렇기 때문에 조회하는 읽기 전용 메서드는 @Transactional(readOnly = true)로 해준다! - dirtycheck를 하지 않는 이점 - readOnly(읽기 모드)기 때문에 DB도 리소스를 많이 쓰지 않고 읽기만 함

2. 인젝션(의존 관계 주입 DI) : @Autowired 생성자 Injection 많이 사용. 생성자 하나면 생략 가능

  1. 필드 인젝션 스프링 빈에 등록된 MemberRepository를 의존 관계 주입한다!=>해당 필드 수정 어렵다!

    @Autowired
    private MemberRepository memberRepository;
  2. setter 인젝션(수정자 주입) 장점 : 테스트코드 작성시에 파라미터 직접 주입해줄 수 있음. 단점 : 실제 애플리케이션이 돌아가는 시점에 누군가가 값을 셋팅해서 바뀔 수 있다! 하지만 실제로 애플리케이션 런타임에는 뭔가가 바뀔 수가 없고, 바뀌어서도 안된다!

  3. constructor 인젝션(생성자 주입), 해당 필드는 final로 설정 생성될 때 딱 한번 주입된다! 다만, 메인 메서드에서 MemberService 객체 인스턴스 생성할 때, 파라미터로 뭐라도 넣어줘야함! 최신 스프링에서는 생성자가 딱 하나일 때는 @Autowired를 생략해도 자동으로 인젝션해준다! final로 설정하면 무조건 값이 있어야하기 때문에 값을 안 넣어주면 컴파일에러로 알려주기 때문이다!

    private final MemberRepository memberRepository;
    @Autowired
    public MemberService(MemberRepository memberRepository){
        this.memberRepository = memberRepository;
    }

  4. (롬복)@AllArgsConstructor : 모든 필드를 생성자주입해준다!

  5. (롬복)@RequiredArgsConstructor : final 붙은 필드들만 생성자주입해준다!(추천)

  6. MemberRepository에서 EntityManager 의존 관계 주입⭐️ EntityManager는 표준 의존 관계 주입(DI) 애노테이션@PersistenceContext가 있어야 한다. 하지만 스프링 부트 JPA가 @Autowired로도 DI 지원해주기 때문에 다른 DI들과 마찬가지로 해줘도 된다! 원래 소스 :@PersistenceContext로 스프링이 JPA의 EntityManager를 생성해서 자동 주

@PersistenceContext
private EntityManager em;

마찬가지로 MemberRepository에서도 EntityManager 필드를 생성자 주입 가능!

@PersistenceContext//스프링이 JPA의 EntityManager 생성해서 자동 주입.
private EntityManager em;

public MemberRepository(EntityManager em){
    this.em = em;
}

이때, @PersistenceContext를 그냥 @Autowired로 해도 된다. 스프링 부트의 JPA가 지원해준다.

@Autowired
private EntityManager em;

public MemberRepository(EntityManager em){
    this.em = em;
}

최종 : MemberRepository 클래스에 @RequiredArgsConstructor해주고 필드 final로 설정.

Last updated