1. JDBCTemplate
  2. AOP advice
  3. Hibernate
  4. @MockBean과 @Mock
  5. JPA
  6. N+1문제

1. JDBCTemplate

스프링에서 JdbcTemplate이 무엇이고 JdbcTemplate을 사용할 때, 직접 Connection, PreparedStatement, ResultSet을 관리하지 않아도 되는 이유는 무엇인가요?

JDBCTemplate

  • 스프링 프레임워크에서 제공하는 데이터 베이스 작업을 쉽게 처리하기 위한 클래스

  • 데이터베이스에 접근할 때 발생할 수 있는 반복적인 코드(Connection, PreparedStatement)를 줄여줌

  • 세부적인 리소스 관리와 예외 처리 등을 내부적으로 처리해주어 효율적인 코드로 데이터베이스 작업을 수행할 수 있도록 도움

  • JDBC가 없다면 DB에 접근하는 모든 메서드에서 Connection을 가져오고, PreparedStatement를 가져와서 sql을 수행하고, 자원을 해제해주는 로직을 작성해야 함 중복코드, 복잡성 증가

장점

  • 설정 편리
  • 반복 문제 해결
  • 개발자는 sql은 작성하고, 전달할 파라미터를 정의하고, 응답 값을 매핑하기만 하면 됨

단점

  • 동적 SQL을 작성하기 어려움 Mybatis / QueryDSL을 사용해서 처리

스프링 데이터 소스 관리

  • JDBCTemplate은 스프링의 Datasource와 결합하여 사용
  • 데이터베이스와의 연결을 관리하고 커넥션 풀 제공
  • 이를통해 데이터베이스 연결을 직접 처리할 필요가 없음

트랜잭션 관리

  • JdbcTemplate은 트랜잭션 관리 기능을 자동으로 처리
  • 트랜잭션 범위 내 데이터베이스 연결과 트랜잭션을 자동으로 관리해 별도 커넥션을 관리하거나 트랜잭션을 처리할 필요 없음

리소스 관리

  • Connection, PreparedStatement, ResultSet과 같은 리소스를 자동으로 열고 닫음
  • 수동으로 관리할 필요가 없음

예외처리

  • JDBC 예외를 DataAccessException으로 래핑하여 발생
  • sql 예외나 자원 관리를 신경쓰지 않고 예외 처리 로직 적용 가능

Question

JdbcTemplate을 사용할 때 내부적으로 Connection, PreparedStatement, ResultSet을 어떻게 관리하나요?

내부적으로 DataSource를 사용하여 데이터베이스 연결을 관리하고, Connection, PreparedStatement, ResultSet 객체를 자동으로 처리합니다. 이를 통해 개발자는 직접 데이터베이스를 연결하거나 예외처리를 작성할 필요 없이 JdbcTemplate이 관리해줍니다.

Question

JDBCTemplate을 사용하면서 발생할 수 있는 성능 문제와 최적화 방법은 무엇인가요?

JDBCTemplate을 잘못 사용하여 동일한 쿼리를 여러 번 호출하거나 불필요하게 데이터를 조회하는 경우 성능이 저하될 수 있습니다. 또 대규모 데이터를 한번에 처리할 때 메모리 부족이 발생할 수 있습니다. 이를 해결하기 위해선 JDBCTemplate에서 제공하는 배치처리 시스템을 사용하거나 지연 로딩을 사용해 큰 데이터셋을 처리할 때 한번에 데이터를 처리하는것이 아니라 필요한 데이터만 가져오도록 설계합니다.

2. AOP advice

스프링 AOP에서 어드바이스(advice)가 실행되는 시점과 그 이유를 설명해 주세요.

AOP advice

  • 특정 지점에서 실행되는 코드
  • Aspect의 핵심으로서 특정 JoinPoint에서 실행될 로직을 정의하는 부분
  • 메소드 실행 전, 후, 예외 발생 시 등 다양한 시점에 실행

Question

스프링 AOP에서 어드바이스(advice)가 실행되는 시점과 그 이유를 설명해 주세요.

