분류 전체보기

경쟁상태와 동기화 매커니즘 에서 경쟁상태를 해결하기 위한 Block & WakeUp 잠금 방식에 대해 알아보았다. 해당 방식은 대기하는 스레드가 Lock을 획득하기 전까지 블로킹된다. 만약 어떤 문제 때문에 원하는 Lock을 획득하지 못하고 무한히 대기하게 된다면 어떻게 될까? 어느 상황에서 이러한 문제가 발생할 수 있으며 어떻게 해결할 수 있는지 살펴보자.   OS에서의 데드락 개념데드락이란 두 개 이상의 프로세스(스레드)가 서로가 가진 자원을 기다리며 무한히 대기하는 상황을 일컫는다. 아래 그림과 같은 상황이다.(여기서 자원이란 파일, 프린터, CPU, Lock 등 프로세스가 사용가능한 모든 것)  A 프로세스와 B 프로세스 각각 a,b 자원을 소유 후 상대가 가지고 있는 자원을 요청한다. 두 자원은..
멀티 스레드, 멀티 프로세스, 스케일 아웃한 서버들 등 동시성의 활용은 성능을 향상시키고 자원을 효율적으로 사용하는 데 필수적이다. 그러나 동시성은 몇 문제를 동반하는데 시스템의 예측 가능성, 안정성을 저해하기에 이를 해결하기 위한 방법들을 잘 알고 활용하는 것이 중요하다. 이번 포스트에서 경쟁상태부터 동기화 매커니즘을 살펴보며 실제 어플리케이션에서는 어떻게 활용되는지 정리해 보았다. 문제의 시작인 경쟁상태부터 살펴보자.   경쟁상태경쟁상태(Race Condition)는 스레드나 프로세스가 공유 자원에 동시에 접근하며 발생하는 문제이다. 공유 자원을 사용하며 다수가 동시에 접근할 수 있는 영역을 임계 영역(Critical Section)이라고 부르며, 이 임계 영역에 접근하는 순서에 따라 결과가 달라질 ..
인덱스는 조회 쿼리의 성능에 큰 영향을 미친다. 데이터의 양이 많을수록 더 극적인 효과를 볼 수 있다. 이번 포스트에서는 '개발 한 스푼' 프로젝트 중 커버링 인덱스를 적용하여 쿼리 성능을 향상시킨 경험을 공유한다.   상황'개발 한 스푼'의 유저는 매일 본인이 선택한 CS 카테고리에 속한 질문들 중 하나를 랜덤하게 발급받는다. 해당 로직은 다음과 같은 수순으로 진행된다. 유저가 선택한 카테고리 가져오기해당 카테고리에 속하는 모든 질문 가져오기유저가 현재까지 발급받은 질문 가져오기2번에서 3번을 뺀 질문들 중 랜덤하게 하나를 선택 발급 여기서 3번 유저가 발급받은 질문들은 `question_open` 이라는 테이블에 저장되어 있다. 해당 테이블에는 5만개 이상의 레코드가 저장되어있기 때문에 데이터를 효율..
필자가 개발하고 있는 '개발 한 스푼' 서비스에서는 Github Actions를 활용해 몇 가지 간단한 자동화를 구축해놓았다. 새 버전의 서버를 준비하는 것에서부터 배포 히스토리를 관리하는데까지 드는 공수를 줄이고 휴먼에러를 방지하기 위해 활용되고 있다. 이번 포스트에서는 브랜치 전략에 맞춰 자동화 시스템을 구축한 경험을 공유해보고자 한다.   소개 : 개발 한 스푼 브랜치 전략개발 한 스푼은 소규모(1~2명)로 운영하고 있다. Git flow와 같은 다수의 개발자가 협업하는 상황에서 필요할 정도의 전략은 현재 상황에서 무게감만 느껴진다고 생각했다. 특히 작업을 병렬로 진행할 가능성이 매우 낮다고 생각하고 상당 부분을 간소화한 브랜치 전략을 사용하였다.  모든 브랜치의 시작점이자 끝점으로 Develop..
· Spring
필자가 운영중인 '개발 한 스푼'에서는 특정 시간에 모든 유저를 대상으로 푸시알림을 보내고 있다. 많은 양은 아니지만 알림처리를 위해 Spring Batch를 사용하고 있다. 하지만 특정 시간대에 몇 번, 몇 분 실행되는 Spring Batch를 위해 컴퓨팅 파워를 추가로 사용하는건 비용 낭비다. 이번 포스트에서는 AWS Lambda를 활용하여 제로 코스트로 Spring Batch를 운용한 경험을 공유한다.   Batch 실행과 문제배치 작업을 실행시키는 방법으로는배치 어플리케이션이 실행되어 있는 상태로 존재하다가 이벤트를 받았을 때 작업을 실행하거나특정 때에 어플리케이션을 실행시켜 작업을 진행한 뒤 어플리케이션이 종료되는 형태일 수도 있다. 필자의 푸시알림 배치작업은 후자와 같다. 문제는 배치 작업이 ..
원활한 서비스 제공을 위해서 서버가 다운되는 상황을 최소화해야한다. 시스템 오류나 트래픽 과부하로 서버가 다운될 수 있지만 새로운 버전의 서버를 배포할 때도 서버가 잠시간 다운될 수 있다. 이런 경우 기존 서버를 내리고 새로운 서버가 재가동 될 때까지의 시간이 다운타임이 된다. 서비스를 운영중이라면 이러한 상황은 배포 때마다 서비스를 이용할 수 없기 때문에 치명적이다. 때문에 다운타임 없이 서버 배포가 가능한 무중단 배포 방식이 거의 필수적이라고 볼 수 있다. 이번 포스트에서는 필자가 '개발 한 스푼' 서비스에 무중단 배포를 적용한 방법을 공유한다.   무중단 배포 매커니즘먼저, 무중단 배포가 어떻게 동작하는지 알아보자. 무중단 배포는 배포 도중에도 서비스 제공이 끊기지 않아야 한다. 새로운 서버가 배포..
· Spring
Spring에서는 이벤트 기반 프로그래밍을 지원한다. EventPublisher를 이용해 이벤트를 발행하고 구독하고 있는 객체에서 이벤트를 처리한다. 덕분에 비즈니스 로직과 직접적으로 관련없는 로직들을 이벤트를 통해 처리할 수 있다. 객체간 낮은 결합도를 유지한 상태로 부가적인 로직을 처리할 수 있다는게 매력적이다. '개발 한 스푼' 서비스에서는 질문 답변이나 게시글을 작성할 때마다 활동 테이블에 카운트를 증가시키고 활동점수에 따라 뱃지 등을 취득할 수 있다. 답변이나 게시글 작성 후 활동점수 집계는 문맥이 다르기 때문에 이들은 이벤트를 발행해 처리하고자 했다. 하지만 이벤트를 발행하는 로직 또한 비즈니스 로직 내에 포함된다. 때문에 한 단계 더 나아가 이벤트 발행 로직을 AOP로 분리하여 처리해보았다...
· Spring
동시성 이슈를 예방하고 데이터 일관성을 유지하기 위해서 Lock을 이용한다. 그 중 분산락은 레코드 수준의 잠금보다는 군집 단위에 영향을 미치는 조작, 여러 DB에 걸친 수정 등 복잡한 레벨에서의 일관성을 보장하고자 할 때 활용도가 높다. '개발 한 스푼' 서비스에서도 질문 발급 시 분산락을 적용해야할 상황이 생겼다.(실제 서비스에서 문제가 이미 발생했고 후 처리...) 이번 글에서는 분산락을 도입하게 된 배경과 이를 유연하게 적용하기 위해 구현한 방법을 공유해본다. 이 포스트의 마무리에서는 다음과 같은 방식으로 원하는 부분에 쉽게 분산락을 적용할 수 있다. // 분산락 획득 후 트랜잭션 실행. 분산락 Key는 request에 존재@Transactional@DistributedLock(keyClass =..
· Spring
비즈니스 로직 실행 중 올바르지 않은 결과인 경우 예외를 발생시킨다. 클라이언트로의 응답에는 예외 케이스별로 각기 다른 메시지를 건내주어야한다. 때문에 예외별 필요한 정보들을 따로 정리하여 관리하기도 한다. '개발 한 스푼' 서비스도 Enum을 활용하여 예외별 정보를 모아 관리한다. 하지만 예외 케이스가 많아질수록 예외 정보를 가지는 Enum이 비대해지고 가독성 문제가 생길 수 있기 때문에 프로젝트에 맞게 조금 변형하여 활용해보았다. 이번 글에서는 예외 정보를 확장성 및 가독성 좋게(필자 프로젝트만의 특성일 수도 있지만) 관리하기 위해 적용한 방식을 공유해본다.본 포스트는 다음의 순서로 진행됩니다.1. 단일 Enum으로 예외관리 시 문제점2. 개선하기    2.1 Enum을인터페이스로 확장성 좋게 개선하..
· Spring
Spring Security는 애플리케이션의 인증/인가 관리를 쉽게 처리할 수 있도록 도와준다. 제공하는 기능 중에는 특정 API에 인증없이 요청을 처리할 수 있도록 허용하는 기능(permitAll)도 있다. 필자가 운영하는 '개발 한 스푼' 서비스에서도 Spring Security를 통해 인증을 관리하고 있다. 마찬가지로 인증이 필요없는 API들에는 permitAll을 이용해 인증을 열어주었다. 하지만 API별로 인증을 해제하는 기능은 핸들러 메서드에서 제어하는 것이 아닌 Security 설정 코드에서만 제어할 수 있다. 이는 인증 해제가 필요한 API가 늘어날수록 여러 문제를 초래한다. 이번 글에서는 API별 인증 해제를 효율적으로 처리하기 위해 적용한 방법을 공유해본다.본 포스트는 다음과 같은 순서..