Spring
-
싱글 스레드에서 멀티스레드 성능 최적화: 스레드 풀과 큐의 역할Spring 2025. 8. 29. 13:49
이번 프로젝트에서 결제 승인 처리 기능을 구현하게 되었습니다.승인 처리는 매번 실시간으로 API를 호출하는 방식이 아니라, 스케줄러가 주기적으로 배치로 실행되며 특정 조건을 만족한 카드들을 모아서 승인 처리를 진행합니다.승인 로직은 외부 결제망(예: Cybersource)과 직접 연동되기 때문에 네트워크 지연이나 타임아웃이 빈번하게 발생할 수 있습니다.초기에는 단순히 new Thread(...)를 통해 워커 스레드를 직접 띄워 처리했는데, 이 방식에는 다음과 같은 한계가 있었습니다.매 요청 마다 스레드를 생성 및 종료하는 작업은OS의 Kernel 레벨에서 이루어지기 때문에 성능에 매우 좋지 않음스레드를 만드는 과정은 단순한 객체 생성(new)과 달리, 커널에 진입해 스택 메모리 확보, TCB(Thread..
-
캐싱 최적화: Redis를 사용하지 않고 Local Cache로 캐싱하는 방법Spring 2025. 8. 25. 17:29
문제 배경현재 진행 중인 프로젝트는 카드, 파일, 암호화 키, 공급자 정보, 카드 상품 등 다양한 프로파일 데이터를 빈번하게 조회해야 합니다.기존 방식은 DAO를 통해 매번 DB에 접근하는 구조였는데, 이로 인해 다음과 같은 문제가 있었습니다.동일한 데이터라도 매번 DB I/O 발생대량 프로파일 조회 시 DB 부하 증가운영 환경에서 빠른 응답 속도 보장 어려움이를 해결하기 위해 데이터를 미리 캐싱하는 방법을 도입하기로 결정했습니다. 해결 전략1. Local Cache (In-Memory)Spring Service 내부에 Map 또는 CaffeineCacheManager와 같은 In-Memory 캐시를 두고, 애플리케이션 시작 시 필요한 데이터를 메모리에 로드하여 사용하는 방식입니다.장점O(1) 조회 속도..
-
성능 개선: 대량 데이터 Batch Insert 최적화와 MyBatis 캐시 문제 해결Spring 2025. 8. 24. 23:19
이번 프로젝트에서 기존 구현되어 있는 코드 성능을 개선하는 작업을 진행했습니다. 카드 발급은 단건부터 수십만 건까지 대량 데이터를 처리될 수 있습니다. 그러나 기존 방식은 데이터를 한 건씩 DB에 저장하는 구조라 10만 건 발급 시 843초가 걸릴 정도로 성능이 떨어지고, 모든 데이터를 한 번에 메모리에 적재하면 OOM(Out Of Memory) 예외까지 발생할 수 있었습니다. 이를 해결하기 위해 데이터를 1,000건 단위로 분할하여 MyBatis와 JDBC Batch를 활용한 배치 처리 방식을 적용했고, 각 배치 처리 후 캐시를 초기화하여 메모리 안정성을 확보했습니다. 그 결과, 10만 건 처리 시간이 약 843초에서 5초로 단축되며 약 99.4%의 성능 개선 효과를 얻었고, 기존 방식과 비교했을 때..
-
Enum find 메서드 최적화: 10배 빠르게 만드는 HashMap 활용법Spring 2025. 8. 12. 21:33
Enum에서 특정 문자열을 기준으로 해당하는 Enum 값을 찾는 메서드를 자주 사용합니다. 예를 들어, find 또는findByValue와 같은 메서드를 통해 문자열 값과 Enum 값을 매칭합니다. Stream API를 사용하여 Enum 값을 찾는 방식은 간단하고 직관적이지만, 반복적으로 호출될 경우 성능 상의 문제가 발생할 수 있습니다. 이에 Jay 님이 작성한 Enum 최적화 방법을 참고하여, HashMap을 사용하여 값을 캐싱하고 빠르게 찾는 방법을 기록하고자 합니다Enum에서 특정 값(예: 문자열)을 기준으로 Enum 인스턴스를 찾는 방법 3가지 예시를 보여드리겠습니다. 각각의 방법은 Stream과 HashMap을 활용한 구현으로 구성됩니다. 1. Arrays.stream() 사용@Require..
-
Transaction: ACID, 격리 수준, 락, 전파 옵션Spring 2025. 8. 12. 20:41
트랜잭션 ACID원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나 실패해야 된다.일관성(Consistency): 트랜잭션 이전과 이후에는 항상 consistent 상태여야 한다.격리성(Isolation): 동시에 실행되는 트랜잭션들이 다른 트랜잭션에 영향을 주어서는 안된다.지속성(Durability): 트랜잭션이 성공적으로 끝내면 그 결과가 항상 기록되어야 한다.트랜잭션 격리수준트랜잭션의 격리 수준(Isolation Level)이란 여러 트랜잭션이 동시에 실행될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 여부를 결정하는 것상호작용Dirty Read: 아직 커밋되지 않은 다른 트랜잭션의 데이터를 읽는 것을 의미Non-repeatable..
-
Jackson JSON ↔ DTO 직렬화·역직렬화Spring 2025. 8. 12. 19:02
Jackson이 JSON 데이터를 DTO로 변환하는 규칙은 객체 생성 방법에 따라 달라집니다.1. 전체 생성자 (생성자가 하나만 있을 경우)생성자가 하나뿐이면, @JsonCreator 없이 자동으로 그 생성자를 사용합니다.public class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; }} 2. 전체 생성자 (생성자가 여러 개 있을 경우)생성자가 여러 개면 Jackson이 어느 생성자를 써야 할지 모르므로 @JsonCreator로 지정합니다.파라미터 매핑은 @JsonProperty("필드명")으로..
-
Spring Bean XML 설정 방법Spring 2025. 8. 12. 18:52
XML 기본 포맷은 아래와 같다. beans 태그 안에 스프링 빈 설정을 작성한다. xmlns:context="" : 빈 등록은 XML, 빈 설정은 자바 애노테이션으로 할 경우 이 포맷을 사용 : 빈 설정을 XML 파일이 아닌 빈 클래스의 애노테이션으로 설정하고자 할 때 사용빈 설정 태그를 이용해 빈을 정의id: 빈 이름 지정class: 빈 타입 설정scope: 빈의 scope 설정 (singleton/prototype)primary: true를 지정하여 빈을 사용할 때 객체가 생성되도록 설정init-method: 빈 객체가 생성될 때 호출할 메서드 설정destroy-method: 빈 객체가 소멸될 때 호출할 메서드 설정자동 주입 설정 - autowire 설정클래스의 참조 타입 필드에 한해서 aut..
-
ApplicationContext와 ApplicationContextAware 이해하기Spring 2025. 8. 12. 18:44
ApplicationContext는 애플리케이션의 컴포넌트를 관리하고 제어하는데 핵심적인 역할을 한다.ApplicationContext는 Spring 컨테이너의 인스턴스로, 애플리케이션의 빈 객체들을 생성, 관리, 제어하는 역할을 한다.빈(Bean)은 Spring에서 관리되는 객체로, IoC 컨테이너에 의해 생성되고 의존성 주입을 받을 수 있다.ApplicationContext는 XML, Java 설정 클래스, 애노테이션 등을 통해 빈의 정의와 의존성을 설정할 수 있다.ApplicationContext 역할빈 객체의 생성과 소멸을 담당하며, 객체의 생명 주기를 제어할 수 있다. 객체의 초기화와 종료를 관리하여 애플리케이션의 안정성과 효율성을 증진시킨다.빈 객체 간의 의존성을 주입하여 객체 간의 결합도를 ..