advice는 joinpoint라는 특정 지점에서 실행됩니다. 일반적으로 메소드 호출이나 실행이 joinpoint로 사용됩니다. 이때 advice가 실행되는 시점은 어드바이스 종류에 따라 다릅니다.

BeforeAdvice는 대상 메소드 실행 전에 실행되어 사용자 인증이나 로그 기록 등에 사용됩니다. AfterAdvice는 대상 메소드 실행 후 실행되어 메소드 실행 후 리소스를 해제하거나 예외발생시 예외처리를 할 때 사용됩니다. AroundAdvice는 메소드 실행 전후에 실행됩니다. 메소드 실행을 전후로 감싸서 제어하는 역할을 합니다. FinallyAdvice는 메소드 실행 후 예외 발생 여부와 상관없이 항상 실행됩니다.

따라서 advice가 실행되는 시점은 다양한 비즈니스 요구사항을 처리하기 위해 선택적으로 실행됩니다.

Question

Join Point와 Advice의 차이점?

JoinPoint는 AOP에서 특정한 실행 지점을 의미합니다. 주로 메소드 실행이 Join Point로 사용됩니다. Advice는 JoinPoint에서 실행될 구체적인 로직입니다. 언제, 어떤 작업을 할지 정의하는 역할을 합니다.

Question

스프링 AOP에서 Advice가 실행되는 순서를 어떻게 제어할 수 있나요?

AOP에서 여러개의 Advice가 하나의 JoinPoint에 적용될 때 실행순서는 기본적으로 설정된 순서대로 실행됩니다. 순서를 명시적으로 제어하기 위해선 @Order 어노테이션을 사용하거나 @Aspect 클래스에 설정된 우선순위 값을 조정할 수 있습니다.

3. Hibernate

하이버네이트가 무엇이고 하이버네이트에서 Lazy Loading과 Eager Loading의 차이점은 무엇이며, 이 두 가지 방법을 사용할 때 발생할 수 있는 문제는 무엇인가요?

Hibernate

  • 자바와 RDBMS간의 데이터 변환을 자동화하여 개발자가 sql쿼리를 작성하지 않고도 데이터베이스와 상호작용할 수 있게 해주는 프레임워크

Lazy Loading과 Eager Loading의 차이점

Lazy Loading

  • 연관된 객체를 실제로 필요할 때까지 로딩하지 않는 방식
  • 처음에는 관련 객체의 프록시 객체를 생성하고, 실제 데이터는 해당 객체에 접근할 때 로딩
  • 성능 최적화를 위해 사용, 초기 로딩시에는 필요한 데이터만 로딩하고 추가적인 데이터는 필요할 때 조회
  • 자식 엔티티가 여러개일 경우 부모 엔티티를 조회할 때 자식 엔티티는 로딩하지 않음

Eager Loading

  • 연관된 객체를 즉시 로딩하는 방식
  • 데이터베이스에서 관련 데이터를 미리 로딩해 조회 시점에 관련된 데이터를 함께 가져와 쿼리수가 줄어들 수 있음
  • 부모 엔티티를 조회할 때 자식 엔티티까지 즉시 로딩

Lazy Loading과 Eager Loading에서 발생할 수 있는 문제

Lazy Loading

  • N+1 문제 : 자식 객체에 접근할 때마다 별도의 쿼리를 발생시켜 많은 자식 객체를 로드할 때 N+1 문제가 발생할 수 있음 Join을 사용하여 필요한 데이터를 가져옴
  • 10개의 부모 객체 조회 부모 객체 조회 쿼리 1번 + 각 부모에 대한 자식 객체 조회 쿼리 10번 = 11번

Eager Loading

  • 불필요한 데이터가 한 번에 로드할 수 있음, 부모 객체를 조회할 때 자식 객체가 너무 많거나 연관된 엔티티가 크고 복잡할 수록 성능저하 발생 필요한 데이터만 로딩할 수 있도록 @Query 에서 로딩할 데이터 선택적으로 지정

Question

Lazy Loading을 사용할 때 N+1 문제를 해결하기 위한 최적화 방법은 무엇인가요?

