들어가며 '동시성 문제'는 CS 공부를 하거나, 백엔드 개발을 하다 보면 종종 마주하는 문제입니다. 저 역시도 프로젝트 개발 과정에서 본래 상승해야 하는 값이 아닌 다른 값으로 update 되는 케이스를 마주한 경험이 있었습니다. 문제를 해결하기 위해서 전에 공부했던 지식과 기술 블로그, GPT 등을 통해 공부하며 느낀 점은, 선택지가 굉장히 다양하다는 점이었습니다. 아무래도 우리는 개발자니까, 많은 선택지 가운데서 각각의 특징을 이해하고, 서비스와 팀의 상황에 가장 적합한 방법을 고려하는 것이 중요하죠. 이번 글에서는 제가 준비한 여러 방법들에 대한 간단한 개념과 특징, 그리고 적용 방법에 대한 예제를 소개하겠습니다. 그리고 마지막에는 충돌 상황에서 각 방법에 대한 성능 테스트를 진행한 결과를 표와 그..
🍃 Spring
조금 오래되긴 했지만 이전에 캐시에 대한 글을 작성하면서 로컬 캐시와 글로벌 캐시의 특징을 다룬 적이 있었다. 이때, 로컬 캐시는 일반적으로 서버 어플리케이션의 메모리에 함께 저장되기 때문에 캐시를 사용할 때 별도의 네트워크 IO가 발생하지 않아 글로벌 캐시에 비해서 더 빠른 성능을 보여준다고 했었다. 하지만 서버가 여러 대가 존재한다면, 동일한 내용들을 복수의 서버에 저장하게 되어서 자원 낭비가 발생할 수 있고, 캐시에 저장된 내용이 변경될 경우엔 다른 서버의 캐시들도 변경해줘야 하는 문제가 발생한다. 여기서 말한 캐시에 저장된 내용이 변경될 경우엔 다른 서버의 캐시들도 변경해줘야 하는 문제가 이번 글에서 다뤄볼 로컬 캐시의 동기화 문제이다. 사실 어떤 일이 발생할 지에 대해서는 이 문장을 읽기만 해..
캐시란?캐시는 애플리케이션의 성능을 대폭 상승시켜 주는 대표적인 기술입니다. 조회 성능이 더 느린 계층에서 발생하는 병목 현상을 줄이기 위해 조회 성능이 더 빠른 계층에 임시로 데이터를 저장하는 방법입니다. 컴퓨터 구조에서의 메모리 계층에서 캐시라는 개념을 처음 접할 수 있지만, 저같은 백엔드 개발자는 DB(스토리지)에 저장된 것을 RAM으로 저장하여 조회 성능을 상승 키시는 것이 생각나네요. 조회 성능이 뛰어나게 된다면, 모든 정보를 캐싱하면 우리의 서비스는 기존보다 더 많은 트래픽에 대응할 수 있는 서비스로 성장할 수 있겠죠. 하지만 모든 정보를 캐싱하는 것을 불가능에 가깝습니다. 바로 돈 때문입니다. 우리가 컴퓨터를 구매하려고 할 때, SSD가 더 빠르지만 HDD가 훨씬 싸기때문에, 대량의 디스..
개요프로젝트를 진행하면서, 개발자는 로그를 남기게 됩니다. 로그를 남기는 이유는 다양합니다. 저 같은 경우엔 주로 값이 잘 넘어갔는지, 값이 다시 잘 왔는지, 오류가 났는지, 오류가 났다면 어디서 났는지... 등의 이유로 로그를 남기곤 했습니다.꼼꼼하게 로그를 남긴다면 오류가 발생했을 때 빠르게 원인파악이 가능해서 대응에 도움이 될 것입니다. 추가로 사용자들이 어떻게 서비스를 이용하는지에 대한 데이터를 확보할 수 있을 겁니다. 이처럼 중요한 정보를 담고 있는 로그를 저는 지금까지 별 생각없이 매번 Spring이 해주는 기본 설정으로 로그를 사용했었는데요, 기본 설정을 벗어나, 로그 라이브러리를 제대로 사용하는 방법을 공부해야 할 필요성을 느꼈습니다. Spring Boot에서 기본으로 사용한다는 `Logb..

개요Java, Spring으로 백엔드를 구성하면 데이터베이스를 다룰 일이 있을 것입니다.저의 주변에선 주로 JPA나 Mybatis를 이용해서 데이터를 다루는 것을 확인했습니다.저 역시 일반적으로는 JPA와 QueryDSL과 같은 기술들을 이용하지만 특정 상황에서 성능이 너무 떨어진다면 JdbcTemplate이나 Mybatis를 고려하게 되는 일들이 있었습니다. 이번 포스팅에서는 이처럼 다양한 DB 접근 방법 중 insert를 하는 방법에 대해서 알아보고, 각 방법의 성능을 비교해 보도록 하겠습니다. Insert를 하는 다양한 방법 기본적으로 Java에서 DB에 접근하기 위해선 JDBC를 이용해야 합니다. 하지만 직접 JDBC를 이용해서 DB를 조작하는 것은 여러 반복 코드가 발생하고, 커넥션 관리 등 신..
이전 상황 정리 이전 글은 Data JPA를 사용해서 Delete를 진행했을 때, N+1이 발생해서, 성능 저하가 발생했었고, `delete where in ...` 쿼리를 직접 작성하는 것으로 엄청난 성능 향상을 가져왔었다. 이젠 이 쿼리를 프로젝트에 적용하고 성능을 체크해보자. 적용 프로젝트에 적용하기에 앞서, 다시 한번 관계를 확인하겠습니다. Feed를 삭제하면 다음과 같은 관계를 갖습니다. 삭제 성능을 확인하기 위해, 테스트 데이터를 집어넣고 삭제를 진행해보자. 테스트 코드가 상당히 길어서 대충 정리하면 Feed는 10개, Comment는 각 Feed당 100개, Reply는 각 Comment당 100개, ReplyLike는 각 Reply당 10개씩 있어서, ReplyLike가 총 100만개정도 ..
웹 백엔드 프로젝트를 진행하면, 많은 분들이 `Java`언어와 `Spring Boot` + `JPA` 혹은 `MyBatis` 조합을 사용해서 개발을 진행합니다. 저 역시 지금껏 Spring Boot를 활용해서 개발을 했었고, `JPA`와 `MyBatis` 모두 사용해 보았지만, 최근엔 `JPA`를 주로 사용하며 개발을 했습니다. `JPA`를 선택하면, 많은 편의성이 있지만, 가장 와닿는 점은 쿼리를 직접 작성하지 않아도 된다는 점이라고 생각합니다. 하지만 `JPA`가 직접 작성해 주는 쿼리는 저희의 생각과는 다르게 동작하는 경우도 존재합니다. 이 글은 `JPA`의 Delete 쿼리를 사용하면서 발견한 의아한 부분을 발견하고, 더 효율적인 방법을 찾아보려고 했던 내용에 대해서 다룹니다. 배경 최근 한 프로..
❓ 사전 배경 - 왜 이런 방법들이 생겼는가? 우리가 사용하는 웹 서비스에서 통신하는 프로토콜인 HTTP는 무상태성을 특징으로 갖는다. 즉, 내가 서버와 10번, 100번을 통신했더라도, 101번째 통신에서조차 서버는 나인지 모르고, 다시 내가 누구인지 밝혀야 하는 상황이라는 것이다. 이 상황은 이용자가 굉장히 불편하게 만든다. 내가 네이버로 메일을 보내려고 하는데, 메일함 누르는 순간, 메일 작성 버튼을 누르는 순간, 등등 매번 로그인을 하라고 한다면 귀찮지 않겠는가? (사실, 로그인을 했다고 해도, 로그인은 안 될 것이다) 이런 문제를 해결하기 위해, 다들 들어봤을 법한 쿠키, 세션, 토큰과 같은 방법으로 서버에게 사용자에 대한 정보를 지속적으로 준다. 사용자가 어떤 사용자인지, 사용자가 이 기능에 ..