Server 121

JPA - 비관적 락, 낙관적 락 (+ 트랜잭션 격리 수준) 정리!

격리 수준 락(Lock)을 이해하기 전에 트랜잭션 격리 수준을 먼저 알아야한다. 트랜잭션 격리수준(isolation level)이란 동시에 여러 트랜잭션을 처리할 때, 트랜잭션이 얼마나 서로 고립되어 있는지를 의미한다. 즉, 해당 트랜잭션이 다른 트랜잭션에서 변경한 데이터를 볼 수 있는 기준을 결정하는 것이다. 격리수준은 크게 4가지로 나눌 수 있다. READ UNCOMMITTED 커밋되지 않은 데이터를 읽을 수 있다. Dirty Read, Dirty Write가 발생할 수 있다. READ COMMITTED 커밋된 데이터만 읽을 수 있다. 오라클 DBMS에서 표준으로 사용하고 있고 가장 많이 선택된다. Lost Update, Write Skew, Read Skew가 발생할 수 있다. REPETABLE R..

Server/Spring JPA 2022.04.17

Spring Boot - Thread Pool을 관리하는 방법! (Spring Boot에서의 Thread 기본 원리) [ThreadPoolExecutor]

ThreadPool의 동작을 이해하는 것이 개발하는 앱 서버에 영향을 미칠까..?! ThreadPool은 응답 시간, 처리 속도, TPS에 영향을 미친다. 추가로 병목 현상, CPU 오버헤드, 메모리 부족 등의 문제를 방지해서 안정적인 어플리케이션의 운용이 가능하게 합니다. 즉, ThreadPool에 대한 기본적인 개념을 알아야 더 좋은 Server Application을 개발할 수 있습니다. Java - Threading Model Java에서는 One-to-One Threading-Model로 Thread를 생성합니다. One-to-One Threading-Model은 User Thread(Process의 스레드) 1개는 OS Thread 1개와 연결해야 합니다. 이때 작업 요청이 들어올 때마다 Th..

Server/Spring 2022.04.16

Spring Data JPA - JpaRepository 구현체에 @Transactional(readOnly = true)가 있는 이유

JpaRepository Spring Data JPA를 사용할 때 JpaRepository를 상속하는 interface를 만들어서 사용합니다. public interface MemberRepository extends JpaRepository { } 우리는 interface를 상속했을 뿐인데, findAll() 같은 다양한 CRUD 메서드를 사용할 수 있습니다. memberRepository.findAll(); Spring Data JPA는 내부적으로 JpaRepository를 상속하기만 해도 아래와 같은 구현체를 생성해주기 때문입니다. @Repository @Transactional(readOnly = true) public class SimpleJpaRepository implements JpaRep..

Server/Spring JPA 2022.04.10

Spring Data JPA - Bulk Update(일괄 수정)할 때 주의할 점! [영속성 컨텍스트]

Bulk Update JPA에서는 변경 감지를 통해 엔터티를 수정할 수 있지만, 그러면 각 엔터티별로 쿼리가 나가게 됩니다. 그래서 변경할 레코드들의 SET 절이 동일하다면 일괄 수정을 하는 것이 좋습니다. 가령, 만약 모든 사용자에게 10000원의 리워드를 제공하겠다고 하면 1개의 쿼리로 전체 업데이트를 할 수 있습니다. UPDATE user SET point = point + 10000; @Modifying Spring Data JPA에서는 벌크 업데이트를 위해서 Modifying 애노테이션을 사용해야 합니다. SpringDataJPA가 해당 리포지토리 메소드가 SELECT문인지 UPDATE문인지 알아야 Return Type을 결정하는데, 아직은 내부적으로 Query만 보고 판단을 못해서, 명시를 해..

Server/Spring JPA 2022.04.08

Spring Data JPA - Named query 정리 (+ @Query) !!

Spring Data JPA Named query Repository에서 SQL문을 직접 작성할 떄는 JPA의 Named query라는 것을 사용할 수 있습니다.\ Named query의 사용 방법과 장단점에 대해서 알아보겠습니다. @NamedQuery JPA에서는 NamedQuery라는 것을 제공하는데, 엔터티에 @NamedQuery 애노테이션을 사용해서 name과 query를 지정합니다. @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @NamedQuery( name = "User.findByUseranme", query = "select u from User u where u.username = :username" ) public class ..

Server/Spring JPA 2022.04.08

Sequelize - fn(), literal(), col(), where() 잘 사용하기!