연관 관계를 Eager Loading으로 변경하거나, Fetch Join을 사용해 부모 객체와 자식 객체를 한 번의 쿼리로 가져올 수 있습니다.

4. @MockBean과 @Mock

스프링에서 @MockBean과 @Mock의 차이점은 무엇인가요?

@MockBean

  • Spring Test에서 사용하는 어노테이션

  • 스프링 컨텍스트에 mock 객체를 등록하는 역할로 주로 통합테스트에서 사용됨

  • 해당 객체가 Spring Application Context에 등록되어 실제 빈 대체 가능

  • DI를 통해 mock 객체 주입

  • Spring의 ApplicationContext에 mock 객체를 등록하여 해당 클래스가 해당 Mock 객체를 의존성 주입을 통해 주입받도록 함

  • 통합 테스트에서 주로 사용

  • 서비스, 레포지토리, 컴포넌트 등의 빈을 mock으로 대체할 때 사용

@SpringBootTest
public class SomeServiceTest {
    
    @MockBean
    private SomeRepository someRepository;  // 실제 빈을 mock으로 대체
 
    @Autowired
    private SomeService someService;
 
    @Test
    public void testSomeMethod() {
        // Mock behavior 설정
        when(someRepository.someMethod()).thenReturn("someValue");
 
        // 실제 테스트 수행
        assertEquals("someValue", someService.someMethod());
    }
}

@Mock

  • Mockito 라이브러리에서 제공하는 어노테이션

  • 단위테스트에서 mock 객체를 생성할 때 사용

  • Spring Context와 무관하며, 단위테스트를 할 때 사용

  • mock 객체를 생성하지만 Spring의 DI를 활용하진 않음

  • 직접 필드주입이나 생성자 주입을 통해 mock 객체를 전달해야 함

Question

스프링에서 @MockBean과 @Mock의 차이점은 무엇인가요?

@MockBean은 보통 통합테스트에 사용되며 Spring Application Context에 mock 객체를 등록하여 실제 빈을 대체합니다. 이때 의존성 주입을 사용해 mock 객체가 주입됩니다. @Mock은 Mockito 라이브러리에서 제공하는 어노테이션으로 보통 단위테스트에서 mock 객체를 생성하는 데 사용됩니다. Spring과는 관계없이 mock 객체를 생성하고, 필드주입이나 생성자 주입을 통해 테스트 대상에 주입합니다.

Question

@MockBean과 @Mock을 사용할 때 의존성 주입 방식에 대한 차이점은 무엇인가요?

@MockBean은 Spring의 DI 를 사용하여 테스트 클래스에 자동으로 의존성을 주입합니다. @Mock은 Spring의 DI와 별개로 동작하여 해당 객체를 수동으로 주입해야 합니다.

Question

@MockBean을 사용한 통합 테스트에서 ApplicationContext를 초기화하는 이유는 무엇인가요?

애플리케이션의 실제 빈을 사용하면서도 특정 빈만 mock으로 대체하고자 하기 때문입니다. application context를 초기화하면 실제 시스템과 비슷환 환경에서 상호작용을 테스트 할 수 있습니다.

Question

@MockBean과 @Mock을 함께 사용하는 경우, 발생할 수 있는 문제점은 무엇인가요?

Spring context와 mockito 의 관리 방식이 다르기 때문에 충돌이 발생할 수 있습니다.

5. JPA

JPA란 무엇이고 JPA에서 Entity 클래스에 @Id 어노테이션을 붙이는 이유는 무엇인가요? 이 어노테이션 없이 엔티티를 저장하려고 하면 어떻게 될까요?

JPA

  • 자바 객체와 데이터베이스 간의 매핑을 위한 자바 표준 인터페이스
  • sql에 의존하지 않고도 데이터 조작이 가능
  • Hibernate, openJPA와 같은 프레임워크가 JPA 구현
  • 객체와 테이블 매핑
  • 객체 지향적인 쿼리 작성
  • 트랜잭션 관리
  • 영속성 컨텍스트를 활용한 캐싱

