[Async-3][Optimization] 실무 적용 (⭐)
·
Java/Core
1. 들어가며 백엔드 시스템의 성능을 최적화할 때 비동기 처리는 가장 강력한 도구 중 하나이다. 이번 글에서는 영화 도메인을 사례로 들어, 실제 서비스에서 발생할 수 있는 동기 방식의 한계를 살펴보고 이를 비동기 및 병렬 처리로 개선하는 구체적인 과정을 다룬다.2. 영화 도메인 설명과 동기 방식의 한계2.1. 도메인 모델링: 영화 및 관련 서비스이번 장에서는 영화 정보를 관리하는 시스템을 가정한다. 기본적인 영화 엔티티는 다음과 같이 정의된다.@Getter@Table(name = "ch5_movie")@NoArgsConstructor@Entitypublic class Movie { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) priv..
[Async-2][Optimization] CompletableFuture와 효율적인 스레드 풀 관리
·
Java/Core
1. 비동기 프로그래밍의 핵심 도구: CompletableFuture 앞서 비동기 처리의 기초 개념을 살펴보며 CompletableFuture를 활용해 작업을 비동기로 실행하고, 완료 후 후속 작업을 등록하며, 필요한 시점에 결과를 기다리는 과정을 경험하였다. 우리가 사용했던 주요 메서드들을 다시 정리하면 다음과 같다.runAsync(): 반환값 없이 비동기 작업을 수행한다.supplyAsync(): 반환값을 가지는 비동기 작업을 수행한다.thenRun(): 비동기 작업 수행을 마치면 다음에 수행할 작업을 정의한다.join(): 비동기 작업이 완료될 때까지 호출 스레드를 블로킹하며 기다린다. CompletableFuture는 Java 8에서 도입된 클래스로, 복잡한 비동기 작업을 선언적으로 구성할 수 있..
[Async-1][Optimization] 동기 vs 비동기, 블로킹 vs 논블로킹
·
Java/Core
1. 들어가며: 두 축의 명확한 구분백엔드 개발에서 성능 최적화의 핵심은 자원의 효율적 관리에 있다. 이를 이해하기 위해 반드시 정복해야 하는 두 가지 개념 축이 있는데, 이들은 종종 혼동되지만 본질적으로 완전히 다른 관점을 다룬다.1.1. 두 개념의 본질적 차이동기(Synchronous) vs 비동기(Asynchronous): "결과 처리의 책임 주체"에 대한 관점동기: "내가 결과를 기다리며 확인한다"비동기: "다른 사람(시스템)이 끝나면 나를 알려준다"블로킹(Blocking) vs 논블로킹(Non-blocking): "나의 실행 흐름 제어권"에 대한 관점블로킹: "나는 여기서 멈춰야 한다"논블로킹: "나는 계속 다른 일을 할 수 있다"이 두 축은 독립적이지만, 실제 시스템에서는 네 가지 조합으로 나..
[Stream-4][Optimization] 실무 적용과 성과 증명 전략
·
Java/Core
1. 들어가며 지금까지 Java Stream 필터 체이닝에서 선택도와 비용, 그리고 이를 결합한 Filter Overhead 개념이 성능에 미치는 영향을 고찰하였다. 그렇다면 실제 진행 중인 프로젝트에서 성능 저하를 유발하는 비효율적인 필터 순서를 어떻게 발견하고, 이를 어떻게 가시적인 성과로 연결하여 기술적 역량을 증명할 수 있을지 그 구체적인 방법론을 살펴본다.2. 현실적인 문제 발견 단계 이론적으로 가장 완벽한 최적화 프로세스는 프로젝트 내의 모든 filter() 로직을 전수 조사하고, 각 필터의 비용과 선택도를 정밀하게 측정하여 `Filter Overhead = 비용 x 선택도` 수치를 산출한 뒤 이를 오름차순으로 재배치하는 것이다. 그러나 이러한 이상적인 접근법은 현실적으로 다음과 같은 제약이 ..
[Stream-3][Optimization] Filter Overhead를 활용한 성능 개선 사례
·
Java/Core
1. 들어가며 지난 장에서는 Java Stream API의 성능을 결정짓는 핵심 지표인 선택도(Selectivity)와 비용(Cost), 그리고 이를 정량화한 Filter Overhead의 개념에 대해 학습하였다. 이번 장에서는 이러한 이론이 실제 서비스 코드에 어떠한 영향을 미치는지 구체적인 도메인 모델과 시뮬레이션을 통해 검증해 보고자 한다.2. 문제 제기: 비효율적인 필터 순서의 위험성 백엔드 시스템을 개발하다 보면 컬렉션 데이터를 다양한 조건으로 필터링해야 하는 상황을 자주 마주한다. 이때 사용되는 각 필터는 저마다 고유한 비용 특성을 지닌다.저비용 필터: 유저 테이블의 컬럼 값을 기준으로 성인 여부를 판단하는 인메모리 비교 연산 (약 20ns).고비용 필터: 외부 API를 호출하여 유저의 결제 ..
[Stream-2][Optimization] 선택도(Selectivity)와 비용(Cost)의 이해
·
Java/Core
1. 들어가며 Java Stream API의 선언적 처리 방식과 지연 평가(Lazy Evaluation)는 코드의 가독성과 유지보수성을 높여준다. 그러나 복잡한 필터 체이닝을 구성할 때 내부 동작 원리를 고려하지 않으면 예상치 못한 성능 저하를 초래할 수 있다. 본 글에서는 Stream 필터의 효율을 결정짓는 두 가지 핵심 개념인 선택도와 비용을 분석하고, 이를 통해 최적의 필터 배치 전략을 도출해 보겠다.2. 필터 체이닝의 실생활 비유: 기업의 채용 단계 Stream 필터 체이닝의 성능 이슈를 이해하기 위해 기업의 채용 과정을 예로 들어보겠다. 100명의 지원자 중 단 1명의 최종 합격자를 선발해야 하는 상황에서 채용 담당자는 다음과 같은 단계를 구성한다.서류 검토: 학력 및 경력 기준을 통해 50명을..
[Stream-1][Optimization] 선언적 프로그래밍과 지연 평가(Lazy Evaluation)
·
Java/Core
1. 들어가며 소프트웨어를 설계하고 코드를 작성할 때, 개발자는 단순히 기능의 구현을 넘어 "무엇을 할 것인가(What)"와 "어떻게 할 것인가(How)" 사이에서 끊임없이 결정해야 한다. 이 결정의 중심에는 프로그래밍의 두 가지 거대한 패러다임인 명령형(Imperative)과 선언형(Declarative) 방식이 존재한다.2. 명령형 방식 vs 선언형 방식두 방식의 차이를 이해하기 위해 특정 장소로 길을 찾아가는 과정을 비유로 들어보겠다.2.1. 명령형 방식: 직접 경로를 계획하여 이동하기명령형 방식은 목적지에 도달하기 위한 모든 세부 단계를 직접 계획하고 제어한다. 직접 이동하는 상황이라면 다음과 같이 단계별 계획이 필요하다.현재 위치에서 동쪽으로 100m 이동한다.신호등이 있으면 초록불이 될 때까지..
[Basic-2] 제네릭과 제네릭 메서드
·
Java/Core
1. 배경지식사실 제네릭 자체는 자바 문법이기 때문에 파트에 정리하는게 맞지만 Spring 코드를 작성하면서 제네릭 메서드에 대한 내용이 자주 등장하기 때문에 본 글에서 정리하고자 한다. 본인도 제네릭에 대해 어느정도의 내용을 숙지하고 사용하고 있지만 이번 기회에 제대로 정리를 하려고 한다. 2. 제네릭(Generic)이란?제네릭은 클래스나 메서드에서 사용할 데이터 타입을 미리 정하지 않고, 실제 사용할 때 지정할 수 있게 하는 기능이다. 이는 마치 내용물이 정해지지 않은 컵과 같다. 이 컵에는 주스, 물, 커피 등 어떤 액체든 담을 수 있다. 컵 자체는 '담는다'는 본질적인 기능만 수행하며, 내용물(타입)은 컵을 사용하는 시점에 결정된다.제네릭을 사용하면 다음과 같은 장점을 얻을 수 있다.타입 안정성..