Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
Tags
- 피보나치 예제
- katalon 사용법
- 톰캣 실시간 로그
- 해외증권 양도세 한국투자증권
- javascript 자동완성
- 홈택스 해외주식 양도세
- 최대공약수 예제
- 해외주식 양도세 신고
- Katalon Recorder 사용법
- 재귀 예제
- recursion example
- 국세청 해외주식 양도세 신고방식
- 피보나치함수
- 주식 양도세 신고방법
- katalon 비교
- git 연동
- bfs 미로탐색 java
- 재귀함수 예제
- java.sql.SQLSyntaxErrorException
- 테스트 자동화
- katalon 자동화
- 한국투자증권 해외주식 양도세
- js 자동완성
- katalon xpath
- tomcat log
- 피보나치함수 예제
- oracle group by
- katalon
- 한국투자증권 양도세 신고
- CSTS 폭포수 모델
Archives
- Today
- Total
엄지월드
[8차시] 최신 최적화 사례와 트렌드 탐구 : 성능 향상을 위한 지속적 개선 본문
스프링 부트 비동기 및 병렬 처리
- Spring Boot에서 비동기 처리 도입
- @EnableAsync 어노테이션으로 비동기 처리 활성화
- @Async 어노테이션으로 비동기 메서드 정의
- 기본적으로 Executor가 비동기 작업을 처리
- 반환 타입으로 Future, CompletableFutre 사용
- 비동기 처리의 성능 최적화
- ThreadPoolTaskExecutor를 사용해 비동기 스레드 풀 설정
- corePoolSize, maxPoolSize, queueCapacity 등의 파라미터 최적화
- 작업이 과도할 때 RejecctedExecutionHandler 설정
- 적절한 스레드 풀 사이즈를 통해 리소스 사용 최적화
@Bean
public Exeucutor() {
ThreadPoolTaskExcutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(500);
executor.setTHreadNamePrefix("Asyn-");
executor.initialize();
return executor;
}
- 비동기 작업 예외 처리
- AsyncUncaughtExeceptionHandler로 비동기 예외 처리
- CompletableFuture의 handle 메서드를 사용해 예외 처리
- 비동기 작업 실패 시 Fallback 메커니즘 구현
@Async
public CompletableFuture<String> asyncMethodWithException() {
if (new Random().nextInt(10) < 5) {
throw new RuntimeException("Error ocurred");
}
return CompletableFuture.completedFuture("Success");
}
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
System.out.println("Exception async method : " + ex.getMessage());
}
- Spring에서 병렬 처리 도입
- Parallel Streams를 사용해 데이터 스트림을 병렬 처리
- CompletableFuture를 사용해 병렬 작업 구현
- ForkJoinPool을 활용해 대규모 병렬 작업 관리
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.parallelStream().forEach(number -> {
System.out.println("Processing number:" + number);
});
- Fork/Join framework를 활용한 병렬 처리 최적화
- Fork/Join Framework로 작업을 여러 하위 작업으로 나누어 병렬 처리
- RecursiveTask 또는 RecursiveAction을 사용해 작업 분할
- 병렬 처리 후 결과를 병합하여 최종 처리
public class SumTask extends RecursiveTask<Integer> {
private final int[] array;
private final int start, end;
public SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
}
- 비동기 및 병렬 처리의 주의점
- 데드락 발생 방지 : 동기화된 자원 접근 관리
- 스레드 풀 과부하 방지 : 적절한 스레드 수 관리
- 상태 관리 주의 : 상태 변화가 많은 객체의 비동기 처리에서 동기화 고려
- 비동기 및 병렬 작업에서 오류 처리 및 타임아웃 설정
- 비동기 처리와 병렬 처리의 차이점
- 병렬 처리는 여러 작업을 동시에 실행하여 처리 속도를 높임
- 비동기 작업은 주로 I/O 작업에 적합, 병렬 작업은 CPU 집약적 작업에 적합
- 비동기 작업은 비동기 호출의 실행 흐름을 관리하는 것이 핵심,
병렬 처리는 리소스 사용을 최적화하는 것이 중요
- 실시간 시스템에서의 비동기 및 병렬 처리 활용
- 대규모 트래픽 처리 : 비동기 작업을 통해 처리량 증가
- 데이터 스트리밍 : 병렬 처리를 통해 대규모 데이터를 실시간으로 처리
- 실시간 알림 시스템에서 비동기 작업을 통한 빠른 응답
- 병렬 처리를 활용한 배치 처리 작업의 성능 최적화
스프링 부트 로그 관리 및 성능 최적화
- 로그 관리 도구와 외부 시스템 연동
- ELK Stack(Elasticsearch, Logstash, Kibana)을 사용한 로그 중앙화
- Graylog, Splunk와 같은 외부 시스템을 통한 로그 수집 및 분석
- 로그 데이터를 JSON 형식으로 저장하여 분석 용이
- Spring Boot에서 Logstash로 로그 전송
<appendern name="LOGSTASH"
class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>localhost:5000</destination>
</appender>
- 로그 샘플링 및 필터링
- 샘플링 : 빈번하게 발생하는 로그의 비율을 조정하여 성능 최적화
- 필터링 : 특정 조건을 만족하는 로그만 기록
- 중요하지 않은 로그 수준을 조정하여 성능 저하 방지
- Logback에서 로그 샘플링 설정
<appender name="ASYNC_FILE" class="ch.qos.logbak.classic.AsyncAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>return event.getLevel().toInt() == WARN</expression>
</evaluator>
<OnMatch>ACCEPT</OnMatch>
<OnMismatch>DENY</OnMismatch>
</filter>
</appender>
Virtual Threads 소개
- Project Loom 개요
- Virtual Thread는 매우 가벼운 스레드
- 동시성 처리의 성능과 복잡성을 단순화
- 기존의 OS 스레드 대비 훨씬 많은 수의 스레드를 효율적으로 처리
- Project Loom은 Java 21부터 공식적으로 도입됨
- 기존 스레드 모델의 한계
- OS 스레드는 고정된 자원을 사용하며, 수천 개 이상의 스레드를 생성하는 것이 비효율적
- Context Switching으로 인해 성능 저하 발생
- 블로킹 I/O에서 자원이 낭비되는 문제
- 비동기 코드 작성의 복잡성 증가
- Virtual Threads의 개념
- Virtual Threads는 JVM 레벨에서 생성되고 관리되는 경량 스레드
- 매우 작은 메모리 공간을 사용하며, 필요할 때만 CPU 리소스를 사용
- 기존 스레드 풀을 대체하여 동시성 처리가 더 쉬워짐
- 스레드 생성의 오버헤드가 거의 없음
- Virtual Threads의 사용법
- Thread.ofVirtual() 메서드를 통해 Virtual Thread 생성
- Virtual Threads를 사용한 간단한 예시
- Thread vt = Thread.ofVirtual().start(() ->
{ System.out.println("Virtual Thread 실행"); }); - Excutors.newVirtualThreadPerTaskExecutor()로 여러 작업 병렬 처리
- var executor = Excutors.newVirtualThreadPerTaskExecutor();
executor.submit(() > { // 작업 내용 }); executor.shutdown(); - 기존 스레드 API와 호환 가능
- Virtual Threads의 장점
- 메모리 효율성 : 수십만 개의 스레드를 생성해도 성능 저하가 거의 없음
- I/O 작업 최적화 : 블로킹 I/O에서도 리소스 낭비 없이 효율적
- 간단한 코드 : 기존 비동기 처리에 비해 코드 복잡성 감소
- 높은 동시성 처리 : 많은 요청을 병렬로 처리 가능
- Virtual Threads와 기존 동시성 모델 비교
- 기존 OS 스레드는 고정된 리소스 사용
- 비동기 코드를 작성할 때, 복잡한 콜백 및 Future 처리
- Virtual Threads는 더 많은 작업을 동시에 처리할 수 있음
- 비동기 작업과 동일한 성능을 제공하지만 코드가 더 단순
- Virtual Threads의 성능 비교
- 메모리 사용량 : OS 스레드보다 훨씬 적은 메모리 사용
- Context switching 비용 : Virtual Threads는 스케줄링 비용이 낮음
- 수천 개의 스레드에서 응답 시간이 더 빠름
- 실제 성능 테스트 결과 : Virtual Threads는 블로킹 I/O 작업에서도 효율적
- Virtual Threads 사용 시의 고려 사항
- 기존 스레드 풀 기반 동시성 처리와는 다른 패턴 요구
- Virtual Threads는 스레드 풀보다는 직접 실행에 가까운 방식으로 동작
- 기존 코드와의 호환성 유지 필요
- Virtual Threads는 블로킹 I/O 작업을 효율적으로 처리하지만,
비동기 작업이 항상 더 빠를 수는 없음 - Virtual Threads 사용 시 적절한 메모리 관리 및 설정 필요
- Virtual Threads와 병렬 처리
- Virtual Threads는 병렬 처리 작업에서 유용
- 각 작업을 별도의 Virtual Thread로 처리하여 동시성 극대화
- CPU 집약적인 작업에서도 높은 성능 제공
- 기존의 비동기 처리와 병렬 처리를 함께 사용하여 최적화된 성능 구현
- Virtual THreads의 실제 적용 사례
- 대규모 웹 어플리케이션에서 수십만 개의 동시 요청 처리
- 고성능 데이터 처리 시스템에서 대규모 병렬 작업 처리
- 기존 비동기 처리 모델을 단순화하여 복잡성 감소
- 대규모 I/O 작업이 많은 서비스에서 블로킹 I/O 작업 최소화
- Spring Boot에서 Virtual Threads 활성화
- Spring Boot 3.2와 Java 21에서 Virtual Threads 사용 가능
- application.properties 설정 예시 : spring.threads.virtual.enabled=true
- Virtual Threads는 기존의 스레드 풀을 대체하여 동시성 처리를 더 효율적으로 관리
- Virtual Threads 활성화를 통해 더 많은 요청을 동시에 처리 가능
@Bean
public AsyncTaskExcutor taskExecutor() {
return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor());
}
어플리케이션 성능 최적화
- WebP와 같은 최신 이미지 포맷 사용
- 이미지 크기 압축 : JPEG, PNG 파일 압축
- Lazy Loading : 스크롤 시점에 이미지를 로드
- Responsive Images : 화면 크기에 맞춘 이미지 제공
- 코드 압축과 최소화
- CSS와 JS 코드 압축(Minification)
- Whitespace 제거 및 변수명 축약
- Babel, UglifyJS 등의 도구를 사용한 코드 변환
- HTML 압축 및 인라인 스타일 최소화
- 파일 병합
- 여러 개의 CSS 파일을 하나로 병합
- JS 파일 병합으로 요청 수 줄이기
- HTTP/2 프로토콜을 사용하면 병합의 이점이 다소 감소하지만 여전히 유용함
- CSS 및 JS 모듈화를 위한 Bundling 도구 사용 (예 : Webpack)
- CDN 활용 - 웹 성능 최적화의 핵심 도구
- 전 세계 분산 서버를 통해 사용자에게 빠른 콘텐츠 제공
- 이미지, CSS, JavaScript와 같은 정적 파일을 캐싱
- Cloudflare, Akamai와 같은 CDN 제공 업체 사용
- 캐싱 정책 설정을 통해 더 빠른 응답 제공
- 브라우저 캐싱 설정
- Cache-Control 헤더 설정으로 브라우저 캐싱 활성화
- Expires 헤더로 캐싱 만료 시간 설정
- CSS, JS, 이미지와 같은 정적 파일 캐싱
- 자주 변경되지 않는 파일에 대해 장기 캐싱 적용
- 폰트 로딩 최적화
- font-display 속성 사용으로 폰트 로딩 제어
- woff2 포맷을 사용해 파일 크기 감소
- Fallback 폰트를 지정해 폰트 로딩 시 사용자 경험 개선
- Google Fonts와 같은 외부 폰트 캐싱 활용
- 비디오 및 미디어 최적화
- 비디오 스트리밍 서비스 사용(예 : 유투브)
- 비디오를 Lazy Load로 설정
- HTML5 비디오 태그를 사용한 적응형 스트리밍
- 적절한 미디어 포맷 선택(예 : MP4, WebM)
- 캐싱 전략을 통한 성능 개선
- 브라우저 캐싱을 통해 자주 요청되는 리소스 캐시
- Content Delivery Network (CDN) 캐싱 활용
- 서비스 워커를 사용해 오프라인 캐싱 및 빠른 로딩
- 캐시 무효화 전략 (TTL 설정, ETag 활용)
- Progressive Web App(PWA) 적용
- PWA의 오프라인 모드로 빠른 로딩 제공
- 서비스 워커를 통해 백그라운드에서 작업 처리
- 앱 캐싱과 프리로드를 사용하여 빠른 데이터 제공
- 푸시 알림을 통한 사용자 참여 증대 및 성능 향상
'기타' 카테고리의 다른 글
[7차시] 실제 성능 및 부하 테스트 실습 : 애플리케이션의 한계를 찾아서 (0) | 2025.03.23 |
---|---|
[6차시] 메모리 관리 및 GC 최적화 : 메모리 문제 예방과 안정적인 시스템 운영 (0) | 2025.03.23 |
[5차시] 데이터베이스 및 SQL 튜닝 : 데이터 처리 성능 극대화 (2) | 2025.03.18 |
[4차시] 캐싱 전략과 최적화 기법 : 속도와 자원을 동시에 잡는 방법 (0) | 2025.03.18 |
[3차시] 스프링 부트 내장 톰캣 최적화 및 NGINX 연계 : 효율적 요청 처리 환경 만들기 (0) | 2025.03.17 |
Comments