@Id

  • JPA 엔티티의 기본 키를 지정하는 데 사용
  • 데이터베이스 테이블과 매핑되며, 고유하게 식별할 수 있는 기본 키 필요
  • 각 레코드를 고유하게 식별하는 데 필수

@Id없이 엔티티에 저장시

  • JPA는 기본 키가 없는 엔티티를 영속성 컨텍스트에 저장할 수 없음
  • hibernateException 발생

Question

JPA에서 기본 키 생성을 위한 @GeneratedValue 전략 중 IDENTITY, SEQUENCE, TABLE의 차이는 무엇인가요?

  • IDENTITY: 데이터베이스에서 AUTO_INCREMENT를 사용하는 방식. 새로운 ID는 데이터베이스가 자동으로 생성.
  • SEQUENCE: 데이터베이스의 시퀀스 객체를 사용하여 ID를 생성. 주로 Oracle, PostgreSQL에서 사용.
  • TABLE: ID 생성을 위해 별도의 테이블을 사용하여 고유 ID를 관리. 데이터베이스 독립성을 높일 수 있으나 성능이 낮을 수 있음.

6. N+1문제

JPA에서 N+1 문제를 해결하기 위한 방법에 대해 설명해 주세요.

  • JPA에서 발생하는 성능 문제로, 하나의 조회로 여러 엔티티를 조회한 후 각각의 엔티티와 연관된 데이터를 추가로 조회하는 상황

해결 방법

  • Fetch Join 을 사용하여 연관된 엔티티를 한번에 가져옴
  • fetchType을 Eager로 변경 불필요한 데이터까지 로딩되어 성능 문제 발생
  • @EntityGraph 어노테이션을 사용하여 FetchType 설정 재정의
  • Batch Fetch Size : 연관된 엔티티를 배치로 조회하여 쿼리수를 줄임

Question

Fetch Join과 Batch Fetch Size의 차이는 무엇이며, 언제 각각을 사용하는 것이 적합한가요?

Fetch Join은 한 번의 조인 쿼리로 연관된 엔티티를 가져오며 간단한 관계일 때 적합합니다. Batch Fetch Size는 대량의 데이터를 처리할 때 효과적입니다.


Question

ORM과 JPA, Hibernate의 관계에 대해 말씀해주세요.

  • ORM(레시피):
    • ORM(Object-Relational Mapping)은 객체(Object)와 데이터베이스의 테이블(Relational)을 연결하는 방법(레시피)입니다.
    • 예를 들어, “클래스와 테이블을 매핑하고, 객체를 저장하거나 불러오는 방법을 제공한다”는 일반적인 개념입니다.
    • 레시피처럼 “어떻게 요리할지”에 대한 큰 그림을 제시합니다. ORM은 이런 원리를 이해하면, 많은 라이브러리가 이를 활용할 수 있죠.
  • JPA(요리책):
    • JPA(Java Persistence API)는 ORM의 표준 인터페이스로, 자바 세계에서 사용하는 ORM의 “공식 요리책” 같은 역할을 합니다.
    • 요리책에는 “어떤 재료를 준비해야 하고, 어떤 순서로 요리해야 한다”는 기본적인 규칙들이 나와 있습니다.
    • JPA는 ORM의 표준을 정의하고, 다양한 라이브러리가 이 표준에 맞춰 구현되도록 돕습니다.
  • Hibernate(요리사):
    • Hibernate는 JPA라는 요리책을 참조하며 실제로 요리를 만들어 내는 요리사입니다.
    • Hibernate는 JPA의 규칙을 따르면서도 자체적으로 추가적인 기능(레시피)을 제공하여 더 맛있고, 효율적인 요리를 만들어 냅니다.
    • 즉, JPA가 표준이라면 Hibernate는 그 표준을 구현한 대표적인 실질적 도구입니다.
  • ORM은 개념입니다. 객체와 데이터베이스를 매핑하는 일반적인 방법을 말합니다.
  • JPA는 표준입니다. 자바에서 ORM을 사용할 때 지켜야 할 규칙을 정의합니다.
  • Hibernate는 구현체입니다. JPA 표준을 따르면서, 더 많은 기능을 제공하는 라이브러리입니다.