Sequelize.fn()Sequelize.fn()을 사용하면 sql 함수를 쉽게 사용할 수 있습니다. 예시를 몇개 들겠습니다.// SUBSTR(str, pos);sequelize.fn("substr", str, pos);// IFNULL(a, b);sequelize.fn("ifnull", a, b);// SUM(a, b);sequelize.fn("sum", a, b);// CONCAT(a, b);sequelize.fn("concat", a, b);첫 번째 파라미터로는 함수명을, 두 번째 파라미터부터는 대상을 지정하면 됩니다.function fn(fn: string, ...args: unknown[]): Fn;SELECT에서 사용할 때는 아래와 같이 사용할 수 있습니다. attributes를 배열로 정의..

Server/Node.js 2022.03.25

Sequelize - SubQuery를 FROM 절에서 사용하기(?)

Sequelize - SubQuery in From clause SQL 함수를 SELECT 절에서 계산된 결과를 WHERE절 조건식에 넣고 싶은 경우가 간혹 있습니다. 예를 들면 아래의 경우 입니다. SELECT * FROM (SELECT CONCAT(first_name, ' ', last_name) AS fullName FROM user) WHERE full_name LIKE '%david%'; 그래서 공을 들여 관련 내용을 어떻게든 찾아봤는데... 결론부터 말씀드리면, 안타깝게도 할 수 없습니다! 아래 이슈를 보시면 많은 분들이 원함에도 불구하고, 해당 기능을 사용할 수 없습니다. https://github.com/sequelize/sequelize/issues/5354 따라서, 아래의 선택들이 있..

Server/Node.js 2022.03.25

JPA - 영속성(persistence란) [+1차 캐시]

영속성 Spring JPA 로고를 보면 영속성(persistence)라는 단어가 크게 그려져 있습니다. 그만큼, 영속성 없이 Spring JPA를 얘기하기 힘듭니다. 영속성은 쉽게 말하면 지속을 의미합니다. 더 자세히 풀자면, 엔터티를 사용하고 바로 폐기하는 것이 아니라, 저장을 해서 지속적으로 사용하며 얻는 이점을 얻는 것을 말합니다. 예를 들어, JPA에서 repository.findOne을 동일한 데이터에 대해 조회를 5번 요청합니다. 하지만, DB의 쿼리 로그나 JPA가 기록한 로그를 보면, SELECT문이 1번만 실행됩니다. 그 이유가 영속성입니다. 첫번째 SELECT한 결과를 JPA의 1차 캐시에 보관하고 계속 재사용하기 때문입니다. 1차 캐시 JPA에서 1차 캐시는 EntityManager가..

Server/Spring JPA 2022.03.15

Jest - 테스트 코드간 충돌, 간섭 막는 방법 (매번 테스트 결과가 다를 때 해결 방법!)

테스트 코드 충돌 (간섭) 사내에서 jest + supertest를 이용해서 테스트 코드를 작성하고 있었습니다. 그런데, 자꾸 테스트를 돌릴 때마다 한 번씩 테스트가 깨지는 현상이 발생했습니다. 알고보니 테스트 코드 파일 A가 다른 테스트 코드 파일 B랑 비동기로 실행되다 보니까 서로 간섭하는 현상이 생기는 것이었습니다. 상황 충돌을 일으킨 테스트 2가지는 아래와 같습니다. 카테고리 MVC 테스트 상품 MVC 테스트 프로젝트 구조가 상품 등록 API를 테스트할 때는 먼저 카테고리를 생성한 후에 상품 등록 API에 요청을 보내는 구조였습니다. 상품 등록 API는 등록할 카테고리의 id를 받아서, 해당 카테고리가 없으면 예외가 발생하기 때문에 그렇게 설계했습니다. 카테고리 MVC 테스트는 각 테스트가 실행될..

Server/Node.js 2022.02.28

Sequelize - bigint를 사용하는 방법? (+ underscored)

DB에 bigint로 저장된 컬럼을 API에서 꺼내서 그대로 사용하면 바이트 부족으로 인해서 데이터가 손실됩니다..!! Sequelize에서는 아래와 같이 dialectOptions의 supportBigNumbers를 정의해서, 손실을 방지할 수 있고, bigNumberStrings를 정의해서 string으로 받을 수도 있습니다. import { Sequelize } from "sequelize"; const shopDB = new Sequelize( "shopDB", "root", "root", { host: "localhost", dialect: "mysql", pool: { max: 10, min: 0, acquire: 5000, idle: 10000, }, timezone: "+09:00", di..

Server/Node.js 2022.01.11