이론 정리/Spring boot 16

Fat JAR / Thin JAR 간략정리

Spring Boot 관련 회의를 하는데 Fat JAR이라는 이야기가 나왔다.근데 이거 처음 들어봐서... 한번 찾아봤다.간단하게 말하자면 애플리케이션 실행에 필요한 모든 의존성 및 코드를 하나의 JAR파일로 패키징한 것 이라는 것이다.이를 통해 단일 JAR파일로 애플리케이션을 실행할 수 있다는것.Spring boot에서는 기본적으로 Fat JAR를 생성하며 이렇게 생성되는 덕분에 애플리케이션이 쉽게 배포되는 것이었다!!!대충 정리해 보면Fat JAR의존성을 포함실행에 필요한 모든 파일 포함Spring Boot는 기본적으로 Fat JAR 사용Thin HAR애플리케이션 코드만 포함의존성은 별도 경로에서 로드의존성을 별도로 참조하는 Spring이 이와 비슷한 빌드이다.애플리케이션 -> Thin JAR의존성 ..

간단하게 메서드 수행시간 로깅을 해보자! (feat. template callback, annotation)

간단하게 메서드 수행시간 로깅을 해보자! (feat. template callback, annotation)여기서는 그냥 메서드의 수행 시간을 파악하기 위한 예제이다.실제로는 다양한 곳에 활용이 가능하겠지.기본 세팅TestService.java@Servicepublic class TestService { public void doSomething() { System.out.println("류찬은 최고에요!!"); }}그냥 간단한 sout 하는 메서드를 만들고TestServiceTest.java@SpringBootTestclass TestServiceTest { @Autowired private TestService testService; @Test public..

Spring boot Transactional rollback test와 Transaction 격리에 관한 소고(feat. requires_new)

Transactional rollback test와 Transaction 격리에 관한 소고 다들 알다시피, @SpringBootTest 에서 @Transactional 을 설정하면, 테스트 환경에서 진행한 내용이 실제로 DB와 격리된다. 즉, 테스트에서 뭘 하든 간에 실제 DB에 적용되지 않는다는 것이다. 나는 이거를 통해 여러 테스트를 해 보았는데(사실 근데 혼자 테스트할때는 거의 맨날 넣었다) 이번에 좀 생각치도 못한 변수를 마주해서 정리한다. Transactional의 기본 propagation은 REQUIRED이다. 기본적으로 Spring Boot의 propagation은 REQUIRED로 되어있고, 이건 이전에 활성화된 트랜잭션이 있다면 그 안에서 따로 새로운 트랜잭션의 호출 없이 거기 참가한다..

Spring 기본(IoC, DI, Bean)

IoC 컨테이너 Inversion of Controll 말하자면 제어의 역전 이라는 것이다. 그래서 그게 뭔데? 라고 하면 말하자면 "주도권을 뺴앗겨서, 그 주도권이 Spring에게 있다."는 뜻이다. 예를 들어 Class 설계도 Object 실체화가 가능한 것 예를 들어 abstract class처럼 실제로 존재하지 않는 것들은 Object가 될 수 없다. Instance 실체화 된 것 이런 3개에 대하여 생각해 보았을 때에 보통은 java에서 Public void MakeHandsomeMan() { Ryoochan ryoochan = new Ryoochan(); }이런 식으로 직접 heap영역에 만들었을 것이다. 그러면 MakeHandsomeMan 에서만 ryoochan이 존재하고, 다른 곳에서는 사..

Springboot에서 외부 Redis에 값을 넣고 빼보자(feat.pipeline, Spring boot 3.0)

코드는 https://github.com/RyooChan/redis-pipeline/tree/main 여기서 확인 가능 Springboot에서 외부 Redis에 값을 넣고 빼보자(feat.pipeline, Spring boot 3.0) 해당 테스트를 하기 전에 Redis는 localhost가 아닌 외부에 존재한다고 가정한다. (외부 레디스를 사용하면 네트워크 지연 시간이 발생하게 될 것이다.) 알다시피 레디스는 굉장히 속도가 빠르다. 그렇지만 레디스와 서버는 TCP 네트워크 모델을 기반으로 통신한다. 이게 무슨 뜻일까... 하면, redis와 서버간의 통신 과정에서 TCP 3-way handshake를 따르고, 여러 번 통신을 하면 결국 속도에서 손해를 볼 수밖에 없다는 것이다. 한번 이를 테스트해 보자..

spring boot에서 redis를 사용한 동시성 이슈 처리

Redis를 활용해서 동시성 이슈를 방지하는 두 가지 방법이 있다. Lettuce setnx 명령어를 활용하여 분산락 구현 set if not exist의 줄입말이다. key와 value를 set할 때 기존의 값이 없을 때에만 set하기 spin lock 방식 락을 사용하는 쓰레드가 이걸 사용할 수 있는지 매번 시도하는 방식 retry 로직을 개발자가 직접 구현해야 한다. Redisson pub-sub 기반으로 Lock 구현 제공 앞선 쓰레드가 자신이 끝나면 다음 쓰레드에 접근하라고 할려줌 Lettuce 요런 식으로 lock을 사용하고 setnx를 써서 하면 이전에 만들어둔게 없음 1 -> 만들어짐 이전에 만들어둔게 있음 0 -> 안됨 이전에 있던걸 지우고 다시하면 잘 되는것도 확인 가능 구현이 간단하다..

Spring boot Transactional annotation

Transaction이란 DB에서의 상태 변경을 위해 수행하는 작업의 단위 간단하게 말하면 CRUD를 통해 DB에의 접근을 진행하는 것이다. Transaction은 ACID라는 성질을 갖는다. Atomicity(원자성) 트랜잭션은 모두 DB에 반영되거나, 그렇지 않으면 모두 반영되지 않아야 한다. Consistency(일관성) 트랜잭션 처리 결과는 일관성이 있어야 한다. 즉, 트랜잭션 진행 도중 DB가 변경되어도 처음 트랜잭션 진행을 위해 참조한 데이터 기준으로 적용 Isolation(독립성) 둘 이상의 트랜잭션이 동시에 수행되고 있는다면 다른 트랜잭션의 연산에는 끼어들수 없다. Durability(지속성) 트랜잭션이 성공적으로 완료되면 그 결과는 영구적으로 반영되어야 한다. Transactional a..

값 타입과 임베디드 타입

값 타입 기본값 타입 임베디드 타입(복합 값 타입) 값 타입과 불변 객체 값 타입의 비교 값 타입 컬렉션 기본값 타입 JPA는 데이터 타입을 최상위 레벨로 볼 때 두가지로 분류한다. 엔티티 타입 @Entity로 정의하는 객체 데이터가 변해도 식별자를 통해 지속해서 추적이 가능하다. 값 타입 int, Integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체 식별자가 없고 값만 있으므로 변경시 추적이 불가능하다. 값 타입의 분류 기본값 타입 자바 기본 타입(int, double) 래퍼 클래스(Integer, Long) String 임베디드 타입(enbedded type, 복합 값 타입) 컬렉션 타입 기본값 타입 생명 주기를 엔티티에 의존한다. 즉 엔티티를 삭제하면 기본값도 삭제된다. ..

컬렉션 페치조인과 페이징 하기(feat. batch size)

디프만 프로젝트에서 댓글 관련 API중 하나를 담당했는데, 해당 내용은 어떤 맥주를 통해 이곳에 작성된 모든 기록들을 받아오고, 동시에 저장된 맛(최대 3개)를 가져와 보여준다. 그리고 여기 페이징을 적용한다. 였다. 즉 이 경우 기록 -> 맛을 가져올 때 일대다 조인이 생기게 된다. 맥주를 통해 기록을 가져옴(여기서 N개의 기록을 가져옴) 해당 기록에 있는 맛태그를 가져옴(최대 3개의 맛태그) 맛태그를 통해 맛을 가져옴(다대일) 2, 3번의 로직을 수행할 때에 문제가 여러개 생기게 된다. 먼저 일대다 조인의 경우 페치 조인만으로 페이징을 할 수 없다. 알다시피 일대다 조인을 페치조인하면 동일한 데이터가 여러 번 출력되어 데이터가 뻥튀기된다!! 그리고 비효율적인 쿼리가 생성되게 된다. 하나의 기록마다 맛..

페치 조인과 그 한계에 관하여

실무에서 매우 중요하다. SQL의 조인 종류에 해당하지는 않는다. JPQL에서 성능 최적화를 위해 제공하는 기능이다. 연관된 엔티티나 컬렉션을 SQL한 번에 조회하는 기능. join fetch 명령어 사용 예를 들어 회원을 조회하면서 연관된 팀을 함께 조회하려 한다(SQL한번에) select m from Member m join fetch m.team -> SELECT M., T. FROM MEMBER M INNER JOIN TEAM T ON M.TEAM_ID=T.ID 아래와 같이 inner join을 사용하여 Team이 있는 member들을 가져온다고 가정한다면 JpaMain public class JpaMain { public static void main(String[] args){ EntityMa..