본문 바로가기

SPRING/Spring 활용

[스프링부트| 스프링부트와 JPA 활용 1 | 웹 애플리케이션 개발 | 회원 도메인 개발] 회원 서비스 개발

@Service // 스프링 컨테이너에 서비스 계층의 빈으로 등록
@Transactional(readOnly = true) // 클래스 수준에서 읽기 전용 트랜잭션을 적용
@RequiredArgsConstructor // final 필드나 @NonNull 필드에 대한 생성자를 자동으로 생성
public class MemberService {

    private final MemberRepository memberRepository; // 의존성 주입을 통한 리포지토리 접근

    /**
     * 회원 가입
     */
    @Transactional // 데이터 변경을 포함하므로 디폴트 readOnly = false 트랜잭션 적용
    public Long join(Member member) {

        validateDuplicateMember(member); // 중복 회원 검증
        memberRepository.save(member); // 멤버 저장
        return member.getId(); // 저장된 멤버의 ID 반환
    }

    public void validateDuplicateMember(Member member) {
        List<Member> findMembers = memberRepository.findByName(member.getName()); // 이름으로 멤버 검색
        if (!findMembers.isEmpty()) { // 검색 결과가 비어있지 않다면 중복 존재
            throw new IllegalStateException("이미 존재하는 회원입니다."); // 예외 발생
        }
    }

    /**
     * 회원 전체 조회
     */
    public List<Member> findMembers() {
        return memberRepository.findAll(); // 모든 회원 조회
    }

    /**
     * 회원 단건 조회
     */
    public Member findOne(Long memberId) {
        return memberRepository.findOne(memberId); // ID를 사용한 단일 회원 조회
    }

}

 

기술 설명

  • @Service`
  • `@Transactional` : 트랜잭션, 영속성 컨텍스트
    `readOnly=true` : 데이터의 변경이 없는 읽기 전용 메서드에 사용, 영속성 컨텍스트를 플러시 하지 않으므로 약간의 성능 향상(읽기 전용에는 다 적용)
    데이터베이스 드라이버가 지원하면 DB에서 성능 향상 `
  • @Autowired`
    생성자 Injection 많이 사용, 생성자가 하나면 생략 가능

기능 설명

  • join()
  • findMembers()
  • findOne()

 

참고: 실무에서는 검증 로직이 있어도 멀티 쓰레드 상황을 고려해서 회원 테이블의 회원명 컬럼에 유니크 제약 조 건을 추가하는 것이 안전하다.

 

참고: 스프링 필드 주입 대신에 생성자 주입을 사용하자.

 

  • 생성자 주입 방식을 권장
  • 변경 불가능한 안전한 객체 생성 가능
  • 생성자가 하나면, `@Autowired` 를 생략할 수 있다.
  • final` 키워드를 추가하면 컴파일 시점에 `memberRepository` 를 설정하지 않는 오류를 체크할 수 있다.(보통 기본 생성자를 추가할 때 발견)

 

@Transactional

@Transactional(readOnly = true)는 스프링 프레임워크에서 제공하는 트랜잭션 관리 어노테이션 중 하나입니다. 이 어노테이션은 해당 메소드나 클래스에 트랜잭션이 읽기 전용임을 명시합니다. 읽기 전용 트랜잭션은 데이터베이스에 대한 변경을 커밋할 필요가 없으므로, 데이터 수정이 일어나지 않는 조회 작업에 주로 사용됩니다.

주요 특징 및 장점

  1. 성능 최적화: 읽기 전용 트랜잭션을 사용하면, 데이터베이스는 데이터 변경을 추적할 필요가 없어집니다. 이는 데이터베이스 리소스 사용을 줄이고, 특히 복잡한 쿼리나 대량 데이터를 다룰 때 성능을 향상시킬 수 있습니다.
  2. 데이터 무결성 보장: 읽기 전용으로 설정함으로써, 이 트랜잭션 내에서는 데이터를 변경할 수 없습니다. 이는 실수로 데이터를 변경하는 것을 방지하고, 데이터 무결성을 유지하는 데 도움을 줍니다.
  3. 트랜잭션 관리 간소화: 데이터 변경이 없기 때문에, 트랜잭션을 커밋하거나 롤백하는 처리가 필요 없어 트랜잭션 관리가 간소화됩니다.

사용법

