분류 전체보기
[Jpa] Transaction Propagation
JPA 를 사용하여 @Transactional 에노테이션을 메소드에 설정하면 트랜잭션이 시작하는 시점과 commit 되는 시점이 메소드의 처음과 끝이라는 것을 알 것이다. 우리가 Repository에 save 하는 과정에서도 트랜잭션 처리가 되어 있다. 만약 이 save() 를 한 줄, 한 줄 호출을 한다면 별도의 트랜잭션을 사용하여 동작이 되는 것이겠죠. 지금부턴 트랜잭션의 전파(Propagation)에 대해 간단히 포스팅 해보겠습니다. 우리는 Member라는 정보를 Repository에 저장하고 수정하는 로직에 더티 체킹이라는 것을 알고 있다. 더티 체킹은 트랜잭션 단위에서 영속성 컨텍스트 내부에서 1차 캐시의 스냅샷을 기준으로 변경된 값을 비교하는 동작을 더티 체킹이라 하는데 이러한 동작은 어떻게 ..
[Item 26] 로 타입(Raw Type)은 사용하지 말라
로 타입은 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않을 때를 말한다. List list = new ArrayList(); 위와 같은 형태를 말한다. 로 타입의 문제점 타입 안정성과 표현력을 확보할 수 없다. 문제점이 컴파일 시에 걸러내지 못하고 런타임에 예외가 발생한다. 따라서 매개 타입을 선언해서 타입 안정성과 표현력을 가져가야 한다. List와 List의 차이점 임의의 객체 타입을 받는다는 표현을 한 것이고 두 동작은 같을 것이다. 대신에 컴파일러가 이 사실을 아냐 모르냐에 차이점이 있다. Object 의 매개 타입은 모든 타입을 허용한다는 표현을 한것이고 컴파일러에게 전달한다. 이로 인해 List은 하위 타입 규칙과 타입 안정성을 모두 지킬 수 있게 된다. 매개 변수 타입에서 사용된다면 pu..
[Item 25] 톱레벨 클래스는 한 파일에 하나만 담으라
소스를 작성하는 파일 내에 하나만 존재하는 클래스를 톱레벨 클래스라고 한다. 소스 파일 하난에 여러개의 톱레벨 클래스가 있다면 문제가 있다. 문제 Product.java class Product { static final StringNAME= "phone"; } class Company { static final StringNAME= "samsung"; } Company.java public class Company { static final StringNAME= "samsung"; } class Product { static final StringNAME= "phone"; } 위의 소스코드는 컴파일 에러에서 중복된 클래스라 에러가 발생할 것이다. 컴파일러에게 어느 소스파일을 먼저 읽게 하냐 에 따라 정..
[Jpa] Transaction Scope and Isolation
트랜잭션은 어떤 작업을 하는데의 단위 묶음이라 한다. Jpa에서 중요한 역할을 하는데 Jpa에서 쿼리가 나가는 시점은 트랜잭션이 시작되고 끝나는 시점에 커밋이 되는 시점에서 쿼리가 발생한다. 또한 강제로 flush() 를 하면 쓰기 지연 sql저장소에 들어 있던 쿼리가 비워지면서 쿼리를 발생시킨다. 영속성과 트랜잭션의 관계 @Test @DisplayName("member save") @Transactional @Rollback(value = false) void memberSave() { Member member = new Member("이기영", "기영@naver.com", Gender.MALE); em.persist(member); } memberSave() 메서드를 한 작업의 묶음으로 설정하고 me..
[DataBase] Index란?
책에서 우리는 원하는 단어를 찾을 때 우리는 목차를 볼 때도 있고 단어를 정리한 페이지를 찾을 때도 있다. 우리는 이를 활용해서 시간을 절약할 수 있고, 여기서 목차는 인덱스라 말한다. 이와 같은 인덱스는 자료를 찾을 때 시간을 절약할 수 있게 만든다. 한편으로는 책의 페이지 수가 늘어난다는 점이다. 이제는 인덱스에 대해 이해가 조금은 갈 것이다. 탐색 알고리즘에서 우리는 해쉬 테이블과 이진 트리를 접했다. 이진 트리는 자식이 2개 이하인 트리를 말하고 root 노드가 하나 있고 그 밑에 하위 노드들이 뿌리처럼 가지고 있다. 해쉬 테이블은 해쉬 함수를 통해 주소 값을 참조하고 새로운 테이블을 만들어 관리하는 식이다. 인덱스는 이러한 원리로 동작하게 된다. 해쉬 테이블 (Hash Table) 해쉬 테이블은..
[Jpa] Deprecated 된 getById() 대안 getReferenceById()
기존의 getById() Spring 2.5 이전 버전에선 getOne()과 getById()란 메서드가 있었다. getOne()과 getById()는 findById()와 같은 동작을 하지만 분명한 차이점이 있다. 먼저 메서드 명으로 동작을 유추해보자. getOne() 은 하나를 가져온다? 라고 해석이 된다. 뭔가 메서드 명에서 재사용 하기에 부족한 것 같은 느낌이 든다. 찾아 보니 deprecated가 되었다. getById() 는 Id 로 부터 가져온다.? 라고 해석이 된다. findById() 는 Id 로 부터 찾아온다.? 라고 해석이 된다. 즉, getById() 는 영속성 컨텍스트에 올라가 있는 프록시 객체를 lazy 로딩으로 가져온다. findById() 는 직접 DB를 조회하여 where ..
[Spring Boot] Spring 에서 비동기 처리 방식은 어떻게 하고 왜 사용해야 할까?
들어가기전. 동기식과 비동기식을 이해하고 있어야 한다. 이 방식을 이해하고 넘어가면 Spring에서 간단히 에노테이션만 붙여주면 적용법은 끝날 것이다. 먼저 동기식을 설명하겠다. 동기식은 개념은 동시에 처리 하는 방식이라 생각하면 된다. 요청과 응답이 시간이 얼마나 걸리던지 요청한 자리에서 결과가 주어져야 한다. 비동기식의 개념은 동시에 처리 하는 방식이 아니라 생각하면 된다. 즉, 요청을 보내면 동시에 응답이 일어나지 않는다. 동기식의 구현은 매우 간단하고 직관적이지만 응답이 내려질 때까지 아무것도 못하고 대기해야 하고 교착 상태와 기아 상태가 발생할 수 있다는 단점이 있다. 비동기식의 동기식보다 복잡하지만 응답이 내려지는데 시간이 걸리더라도 다른 스레드가 다른 작업을 할 수 있다. 하지만 스레드 안정..
[Spring Boot] Interceptor 는 어떻게 사용하고 왜 사용해야 할까?
들어가기전. Interceptor 는 filter와 유사하다. 요청 응답의 정보가 전달 되면 전 후 처리를 할 수 있다. 정보를 가로 채서 컨트롤 할 수 있다. 주로 인증 단계나 필터와 같이 로깅 작업을 할 수 있다. Interceptor는 계층 구조로 하나의 interceptor가 실행되고 또 하나의 interceptor를 추가해 단계 별로 인증체크를 할 수 있다. 사용법을 알아가기 전에 Filter와의 차이점은 무엇일까? 아래의 구성도를 살펴보자. 필터는 스프링 컨텍스트 외부에서 적용이 되고 인터셉터는 스프링 컨텍스트 내부에서 적용이 되고 있다. 필터의 doFilter() 메서드의 매개변수도 살펴보자. 컨텍스트의 Object가 존재하지 않는다. 인터셉트의 메서드의 매개변수를 살펴보자. 핸들러를 할 수..
[Spring Boot] Filter를 왜 사용해야하고 어떻게 사용하는 걸까?
Servlet 에서 제공하는 기능이자 스프링 프레임워크에서도 제공하는 기능이다. 말 그대로 앞단에서 무언가를 걸러줄 때 사용한다. 아래 그림은 대표적인 구성도다. DisPatherServlet 앞단에서 존재하고 있고 DisPatherServlet이 요청과 응답을 다루기 전과 후에 동작을 한다. 위 그림만 보면 라이프 사이클이 예상 될 것이다. 클라이언트로부터 오는 모든 요청과 응답의 순수한 정보에 대해서 컨트롤 할 수 있다는 것을 기대한다. 특징 순수한 RequestBody와 ResponseBody를 확인을 할 수 있다. 유일하게 servletRequest, servletResponse의 객체를 변환 할 수 있다. 인증과 관련된 로직들을 해당 필터에서 처리한다. 왜 Filter 사용해야할까? 요청으로 들..
[Spring Boot] Validation을 왜 해야하고 어떻게 할까?
Validation 사전적 의미를 찾아보자 출처 : https://ko.wikipedia.org/wiki/밸리데이션 밸리데이션 - 위키백과, 우리 모두의 백과사전 위키백과, 우리 모두의 백과사전. 밸리데이션(Validation)이란 '특정 공정이 설정된 규격과 품질 요소들을 만족하고 있는 제품을 지속적으로 생산하고 있음을 보증하기 위한 증거를 문서화하는 것' ko.wikipedia.org 시스템이 사전 설정된 허용 기준에 부합하는 결과를 일관되게 만들어내는 점을 문서화된 프로그램으로 정의하는 것이라 나와 있다. 즉, 서버에 들어온 데이터가 서버에서 요구하는 스펙이랑 일치하는지의 검사를 말한다. 그렇다면 왜 이러한 검사를 해야할까? null 인 데이터를 받아 객체를 인스턴스화를 하면 인스턴스를 만들 수 없..
[Spring Boot] 예외처리를 왜 해야하고 어떻게 처리할까?
예외와 오류에 대해 알아보자. 먼저 예외(Exception) 과 오류(Error)는 다르다는 것을 명심하자. 오류(Error)는 시스템이 정상 활동 되다가 갑자기 종료되거나 서비스가 작동작하지 않고 먹통 상태가 되는 심각한 영향을 준다. 오류 처리를 왜 해야하는가? 2가지만 명심하자. 시간 돈 오류 해결에 의해 시간과 돈이 들어간다. 서비스가 먹통이 되면 엄청난 손실이 올 것이다. 예외(Exception)는 개발자 즉, 프로그램을 만든 사람의 실수에서 나온다. 개발 당시에 생각하지 못한 부분에서 프로그램에 잘못된 영향을 준다. 예외 처리를 왜 해야하는가? 사용자에 임시적인 가이드를 제공 예외도 서비스를 사용하는 사람 입장에서 불편함이 있겠지만 프로그램이 완전히 죽는 것 보단 나을 것이다. 예외, Erro..
[Item 24] 멤버 클래스는 되도록 static 으로 만들라
중첩 클래스(nested class)란 다른 클래스 안에 정의된 클래스를 말한다. 자신을 감싼 바깥 클래스에서만 쓰여야 한다. 그 외의 쓰임새가 있다면 톱레벨 클래스로 만들어야 한다. 중첩 클래스의 종류 정적 멤버 클래스 (비정적) 멤버 클래스 익명 클래스 지역 클래스 정적 멤버 클래스를 제외한 나머지 3가지가 내부 클래스(inner class)에 해당한다. 정적 멤버 클래스와 비정적 멤버 클래스는 구문상 차이는 단지 static이 붙어 있고의 차이뿐이지만, 의미상 차이는 꽤 크다. 비정적 멤버 클래스 인스턴스 생성 public class Outer { private int a; class inner { private int b; } } Outer outer = new Outer(); Outer.inne..
[Item 23] 태그 달린 클래스보다 클래스 계층구조를 활용하라
태그 달린 클래스는 장황하고, 오류를 내기 쉽고, 비효율적이다. 클래스 계층구조보다 나쁘다. public class Figure { enum Shape {RECTANGLE,CIRCLE} private final Shape shape; private int length; private int width; private int radius; public Figure(int radius) { this.shape = Shape.CIRCLE; this.radius = radius; } public Figure(int length, int width) { this.shape = Shape.RECTANGLE; this.length = length; this.width = width; } public int area(..
[Item 22] 인터페이스는 타입을 정의하는 용도로만 사용하라
인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다. 달리 말해, 클래스가 어떤 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에 얘기해주는 것이다. 인터페이스는 오직 이 용도로만 사용해야 한다. 상수 인터페이스 안티패턴 public interface PhysicalConstants { static final intFIRST= 1; static final intSECOND= 2; static final intTHREE= 3; } 이러한 인터페이스는 안티 패턴이므로 사용하지 말자. 클래스 내부에서 사용하는 상수는 외부 인터페이스가 아니라 내부 구현에 해당한다. 클라이언트 코드가 내부 구현에 해당하는 이 상수들에 종속되게 한다. 상수를 공개하는 방..
[Item 21] 인터페이스는 구현하는 쪽을 생각해 설계해라
자바 8 전에는 기존 구현체를 깨뜨리지 않고는 인터페이스에 메서드를 추가할 방법이 없었다. 인터페이스에 메서드를 추가하면 기존 구현체에 이미 메서드가 존재하는 가능성이 적기에 자바 8 이후에 기존에 인터페이스에 메서드를 추가할 수 있도록 디폴트 메서드를 제공했다. 디폴트 메서드는 주로 람다를 활용하기 위해 선언하는데, 디폴트 메서드를 선언하면, 그 인터페이스를 구현한 후 디폴트 메서드를 정의 하지 않은 모든 클래스에서 사용이 가능하다. 불변식을 해치지 않는 디폴트 메서드를 작성하기란 어려운 법이다. Collection 인터페이스의 removeIf() 의 디폴트 메서드를 보면 모든 Collection 구현체와 어우러지는 것은 아니다. Collection 인터페이스를 구현한 SynchronizedCollec..