목록공부/JAVA (6)
빠에야는 개발중
OSIV 무엇인가? OSIV란 Open Session In View의 약자로 JPA에서 영속성 컨텍스트와 hibernate session을 뷰가 렌더링 될 때까지 유지시키는 방법이다. 왜 사용하는가? 기존에 @Transactional 메소드까지 유지가 되던 영속성 컨텍스트의 영향 범위는 뷰 렌더링까지는 닿지 않는다. 따라서 controller 단에서 엔티티를 조회할 때 Lazy loading이 걸린다면, LazyInitializationException을 뱉으면서 실패한다. 이를 해결하기 위해서 영속성 컨텍스트가 뷰를 그릴때도 유지될 수 있도록 하여 Lazy loading을 성공시키는 것이다. 단점 전통적인 OSIV를 기준으로 요청이 들어왔을 때 controller단에서 부터 JDBC connection..
N+1 문제 무엇인가? N+1 문제는 JPA에서 하나의 부모 객체와 다수의 자식 객체 데이터를 얻기 위해 메소드를 호출했을때 부모를 조회하는 쿼리 1개와 하위의 N개의 자식들을 조회하는 쿼리 N개가 발생하는 문제이다. 이는 1:N 관계에서 fetch type이 eager loading일 때 findAll() 따위로 전체를 조회하는 메소드를 사용하거나, lazy loading일 때 자식 객체를 반복문 따위로 순환 조회하는 과정에서 발생한다. 한번의 쿼리로 join해서 가져올 것을 자식 객체 수만큼의 쿼리를 사용하니 당연히 성능적으로 좋지 않다. 어떻게 해결하는가? JPQL에서는 fetch join이라는 기능을 제공한다. 데이터를 한번에 가져올 수 있도록 해준다. 하지만 두 개 이상의 컬렉션을 가진 엔티티를..
무엇인가? CAS(Compare And Swap)은 동시성 처리를 위한 세가지 방법(volatile, synchronized, CAS) 중 하나로서 말 그대로 “비교한 후 바꿔주는 것”이다. 멀티 스레드, 멀티 코어 환경에서 각 변수는 스레드 내의 스택(캐시)에 저장된다. 이 변수에 대해서 스레드에 저장된 값과 메인 메모리에 저장된 값을 비교하여 값이 같다면 새로운 값으로 치환해준다. 값이 다르다면 계속 재시도를 한다. CAS는 lock을 걸지 않고 변수마다 동기화를 하기 때문에 값이 싸다. 물론 volatile 키워드도 변수마다 동기화를 해줄 수 있지만 읽기 연산에서만 사용할 수 있다는 단점이 있다. 실제로 CAS의 내부 구현에서 메인 메모리의 값을 가져오는 용도로 volatile을 사용한다. 어디에 ..
String 일반적으로 자주 사용되는 String은 불변 객체로서 그 내용이 바뀌지 않고 +, concat 등 문자열 연결을 하게 되면 새로운 객체를 생성하여 연결된 문자열을 할당하고 기존 문자열은 가비지 컬렉터에 의해 회수된다. 그렇기 때문에 여러 입력을 받았을 때 성능 이유가 발생한다. StringBuffer, StringBuilder StringBuffer와 StringBuilder는 불변 객체인 String의 한계를 극복하기 위해 등장한 가변 객체이다. 즉 문자열을 추가하면 기존 객체에 버퍼 크기를 늘려 문자열을 더하는 연산만 하는 것이다. 이로써 성능 이슈를 해결할 수 있게 된다. 그렇다면 두 클래스의 차이는 무엇일까? 그것은 “동기화 여부”이다. StringBuffer는 synchronized..
abstract class(이하 추상 클래스)와 interface(이하 인터페이스)는 하위 클래스(정확히는 다르다.)가 미리 선언된 메소드를 오버라이딩 해서 사용할 수 있도록 하는 도구라는 공통점이 있다. 하지만 이 둘은 차이점이 존재한다. 오히려 차이점이 없으면 두 가지가 존재할 이유가 없다. 그 이유를 외적인 차이와 내적인 차이로 알아보자. 외적인 차이 추상 클래스는 추상 메소드 이외에도 일반 메소드를 선언하고 정의할 수 있다. 그리고 하위 클래스에서 이 클래스를 상속(extends)하여 추상 메소드를 오버라이딩 하여 사용할 수 있다. 반면 인터페이스는 일반 메소드를 정의할 수 없고, 하위 클래스가 인터페이스를 구현(implements)해서 오버라이딩을 통한 메소드 정의를 한다. 인터페이스에서는 메소..
자바 8에서 추가된 큰 기능들 중 하나가 스트림 api이다. 스트림을 사용하면 컬렉션의 요소들의 연산을 쉽게 처리할 수 있다는 큰 장점이 있다. 스트림의 특징은 다음과 같다. 1. 스트림은 요소들을 보관하지 않는다. 필요할 때마다 스트림을 생성한다.2. 스트림은 원본 컬렉션을 변경하지 않는다. 새로운 스트림을 반환할 뿐이다.3. 스트림은 지연(lazy) 처리된다. 예를 들어 정렬을 수행할 때 도중에 결과값을 반환하게 된다면 전체 연산을 수행하지 않는다. 스트림은 또한 간단하게 병렬 처리를 구현할 수 있다. parallelStream()으로 스트림을 생성하면 스트림 라이브러리가 병렬로 연산을 수행한다.12long count = words.stream().filter(w -> w.length() > 12)...