@Transactional(readOnly = true)는 메소드 레벨 또는 클래스 레벨에서 사용할 수 있습니다. 클래스 레벨에 적용할 경우, 해당 클래스의 모든 메소드에 읽기 전용 트랜잭션이 적용됩니다. 특정 메소드에서 데이터 변경이 필요한 경우, 그 메소드에만 별도로 @Transactional을 적용하고 readOnly 속성을 false로 설정하면 됩니다.

 

IllegalStateException

IllegalStateException은 자바의 표준 예외 중 하나로, 메소드가 어떤 작업을 수행하기에 적합하지 않은 상태일 때 발생합니다. 이 예외는 주로 메소드 호출이 객체의 현재 상태와 호환되지 않을 때 사용됩니다. 예를 들어, 객체가 아직 초기화되지 않았거나, 메소드가 허용하지 않는 조건에서 호출되었을 때 IllegalStateException을 발생시킬 수 있습니다.

IllegalStateException 사용의 의미

IllegalStateException은 런타임 예외(RuntimeException)의 하위 클래스로, 체크 예외가 아니기 때문에 반드시 예외 처리를 강제하지 않습니다. 이는 개발자가 선택적으로 예외 처리를 할 수 있도록 하며, 메소드 사용의 전제 조건이 충족되지 않았을 때 적절한 오류 메시지와 함께 프로그램의 흐름을 중단시키는 데 유용합니다.

코드 컨텍스트에서의 사용

제시된 코드에서 validateDuplicateMember 메소드는 멤버의 이름을 검색하여 이미 데이터베이스에 같은 이름을 가진 멤버가 존재하는지 확인합니다. 검색 결과가 비어있지 않다면, 즉 하나 이상의 멤버가 이미 존재한다면, 이는 회원 가입의 전제 조건을 위반하는 상황입니다.

 

영속성 컨텍스트(Persistence Context)

영속성 컨텍스트(Persistence Context)는 Java Persistence API(JPA)의 핵심 개념 중 하나로, 엔티티를 영구 저장하는 환경을 말합니다. 이 컨텍스트는 엔티티 매니저(Entity Manager)에 의해 관리되며, 엔티티의 생명주기를 관리하고 데이터베이스와의 트랜잭션을 코디네이트하는 중요한 역할을 합니다.

영속성 컨텍스트의 주요 기능

  1. 엔티티의 생명주기 관리: 영속성 컨텍스트는 엔티티의 생명주기 상태(비영속, 영속, 삭제, 분리)를 관리합니다. 엔티티가 영속성 컨텍스트에 저장되면, 그 엔티티는 '영속 상태'가 되며, 이 상태에서 엔티티에 대한 변경은 데이터베이스와 동기화됩니다.
  2. 1차 캐시: 영속성 컨텍스트는 1차 캐시 역할을 하여, 한 트랜잭션 내에서 엔티티를 반복해서 조회할 때 매번 데이터베이스를 조회하지 않고 메모리 내 캐시에서 빠르게 조회할 수 있게 합니다. 이는 데이터베이스의 부하를 줄이고 성능을 향상시킵니다.
  3. 변경 감지(Dirty Checking): 영속성 컨텍스트는 관리하고 있는 엔티티의 초기 상태를 저장하고, 트랜잭션이 종료될 때 엔티티의 현재 상태와 비교합니다. 상태가 변경된 경우(더티 상태), 이 변경을 자동으로 데이터베이스에 반영(Flush)합니다.
  4. 지연 로딩(Lazy Loading): 영속성 컨텍스트는 엔티티의 연관된 객체를 즉시 로딩하는 대신 필요할 때까지 로딩을 지연시키는 지연 로딩을 지원합니다. 이는 불필요한 데이터 로드를 방지하고 성능을 최적화합니다.
  5. 트랜잭션과의 통합: 영속성 컨텍스트는 현재 진행 중인 트랜잭션과 긴밀하게 통합되어 작동합니다. 트랜잭션이 커밋되면, 영속성 컨텍스트는 변경 내용을 데이터베이스에 반영하고, 롤백되면 모든 변경을 취소합니다.

영속성 컨텍스트의 이점

  • 데이터 무결성: 영속성 컨텍스트는 엔티티의 일관된 상태를 유지하며 데이터 무결성을 보장합니다.
  • 성능 최적화: 1차 캐시와 지연 로딩 기능은 애플리케이션의 성능을 개선합니다.
  • 애플리케이션 개발의 단순화: 개발자는 데이터베이스와의 상호작용을 신경 쓸 필요 없이 객체 중심의 코드를 작성할 수 있습니다.