프로그래밍 공부/Spring
N+1 문제 해결하기
N+1 문제란? 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 개수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오는 현상 발생 이유 N+1 문제가 발생하는 이유는 JPA가 JPQL을 분석해서 SQL을 생성할 때는 글로벌 Fetch 전략을 참고하지 않고 오직 JPQL 자체만을 사용하기 때문이다. 즉, 아래와 같은 순서로 동작하기 때문에 발생한다고 보면 된다. findAll()을 한 순간 select t from Team t 이라는 JPQL 구문이 생성되고 해당 구문을 분석한 select * from team이라는 SQL이 생성되어 실행된다. DB의 결과를 받아 team 엔티티의 인스턴스들을 생성한다. team과 연관되어 있는 user 도 로딩을 해야 한다. 영속성 컨텍스트에서..
스프링 트랜잭션 전파속성
트랜잭션 전파 속성이란? @Transactional 어노테이션(선언적 트랜잭션)을 사용하면 6가지 속성을 지정해 트랜잭션을 세부적으로 이용할 수 있다. readOnly isolation propagation timeout rollbackFor, noRollbackFor (트랜잭션 롤백/커밋 예외) 이중 Propagation은 새로운 트랜잭션을 시작할지 기존의 트랜잭션에 참여할지 등 트랜잭션의 진행 방식에 대한 내용을 결정하게 된다. Spring이 지원하는 전파속성은 다음의 7가지이다. REQUIRED SUPPORTS MANDATORY REQUIRES_NEW NOT_SUPPORTED NEVER NESTED 물리 트랜잭션과 논리 트랜잭션 물리 트랜잭션 : 실제 커넥션 객체를 사용하여 DB에 적용되는 트랜잭션..
JpaRespository가 아닌 Repository를 사용한 이유
Spring Data Jpa의 Repository들 Spring Data JPA를 사용하면 대체로 JpaRepository 인터페이스를 사용하게 된다. 하지만 내부를 살펴보면 더 많은 Repository가 존재한다는 것을 알 수 있다. Repository - 기본적인 Repository이다. CrudRepository - CRUD 기능을 제공한다. PagingAndSortingRepository - 페이지네이션과 sort 기능을 제공한다 JpaRepository - 영속성 context를 flush하거나 Batch등의 기능을 선언하지 않고 사용할 수 있다. 이러한 Repository들은 상속관계로 연결되어있어, 결과적으로 JpaRepository는 상위의 모든 Repository가 제공하는 기능들을 제공..
[Spring] DB ConnectionPool이란?
DB Connection DB를 사용하기 위해 DB와 애플리케이션 간 통신을 할 수 있는 수단. DB 드라이버와 DB 연결정보를 담은 URL이 필요하다. DB 커넥션풀 DB 커넥션 객체를 여러 개 생성하여 풀(Pool)에 담아놓고 필요할 때 꺼내쓰는 방식. 즉, 자주 쓰는 객체를 미리 만들고, 사용한 다음 필요할 때마다 가져간 다음에 반납하는 방식(=Pooling)을 의미한다. 간단히 정리하자면 다음과 같다. 여러 개의 DB Connection을 하나의 Pool에 모아놓고 관리 DB 커넥션 객체를 여러 개 생성한 뒤 Pool에 담아놓고 필요할 때 불러와서 사용 만약, 빌려줄 수 있는 Connection이 없다면 Connection 객체가 반환할 때 까지 클라이언트는 대기 상태로 전환 사용이 끝난 커넥션 ..
[Spring] 의존 자동 주입, @AutoWired
@Autowired 어노테이션을 이용한 의존 자동 주입 대체로 스프링에서 자동주입이라고 말하면 @Autowired 어노테이션이 붙어있는 경우를 말한다. @Autowired 를 해당 필드나 메서드에 붙이게 되면 스프링은 타입이 일치하는 빈 객체를 찾아서 주입하게 된다. 만약 생성자 주입을 사용한다면, 생성자가 하나일 경우 @AutoWired 를 생략해도 자동 주입된다. public class MemberInfoPrinter { private MemberDao memDao; private MemberPrinter printer; public void printMemberInfo(String email) { Member member = memDao.selectByEmail(email); if (member =..
[Spring] @Component vs @Bean
저번 포스팅 ([Spring] Java Bean vs Spring Bean) 에 이어서 빈과 관련된 두번째 포스팅을 진행한다. 스프링 MVC에서는 @Controller, @Service, @Repository 등으로 빈으로 등록할 수 있으며, configuration 관련 객체들은 @Bean과 @Component 으로 스프링 컨테이너에 객체를 빈으로 등록할 수 있다. 그럼 @Bean 과 @Component의 차이는 무엇일까? 두 어노테이션은 혼용해도 될까? 정답은 No다. @Bean과 @Component는 각자 선언할 수 있는 타입이 정해져있어 해당 용도외에는 컴파일 에러를 발생시킨다. 각각의 어노테이션에 대해서 알아보도록 하자. @Component 개발자가 직접 컨트롤이 가능한 Class들의 경우에사용..
[Spring] Controller에서 데이터 받기
대체로 Spring으로 애플리케이션을 구성한다면, Controller에서 값을 받아서 비즈니스 로직을 처리하도록 넘기게 된다. 이때, 이러한 Method Parameter를 어떻게 받는지에 대해서 이야기해보고자 한다. 어찌보면 간단한 개념을 왜 정리하지? 싶을 수도 있으나, 공식 문서를 보게되면 굉장히 많은 Method Argument를 제공하고 있다는 것을 볼 수 있다. 그렇기에, 일단 지금 쓰는 것을 제대로 소화하고, 그 이유를 이해한 뒤에 추가적으로 다른 개념들을 이해하면 더 좋을 것 같아서 정리해본다. @RequestParam @Controller @RequestMapping("/pets") public class EditPetForm { // ... @GetMapping public String..
[Spring] Java Bean vs Spring Bean
스프링으로 개발을 진행하다보면, Bean이라는 개념을 정말 자주 만나게 된다. 무슨 느낌인지 대충은 알겠는데... 그래서 대체 Bean은 어떻게 만들어지는 것이고, 무슨 개념일까? 라고 물으면 막상 대답하기는 쉽지 않다. 그래서 일단 Bean이라는 것이 무엇인지부터 알아보면서 Bean에 대해서 하나씩 정리해보고자 한다. Java Bean Bean은 스프링에서만 나오는 개념 아니야? 라고 물어볼 수 있으나, 자바에도 빈이라는 개념은 존재한다. 위키피디아 링크 Java Bean은 데이터 표현을 목적으로 하는 특정 형태의 클래스라고 이해하면 된다. DTO나 VO와도 유사한 점이 있어 보인다. 개발 툴이나 응용프로그램에서 사용하고자 하는 개념으로 출발했다고 하나, 현재는 그 의미로는 거의 사용하지 않는 것으로 ..
[Spring] @ExceptionHandler 와 @ControllerAdvice
예외처리 프로그래밍에서 예외처리는 매우 중요하다. 사실 우테코에 들어오기 전에는 예외처리와 관련된 코드를 매우 세세하게 짜는 편은 아니었다. 그냥 돌아가면 되는 거지! 정도의 코드였다. 다만, 상세하고 다양한 예외를 갖출 수 있게 된다면 더 안정적인 프로그램이 만들어질 수 있다. 그렇지만 try-catch나 if문으로 예외를 잡거나 상위메서드로 예외처리를 위임하는 등의 작업을 진행하더라도 코드는 쉽게 복잡해질 수 있고, 이는 비즈니스 로직보다 예외처리를 위한 코드에 더 힘쓰게 되는 결과를 초래한다. 나 역시 해당 부분에 있어서 잘 모르는 부분이 존재했고, 또한 기존 Spark 구현 코드를 Spring으로 이식하는 과정에서 예외처리와 관련된 문제들을 해결하기 위해 @ExceptionHandler와 @Con..
[Spring] DI(Dependency Injection, 의존성 주입)이란?
의존이란? 의존 주입이라는 단어를 알아보기 전, 의존이라는 단어의 의미부터 알아보자. 여기서 말하는 의존은 객체 간의 의존을 의미한다. 간단하게 아래의 예시를 보자. public class LottoService{ private LottoTicket winLottoTicket = new WinLottoTicket(); public int checkNumber(LottoTicket userTicket){ return winLottoTicket.checkSameNumber(userTicket); } } 위의 코드에서 집중해서 보아야 할 점은, LottoService라는 클래스가 LottoTicket이라는 클래스의 메서드를 사용한다는 점이다. 즉, 간단하게 말해서 객체에서 '의존'한다는 의미는 한 클래스가 다..