Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
spring-retry-toolkit — CVE-2026-41710을 위한 틈새 툴킷을 포함한 spring retry 1.3.x 수정 | Kitploit
도구/GitHubGitHub/nichetoolkit/spring-retry-toolkit
Vulnerability AnalysisWeb SecuritySupply Chain Security
GitHubnichetoolkit/spring-retry-toolkit

spring-retry-toolkit

CVE-2026-41710을 위한 틈새 툴킷을 포함한 spring retry 1.3.x 수정

저장소 보기
212개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Javadocs

이 프로젝트는 Spring 애플리케이션을 위한 선언적 재시도 지원을 제공합니다. 이는 Spring Batch, Spring Integration 등에서 사용됩니다. 명시적 사용을 위한 명령형 재시도도 지원됩니다.

버전

이 버전은 java8 및 spring4 또는 spring5를 위한 spring-retry 2.0.13 버전을 수정한 것입니다. 자세한 내용은 공식 Spring 2.0.13 버전을 참조하십시오.

빠른 시작

이 섹션에서는 Spring Retry를 시작하는 방법을 간단히 소개합니다. 선언적 예제와 명령형 예제를 포함합니다.

선언적 예제

다음 예제는 선언적 스타일로 Spring Retry를 사용하는 방법을 보여줍니다:

@Configuration
@EnableRetry
public class Application {

    @Bean
    public Service service() {
        return new Service();
    }

}

@Service
class Service {
    @Retryable(RemoteAccessException.class)
    public void service() {
        // ... do something
    }
    @Recover
    public void recover(RemoteAccessException e) {
       // ... panic
    }
}

이 예제는 service 메서드를 호출하고, RemoteAccessException으로 실패하면 재시도하며(기본적으로 최대 세 번), 그래도 실패하면 recover 메서드를 시도합니다. @Retryable 애노테이션 속성에는 예외 유형을 포함하거나 제외하고, 재시도 횟수를 제한하며, 백오프 정책을 설정하기 위한 다양한 옵션이 있습니다.

앞서 보여준 @Retryable 애노테이션을 사용하여 재시도 처리를 적용하는 선언적 접근 방식은 AOP 클래스에 대한 추가 런타임 의존성을 가집니다. 프로젝트에서 이 의존성을 해결하는 방법에 대한 자세한 내용은 'Java Configuration for Retry Proxies' 섹션을 참조하십시오.

명령형 예제

다음 예제는 명령형 스타일(버전 1.3부터 사용 가능)로 Spring Retry를 사용하는 방법을 보여줍니다:

RetryTemplate template = RetryTemplate.builder()
				.maxAttempts(3)
				.fixedBackoff(1000)
				.retryOn(RemoteAccessException.class)
				.build();

template.execute(ctx -> {
    // ... do something
});

1.3 이전 버전의 경우 RetryTemplate 섹션의 예제를 참조하십시오.

빌드

Spring Retry는 Java 1.7 및 Maven 3.0.5(이상)가 필요합니다. 빌드하려면 다음 Maven 명령을 실행하십시오:

$ mvn install

기능 및 API

이 섹션에서는 Spring Retry의 기능을 설명하고 API 사용 방법을 보여줍니다.

RetryTemplate 사용하기

처리를 더 견고하고 실패 가능성이 낮게 만들기 위해, 실패한 작업이 후속 시도에서 성공할 가능성이 있는 경우 자동으로 재시도하는 것이 도움이 될 때가 있습니다. 이러한 종류의 처리가 가능한 오류는 본질적으로 일시적입니다. 예를 들어, 네트워크 장애로 인해 실패하는 웹 서비스나 RMI 서비스에 대한 원격 호출, 또는 데이터베이스 업데이트에서의 DeadLockLoserException은 짧은 대기 후에 스스로 해결될 수 있습니다. 이러한 작업의 재시도를 자동화하기 위해 Spring Retry는 RetryOperations 전략을 제공합니다. RetryOperations 인터페이스 정의는 다음과 같습니다:

public interface RetryOperations {

    <T> T execute(RetryCallback<T> retryCallback) throws Exception;

    <T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback)
        throws Exception;

    <T> T execute(RetryCallback<T> retryCallback, RetryState retryState)
        throws Exception, ExhaustedRetryException;

    <T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,
        RetryState retryState) throws Exception;

}

재시도할 비즈니스 로직을 삽입할 수 있게 해주는 간단한 인터페이스가 기본 콜백입니다:

public interface RetryCallback<T> {

    T doWithRetry(RetryContext context) throws Throwable;

}

