본문 바로가기

스프링 부트58

[스프링] AOP와 JPA 트랜잭션 동작 방식 AOP란? AOP란 관점 지향 프로그래밍의 약자로 흩어진 관심사를 하나로 모듈화 한 것이다. OOP의 개념에서 더 확장된 개념이다. AOP를 구현하는 방법 1. AspectJ 2. Spring AOP AspectJ는 자바에서 제공하는 AOP 기술이다. 3가지 바이트 코드 위빙을 사용한다. 위빙이란? Aspect 를 대상 객체(Target)에 연결시켜 AOP 객체로 만드는 바이트 코드 및 객체 조작과정 1. Compile-time weaving: 소스 코드를 입력하고 클래스 파일을 생성한다. 2. Post-compile weaving: 컴파일 후 위빙, JAR와 클래스 파일을 위빙하는데 사용한다. 3. Load-time weaving: 클래스 로더가 클래스 파일을 JVM에 로드할 때까지 위빙이 연기된다. .. 2022. 11. 1.
[스프링] 동시성 문제를 처리하는 2가지 방법 스프링에서 발생할 수 있는 동시성 문제에 대한 해결 방법 3가지를 알아보자 목차 낙관적 락 비관적 락 낙관적 락 낙관적 락이란 자원에 락을 걸지 않고 동시성 문제가 발생했을때 처리하는 방법이다. 트랜잭션이 충돌하지 않는다고 가정하고, 만약 충돌이 된다면 롤백을 진행시킨다. DB단에서 동시성 처리하지 않고 제어권을 어플리케이션이 가지고 있다는 특징이 있다. 언제 사용할까? 충돌이 잘 일어나지 않는 트랜잭션 -> 락을 걸지 않기 때문에 성능이 좋다. 단점은 없나? 롤백이 발생할때 개발자가 수동으로 하나하나 처리해주어야 한다. Alice가 id 1번을 조회 Bob이 id 1번을 조회 Bob이 id 1번을 업데이트 후 커밋 Alice이 id 1번을 업데이트 시도했으나 이미 version이 달라졌기에 업데이트 쿼.. 2022. 10. 11.
[스프링] 톰캣의 NIO Connector Connector란? 서블릿 컨테이너가 외부와 소통이 가능하게 하는 것을 말한다. 톰캣은 통신을 위해 자바의 IO 기술을 이용하는데 BIO와 NIO 기술이 있다. JAVA Blocking IO Blocking IO는 바이트 스트림을 기반으로 하며, 배열처럼 인덱스가 없고 단순한 데이터의 연속된 흐름이다. Blocking IO 작업을 하게 되면 해당 쓰레드가 진행하는 작업을 중지해야 한다. 따라서 클라이언트 별로 분리된 연결 쓰레드가 생성되야 한다. 그러나 갑자기 접속자가 많아질 경우 쓰레드 수가 늘어나게 된다. 쓰레드가 많으면 많을수록 CPU의 컨텍스트 스위칭이 늘어 오버헤드가 증가하게 되고, 성능에 악영향을 일으키게 된다. JAVA NIO Java.nio는 소켓 연결을 위한 비차단 API로 스레드 수에.. 2022. 10. 8.
[스프링] Hibernate란 Hibernate란? Hibernate는 ORM 프레임워크 중의 하나이다. JPA 인터페이스의 구현체이며, JDBC API를 사용해 DB와 통신한다. JPA란? 자바에서 RDBMS를 사용하는 방식을 정의한 인터페이스이다. 구현체로는 Hibernate가 있다. JDBC란? JPA와 DB를 연결해주는 표준이다. RDBMS는 JDBC 인터페이스를 구현해 제공된다. JDBC 드라이버라고 부른다. 프로그래머는 어떤 종류의 RDBMS를 사용하더라도 똑같은 개발 방법으로 구현하면 된다는 장점이 있다. JPA의 장점 1. SQL 반복 작업을 하지 않아도 되기에 생산성이 올라간다. 2. 인터페이스가 제공되기 때문에 특정 벤더에 종속되지 않는다. 3. 객체와 RDBMS의 패러다임 불일치 문제를 해결해준다. JPA의 단점 .. 2022. 10. 8.
[스프링] 히카리CP란? 우선 JDBC의 개념에 대해서 알아보자 JDBC란 자바에서 데이터베이스에 접속할 수 있도록 하는 API를 말한다. 커넥션 풀이란? 비용이 많이 드는 커넥션 연결 과정을 제거하기 위해 미리 커넥션을 생성해두고, 요청 시마다 연결한 커넥션을 통해 빠르게 DB에 연결한다. Hikari CP Spring Boot 2.0 이상부터 기본 제공 Hikari cp는 DB 커넥션 풀을 관리한다. JDBC의 커넥션 맺는 과정이 복잡하고 많은 자원을 소모하는 작업이기 때문이다. Hikari cp는 미리 정해놓은 커넥션만큼 풀에 담아놓고 요청 시 만들어진 커넥션을 연결한다. 제공되는 설졍 옵션 maxLifeTime: 커넥션이 커넥션 풀에 머무를 수 있는 시간 활성 커넥션은 관계없이 계속 연결된다. maxLifeTime의 값은.. 2022. 10. 7.
[스프링] TestContainer란? 새로 하는 프로젝트에서 TestContainer를 이용해 멱등성 있는 테스트를 구축하고 싶어 알아보게 되었다. TestContainer란? Junit Test를 지원하는 자바 라이브러리, Docker 컨테이너를 사용할 수 있도록 일회용 인스턴스를 사용한다. 어떤 환경에서든 독립적이고 멱등성 있는 테스트 환경을 제공한다. 기존의 방식 H2같은 인메모리 DB 사용 또는 테스트용 DB를 구축해서 사용했다. 인메모리 DB는 실 사용 DB와 방언 차이가 있을 수 있다. 테스트용 DB는 구축하는데 비용이 든다. Local DB를 띄워서 하더라도 각 개발자 환경에 맞춰야 한다. TestContainer 방식을 사용하면 일회성 Docker 컨테이너를 띄우기 때문에 실 DB와 똑같다. 개발자가 테스트용 DB에 대한 리소.. 2022. 10. 4.
[스프링] String 클래스 자동 trim 메서드 적용하기 새 프로젝트 도중 string 클래스가 앞뒤 공백이 있어도 저장이 되는 것을 확인할 수 있었다. DTO의 각 필드마다 trim 메서드를 적용할 수 있었지만 그러면 보일러 플레이트가 너무 많아져 관리 포인트가 늘어난다. 아래 역직렬화 모듈을 String 클래스만 등록하여 사용할 수 있다. StdScalarDeserializer 클래스를 오버라이드하여 원하는대로 커스텀하여 적용할 수 있다. @Component public class StringTrimModule extends SimpleModule { public StringTrimModule() { addDeserializer(String.class, new StdScalarDeserializer(String.class) { @Override public.. 2022. 10. 2.
[개발방법론] DDD란 무엇인가? DDD는 Domain Driven Design의 약자 비즈니스 도메인 별로 나누어 개발하는 방식이다. 핵심 목표 도메인을 서비스별로 분리하자. 모듈 간 의존성은 최소화하고, 응집성은 최대화하기 여러 도메인이 역할에 따라 서로 상호장용하며 설계하는 것이다. Bounded Context에 따라 객체의 역할은 바뀐다. 크게 3가지 레이어로 구분한다. 1. Application Layer - API를 제공하는 계층 2. Domain Layer - Entity, VO를 활용해 도메인 로직이 중점적으로 진행되는 계층 3. Infrastructure Layer - 외부 라이브러리, DB 등을 담당하는 계층이다. DTO는 데이터를 전달하는 역할을 한다. VO는 데이터를 가지고, 자신만의 로직을 가진다. Entity는 .. 2022. 9. 10.
[스프링] 재고 시스템으로 알아보는 동시성 문제 해결 방법 아래 코드를 보면 재고 100개의 요청에서 100개의 재고를 하나씩 감소시켰기 때문에 일반적으로 0이 나오는 것을 예상한다. 그러나 실제로는 race condition이 발생했기 때문에 예상한 결과를 받을 수 없다. @Test public void 동시에_100개_요청() throws InterruptedException { int threadCount = 100; ExecutorService executorService = Executors.newFixedThreadPool(threadCount); CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { executorSe.. 2022. 9. 2.
[스프링] DATA JPA In절로 파라미터 넣기 JPA를 통해 in clause를 쉽게 사용할 수 있습니다. 아래처럼 in을 통해 한 개의 쿼리만 수행됩니다. List findByIdIn(List ids); select .... from Worker where id in (? ,? ,?) 여기서 문제는 ids가 고정된 크기의 객체가 아니라는 점입니다. 한번에 16개를 할당해 결과를 얻고 싶을때 너무 많은 데이터를 대비해 5개씩 짤라서 조회했다고 가정했을때, 여러 가지의 SQL이 생성되고 호출이 됩니다. JDBC에는 PreparedStatement 객체가 있는데 이 객체는 이미 생성된 SQL문을 활용해 지속해서 재사용을 통해 좋은 성능을 얻을 수 있도록 하는 객체입니다. in절을 통해 생성하다보면 호출마다 다른 SQL이 호출되고 저장되어 위의 장점을 활.. 2022. 8. 25.
[스프링] @Query에 ENUM 타입 쓰는 법 프로젝트 진행 중 ENUM으로 조건을 걸어야 할 일이 있어 찾아보았습니다. ENUM 타입의 모든 경로를 가져와 비교하면 String으로 변환되어 쿼리가 수행됩니다. @Query("SELECT w FROM Worker w WHERE w.region = com.detailretail.kurlyflow.common.vo.Region.UNASSIGNED) 2022. 8. 25.
[스프링] UserDetailsService를 여러 개 구현하고 잘 사용하기 그동안의 프로젝트들은 UserDetails를 하나만 구현했었습니다. 최근 진행한 프로젝트에서 관리자와 작업자 간 도메인이 명확히 달랐고, 그에 따른 인증과 인가 과정이 필요했습니다. 이런 경우 보통 관리자 앱으로 따로 만드는 것으로 알고 있지만 단일 프로젝트였기에 jwt 토큰 발행 시 권한을 다르게 부여하고, UserDetailsService 인터페이스의 loadUserByUsername 구현할때 두 개의 서비스를 두고 구현했습니다. @Override public CustomDetails loadUserByUsername(String adminId) { Admin admin = adminRepository.findById(Long.valueOf(adminId)) .orElseThrow(() -> new .. 2022. 8. 25.