들어가며 현재 사이드 프로젝트 겸 플레이 그라운드 프로젝트에 랭킹 기능을 도입하려고 합니다. 해당 랭킹 기능은 미션 별 step 내림차순입니다. 위 기능을 구현하는 도중 레디스의 Sorted-Set 자료구조를 이용하면 key-value 중복 제거 기능으로 간편하게 구현할 수 있으며, 조회 성능은 폭발적으로 증가시킬 수 있을 것 같았습니다. 참고로 미리 구현한 기능의 응답 시간입니다. 유저 한 명의 요청을 처리하는 데 389ms의 시간이 걸리는 상황입니다. Redis Sorted Set(Zset) 레디스는 다양한 형태의 자료 구조를 제공합니다. 기본적으로 key-value 형태의 구조를 띄며, value가 사용하는 자료 구조에 따라 기능을 사용할 수 있습니다. Sorted Set은 이름에서 알 수 있듯이 ..
들어가며 지난 글에서 JPA가 알아서 동시성 이슈를 해결해주는 모습을 보였지만, 어디까지나 운이라는 결론을 내렸습니다. 이어서 어드민 페이지 동시성 이슈를 직접 해결해보겠습니다. 두 번의 갱신 분실 문제 JPA가 동시성 문제를 파악하고 예외를 던져주는 행위가 운이라고 했는데, 이는 영속성 컨텍스트를 계속 동기화 시켜주는 부분을 제거하면 곧 바로 동시성 문제가 다시 발생하기 때문입니다. 여기서 말하는 동시성 문제란 두 번의 갱신 분실 문제를 뜻하는데, 아래와 같이 3가지 상황이 존재합니다. 최초 커밋만 인정하기 : 첫 번째로 커밋한 트랜잭션의 변경 사항만 반영하고, 마지막 트랜잭션의 변경 사항은 무시한다. 마지막 커밋만 인정하기 : 마지막으로 커밋한 트랜잭션의 변경 사항만 반영하고, 첫 번째 트랜잭션의 변..
들어가며 이번 글에서는 팀 프로젝트의 어드민 페이지에서 데이터 수정에 관련한 동시성 이슈를 알아보려고 합니다. 저희 서비스의 관리자 페이지는 유저들에게 직접적으로 보이는 식품 데이터를 생성/수정/삭제할 수 있는 기능을 제공합니다. 선착순 시스템 등과 갑자기 많은 트래픽이 몰리진 않겠지만, 유저와 사료를 파는 브랜드에게 직접적인 영향이 가는 영역이기 때문에 한 번 발생하게 된다면 서비스 운영에 치명적으로 작용할 수 있습니다. 어떤 문제가 발생할까 그렇다면 만약 2명의 어드민이 동시에 하나의 식품을 수정하게 된다면 어떤일이 발생할까요? 아래는 사료 데이터를 수정하는 메서드 2개를 동시에 실행하는 테스트 코드입니다. 저는 처음에 낙관적 락과 비관적 락을 모두 사용하지 않은 상태였기 때문에 두 번의 갱신 분실 ..
개념적 차이 List와 Set은 모두 JCF이다. 당연히 차이도 존재한다. List에는 중복 데이터가 포함될 수 있지만, Set에는 중복 데이터가 포함될 수 없다. List는 삽입 순서를 유지하지만 Set은 유지할 수 있고, 유지하지 않을 수도 있다. Set은 삽입 순서가 유지되지 않을 수 있으므로 인덱스 기반 액세스를 허용하지 않는다. LinkedHashSet과 같이 순서를 유지하는 Set도 있다. List와 Set 성능 비교 JMH(Java Microbench Harness)를 사용해서 List, Set 데이터 구조의 성능을 비교해 보자. 먼저 ListAndSetAddBenchmark 및 ListAndSetContainBenchmark라는 두 개의 클래스를 만든다. 그다음 List 및 Set 데이터 ..
서론 JPA와 Querydsl을 사용하면서 DTO에 관해 느낀 것이 많다. 그래서 이번 글에는 JPA와 Querydsl으로 개발을 진행할 때 고려해 보면 좋을 몇 가지에 대해 소개하겠다. Repository에서 DTO를 반환해야 하는 이유 여러분들은 Querydsl에서 DTO를 반환해야 한다는 이야기를 자주 들어보았을 것이다. 다만, Querydsl에서 DTO를 아무 의미 없이 기계적으로 반환한다면 그건 옳지 않다고 생각한다. 필자가 Querydsl에서 DTO를 반환하는 이유는 다음과 같다. 엔티티 보호 엔티티를 사용자에게 노출하면 원하지 않는 상황에서 자원의 속성이 변경될 가능성이 있다. 그리고 엔티티를 프레젠테이션 계층에 노출하는 것은 테이블 설계와 화면을 공개하는 것이나 다름없기 때문에 보안상으로도..
서론 개발을 하면서 Application Code와 Database Query 둘 중 어느 것을 사용하여 비즈니스 로직을 처리해야 할지 고민했던 적이 있었는가. 그런 상황이 적지 않았을 것이라고 생각한다. 필자는 꽤나 궁금해서 과연 Application Code와 Database Query 사이의 패러다임을 어느정도 감안하고 Trade Off 해야 할지, 더 나아가선 성능은 얼마나 차이가 나는지 측정해보려고 한다. 구현 내용 우선 요구 사항은 필터링 기능이 주를 이룬다. 애플리케이션 코드로 처리하든, 쿼리로 처리하든 개발자에게는 꽤나 많은 리소스가 들 것이라고 예상되기 때문이다. 필터링 요구사항은 다음과 같다. 카테고리별 복수 선택이 가능하며, 같은 카테고리에서 복수 선택 시 or 조건 발생, 다른 카테..
집사의고민 프로젝트에서 JPA를 사용하면서 알아본 Fetch Join시 유의해야 하는 부분들에 대해서 기술해보려고 합니다. 특히나 자주 사용하는 fetch join + on절에 대한 이슈를 모르거나 잘 기억이 나지 않으신다면 이해하고 넘어가는게 좋습니다. 우선 쿼리가 정상적으로 동작하는지와 어떤 쿼리가 발생하는지를 알아보기 위해 간단한 테스트 코드를 작성해보았습니다. PetFoodRepositoryImplTest @DataJpaTest @Import(QueryDslTestConfig.class) @Sql(scripts = {"classpath:truncate.sql", "classpath:data.sql"}) @AutoConfigureTestDatabase(replace = AutoConfigureTes..