콜백이 시도되고, 실패하면(Exception을 던져서) 성공하거나 구현이 중단을 결정할 때까지 재시도됩니다. RetryOperations 인터페이스에는 여러 가지 오버로드된 execute 메서드가 있어, 모든 재시도 시도가 소진되었을 때의 복구에 대한 다양한 사용 사례를 처리하고, 클라이언트와 구현이 호출 간에 정보를 저장할 수 있게 해주는 재시도 상태를 처리합니다(이에 대해서는 나중에 더 다룹니다).

RetryOperations의 가장 단순한 범용 구현은 RetryTemplate입니다. 다음 예제는 이를 사용하는 방법을 보여줍니다:

RetryTemplate template = new RetryTemplate();

TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);

template.setRetryPolicy(policy);

Foo result = template.execute(new RetryCallback<Foo>() {

    public Foo doWithRetry(RetryContext context) {
        // Do stuff that might fail, e.g. webservice operation
        return result;
    }

});

앞선 예제에서는 웹 서비스 호출을 실행하고 그 결과를 사용자에게 반환합니다. 해당 호출이 실패하면 타임아웃에 도달할 때까지 재시도됩니다.

버전 1.3부터는 다음과 같이 RetryTemplate의 fluent 구성도 사용할 수 있습니다:

RetryTemplate.builder()
      .maxAttempts(10)
      .exponentialBackoff(100, 2, 10000)
      .retryOn(IOException.class)
      .traversingCauses()
      .build();

RetryTemplate.builder()
      .fixedBackoff(10)
      .withinMillis(3000)
      .build();

RetryTemplate.builder()
      .infiniteRetry()
      .retryOn(IOException.class)
      .uniformRandomBackoff(1000, 3000)
      .build();

RetryContext 사용하기

RetryCallback의 메서드 매개변수는 RetryContext입니다. 많은 콜백이 이 컨텍스트를 무시합니다. 그러나 필요한 경우, 반복이 지속되는 동안 데이터를 저장하기 위한 속성 가방(attribute bag)으로 사용할 수 있습니다.

RetryContext는 동일한 스레드에서 중첩된 재시도가 진행 중인 경우 부모 컨텍스트를 가집니다. 부모 컨텍스트는 execute 호출 간에 공유해야 하는 데이터를 저장할 때 종종 유용합니다.

RecoveryCallback 사용하기

재시도가 소진되면, RetryOperations는 제어를 다른 콜백인 RecoveryCallback으로 넘길 수 있습니다. 이 기능을 사용하려면, 클라이언트는 다음 예제에서 보듯이 콜백들을 함께 동일한 메서드에 전달할 수 있습니다:

Foo foo = template.execute(new RetryCallback<Foo>() {
    public Foo doWithRetry(RetryContext context) {
        // business logic here
    },
  new RecoveryCallback<Foo>() {
    Foo recover(RetryContext context) throws Exception {
          // recover logic here
    }
});

비즈니스 로직이 템플릿이 중단을 결정하기 전에 성공하지 못하면, 클라이언트는 복구 콜백을 통해 대체 처리를 수행할 기회를 얻습니다.

무상태 재시도

가장 단순한 경우, 재시도는 단순한 while 루프입니다. RetryTemplate은 성공하거나 실패할 때까지 계속 시도할 수 있습니다. RetryContext에는 재시도할지 중단할지 결정하기 위한 일부 상태가 포함되어 있습니다. 그러나 이 상태는 스택에 있으며, 어디에도 전역적으로 저장할 필요가 없습니다. 따라서 이를 "무상태 재시도"라고 부릅니다. 무상태 재시도와 상태 저장 재시도 간의 구분은 RetryPolicy의 구현에 포함되어 있습니다 (RetryTemplate은 둘 다 처리할 수 있음). 무상태 재시도에서는 콜백이 재시도 시 실패했을 때와 동일한 스레드에서 항상 실행됩니다.

상태 저장 재시도

실패로 인해 트랜잭션 리소스가 무효화된 경우에는 몇 가지 특별한 고려 사항이 있습니다. 이는 단순한 원격 호출에는 적용되지 않습니다. 왜냐하면 (보통) 트랜잭션 리소스가 없기 때문이지만, 데이터베이스 업데이트에는 때때로 적용되며, 특히 Hibernate를 사용할 때 그렇습니다. 이 경우, 트랜잭션이 롤백되고 새로운 (그리고 유효한) 트랜잭션을 시작할 수 있도록 실패를 호출한 예외를 즉시 다시 던지는 것만이 의미가 있습니다.

이러한 경우에는 무상태 재시도로는 충분하지 않습니다. 왜냐하면 다시 던지기와 롤백은 필연적으로 RetryOperations.execute() 메서드를 벗어나야 하며 스택에 있던 컨텍스트를 잃을 가능성이 있기 때문입니다. 컨텍스트를 잃지 않으려면 스택에서 꺼내어 (최소한) 힙 저장소에 넣기 위한 저장 전략을 도입해야 합니다. 이를 위해 Spring Retry는 RetryContextCache라는 저장 전략을 제공하며, 이를 RetryTemplate에 주입할 수 있습니다. RetryContextCache의 기본 구현은 간단한 Map을 사용하는 인메모리 방식입니다. 메모리 누수를 방지하기 위해 엄격하게 강제되는 최대 용량이 있지만, 고급 캐시 기능(예: TTL)은 없습니다. 이러한 기능이 필요하다면 해당 기능을 갖춘 Map을 주입하는 것을 고려해야 합니다. 클러스터 환경에서 여러 프로세스를 사용하는 고급 사용 사례의 경우, 일종의 클러스터 캐시로 RetryContextCache를 구현하는 것도 고려할 수 있습니다 (다만 클러스터 환경에서도 이것은 과할 수 있습니다).

RetryOperations의 책임 중 일부는 실패한 작업이 새로운 실행에서 (그리고 보통 새로운 트랜잭션으로 감싸져서) 돌아올 때 이를 인식하는 것입니다. 이를 용이하게 하기 위해 Spring Retry는 RetryState 추상화를 제공합니다. 이는 RetryOperations의 특별한 execute 메서드와 함께 작동합니다.

실패한 작업은 재시도의 여러 호출에 걸쳐 상태를 식별함으로써 인식됩니다. 상태를 식별하기 위해 항목을 식별하는 고유 키를 반환하는 역할을 하는 RetryState 객체를 제공할 수 있습니다. 이 식별자는 RetryContextCache의 키로 사용됩니다.

경고: RetryState가 반환하는 키에서 Object.equals()와 Object.hashCode()의 구현에 매우 주의하십시오. 가장 좋은 방법은 비즈니스 키를 사용하여 항목을 식별하는 것입니다. JMS 메시지의 경우 메시지 ID를 사용할 수 있습니다.

재시도가 소진되면, RetryCallback을 호출하는 대신(이제 실패할 가능성이 높다고 간주됨) 실패한 항목을 다른 방식으로 처리할 수 있는 옵션도 있습니다. 무상태의 경우와 마찬가지로, 이 옵션은 RecoveryCallback에서 제공되며, RetryOperations의 execute 메서드에 전달하여 제공할 수 있습니다.

재시도 여부에 대한 결정은 실제로 일반 RetryPolicy에 위임되므로, 한도와 타임아웃에 대한 일반적인 고려 사항을 여기에 주입할 수 있습니다 (추가 종속성 섹션 참조).

재시도 정책

RetryTemplate 내부에서 execute 메서드의 재시도 또는 실패 결정은 RetryPolicy에 의해 결정되며, 이는 RetryContext의 팩토리이기도 합니다. RetryTemplate은 현재 정책을 사용하여 RetryContext를 생성하고 매 시도마다 이를 RetryCallback에 전달하는 역할을 합니다. 콜백이 실패한 후, RetryTemplate은 RetryPolicy를 호출하여 상태(RetryContext에 저장됨)를 업데이트하도록 요청해야 합니다. 그런 다음 정책에 또 다른 시도가 가능한지 묻습니다. 또 다른 시도가 불가능한 경우(예: 한도에 도달했거나 타임아웃이 감지된 경우), 정책은 소진 상태를 식별하는 역할도 담당합니다. 하지만 예외 처리는 담당하지 않습니다. RetryTemplate은 원래 예외를 던지는데, 복구가 불가능한 상태 저장(stateful) 경우는 예외입니다. 이 경우에는 RetryExhaustedException을 던집니다. 또한 RetryTemplate에 플래그를 설정하여 콜백(즉, 사용자 코드)에서 원래 예외를 무조건 던지도록 할 수도 있습니다.

팁: 실패는 본질적으로 재시도 가능하거나 그렇지 않습니다. 동일한 예외가 비즈니스 로직에서 항상 발생한다면 재시도해도 도움이 되지 않습니다. 따라서 모든 예외 유형에 대해 재시도해서는 안 됩니다. 대신 재시도 가능할 것으로 예상되는 예외에만 집중하세요. 더 적극적으로 재시도하는 것이 일반적으로 비즈니스 로직에 해롭지는 않지만, 실패가 결정론적인 경우 미리 치명적임을 알고 있는 것을 재시도하는 데 시간을 낭비하게 되므로 비효율적입니다.

Spring Retry는 상태 비저장(stateless) RetryPolicy(예: SimpleRetryPolicy)와 앞선 예제에서 사용된 TimeoutRetryPolicy의 간단한 범용 구현을 제공합니다.

SimpleRetryPolicy는 명명된 예외 유형 목록 중 어느 것이든 고정된 횟수까지 재시도할 수 있게 해줍니다. 다음 예제는 이를 사용하는 방법을 보여줍니다:

도구 다운로드