Skip to content

Latest commit

 

History

History
143 lines (99 loc) · 6.53 KB

2차시_트랜잭션.md

File metadata and controls

143 lines (99 loc) · 6.53 KB

✏️ Transaction

트랜잭션 상태중 부분 완료와 완료의 차이에 대해 간단히 설명해주세요. 부분 완료는 트랜잭션의 마지막까지 실행되었지만 commit 연산이 실행되기 전의 상태

완료는 트랜잭션 작업이 완료되어 commit 연산이 실행 된 후의 상태

스프링에서 @Transactional을 사용할 때 지연 로딩 문제를 해결하기 위한 해결 방법을 말해주세요. 서비스와 컨트롤러 간에 DTO를 사용해서 양쪽의 엔티티를 주고 받게 해주면 지연 로딩이 발생할 수 있습니다.

추가 설명

지연로딩(Lazy Loading)이란 프록시를 사용해서 조회할 경우 해당 객체에 접근 시 요청을 보내는 방법이다.

하지만 준영속 상태의 엔티티는 이 기능을 사용하지 못하기 때문에 예외가 발생하게 된다.

@Entity
public class School{
	@Id
	@GeneratedValue
	private long id;
	
	@ManyToOne(fetch = FetchType.LAZY) // 지연 로딩 전략
	private Teacher teacher;
}
class SchoolController {
	public String view(Long bookId){
		School school = schoolService.findSchool(schoolId);
		Teacher teacher = book.getTeacher(); // 예외 발생
	}
}

예외가 발생한 이유

School 엔티티는 Service에서 조회한 값이고 이 때는 영속성 컨텍스트가 올바르게 수행되었다.

이 때 findSchool 메서드가 종료되면서 영속성 컨텍스트가 닫혔고 반환된 School 엔티티는 준영속 상태가 된다.

Teacher 는 Lazy Loading 전략을 사용했으므로 비어있는 프록시 객체 상태에서 해당 객체의 값을 뽑아 쓰려고 하니 예외가 발생한 것이다.

해결 방법

  • DTO 사용

    • Service 와 Controller 간에 DTO를 사용한다.
    • 양쪽에서 엔티티를 주고 받을 경우 지연 로딩 이슈 이외에도 컨트롤러가 멋대로 엔티티를 수정하는 문제가 발생할 수 있기 때문에 DTO를 불변 객체로 만들어 사용하면 이를 전달하는 역할만 수행할 수 있다.
    • 지연 로딩된 값을 컨트롤러에 전달하지 않아도 될 경우 DTO 에서 해당 값에 접근하지 않게 하여 로딩 수를 줄이고 전달해야 할 경우 SchoolDTO 안에 TeacherDTO 가 존재하는 방식으로 DTO를 구성하면 그 과정에서 참조가 발생하여 teacher 에 대한 Lazy Loading이 발생할 수 있도록 한다.
    Comparator과 Comparable의 차이에 대해서 설명해주세요.
    • Comparable
      • 객체의 정렬 기준을 정해줄 때 사용하며 자기 자신과 매개변수 객체를 비교
      • 보통 기본형을 정렬하기 보다 객체의 정렬 기준을 만들어 준다.
      • .compareTo(매개변수)라는 메서드를 사용합니다.
      • 기본적인 정렬(오름차순, 내림차순)을 수행합니다.
  • Comparator

    • 이미 정해진 기준 외에 다른 정렬 기준을 사용하고 싶을 때 사용되고 두 매개변수 객체를 비교한다는 차이가 있습니다.
    • 클래스 자체가 정렬 기준으로 사용되기 때문에 외부 정렬 기준을 정의합니다.
    • Compare(매개변수1, 매개변수2)라는 메서드를 사용합니다.
    • 사용자가 정한 규칙을 기준으로 정렬합니다.
@Transactional 어노테이션의 원리에 대해 간단히 설명해주세요.

트랜잭션의 경우 트랜잭션의 시작과 연산 종료시의 커밋 과정이 필요하므로 프록시를 생성해 해당 메서드의 앞뒤에 트랜잭션의 시작과 끝을 추가하여 트랜잭션이 수행되도록 보장해줍니다.

트랜잭션에 대해 간단하게 설명해주세요.

트랜잭션은 데이터 베이스의 상태를 변화시키기 위해 수행하는 작업의 단위를 의미합니다.

트랜잭션을 통해 데이터의 무결성을 유지하고, 시스템 장애나 오류 상황에서도 일관성을 확보할 수 있습니다

JPA에서 트랜잭션 관리는 어떻게 이루어지나요?

JPA는 @Transactional 어노테이션을 통해 트랜잭션을 관리합니다.

Spring Framework와 함께 사용할 경우, 서비스 계층에서 @Transactional을 사용하여 트랜잭션의 시작과 종료를 선언적으로 관리할 수 있습니다.

해당 어노테이션이 적용된 메서드가 호출되면 트랜잭션이 시작되고, 메서드 실행이 끝나면 자동으로 커밋되거나 롤백됩니다.

readOnly = true 옵션을 사용하는 이유

트랜잭션은 데이터 베이스의 상태를 변화시키기 위해 수행하는 작업의 단위를 의미합니다. 트랜잭션을 통해 데이터의 무결성을 유지하고,

시스템 장애나 오류 상황에서도 일관성을 확보할 수 있습니다

트랜잭션의 ACID 속성이 무엇인가요?
  • Atomicity (원자성): 모든 작업이 완료되거나 하나도 실행되지 않아야 함.
  • Consistency (일관성): 트랜잭션 전후 데이터가 일관성을 유지해야 함.
  • Isolation (독립성): 여러 트랜잭션이 동시에 실행될 때 서로 간섭하지 않아야 함.
  • Durability (지속성): 트랜잭션이 완료되면 데이터는 영구적으로 저장되어야 함.
@Transactional에 readOnly 속성을 사용하는 이유에 대해서 설명하시오.

보통의 트랜잭션은 데이터 조회 결과 엔티티가 영속성 컨텍스트에 관리되며, 변경 감지(Dirty Checking)를 위해,

조회시 스냅샷 인스턴스를 생성해 보관하기 때문에 메모리 사용량이 증가한다.

readOnly 속성을 사용한 @Transactional은 트랜잭션 커밋 시점에 flush(DB에 반영)를 하지 않기 때문에

이로 인한 dirty checking 비용이 들지 않아, 메모리가 절약된다.

트랜잭션의 커밋 (Commit)과 롤백 (Rollback)의 차이를 설명해주세요.
  • Commit: 트랜잭션이 성공적으로 완료되어 모든 변경 사항이 영구적으로 저장됨.
  • Rollback: 트랜잭션이 실패하거나 취소되어 이전 상태로 복구됨.

참고