DeferredResult

์ด ํด๋ž˜์Šค๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋ฉฐ, ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ”๋กœ ์ค€๋น„๋˜์ง€ ์•Š์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์€ ๋ฐ”๋กœ ๋ฐ˜ํ™˜๋˜๊ณ , ์‹ค์ œ ๊ฒฐ๊ณผ๋Š” ๋‚˜์ค‘์— ์„ค์ •๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•„๋“œ:

  • timeoutValue: ํƒ€์ž„์•„์›ƒ์„ ์œ„ํ•œ ๊ฐ’์ž…๋‹ˆ๋‹ค. null์ด ๋  ์ˆ˜๋„ ์žˆ๊ณ , ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„๋กœ ํƒ€์ž„์•„์›ƒ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • timeoutResult: ํƒ€์ž„์•„์›ƒ ๋ฐœ์ƒ ์‹œ ๋ฐ˜ํ™˜ํ•  ๊ธฐ๋ณธ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•˜๋Š” Supplier ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์œ„ํ•œ ํ•„๋“œ๋“ค์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์Šต๋‹ˆ๋‹ค: ํƒ€์ž„์•„์›ƒ(timeoutCallback), ์—๋Ÿฌ(errorCallback), ์™„๋ฃŒ(completionCallback) ์‹œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

  • resultHandler: ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ์ž…๋‹ˆ๋‹ค.

  • result: ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค. ์ดˆ๊ธฐ ์ƒํƒœ๋Š” RESULT_NONE์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

  • expired: ๊ฐ์ฒด๊ฐ€ ๋งŒ๋ฃŒ๋˜์—ˆ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ”Œ๋ž˜๊ทธ์ž…๋‹ˆ๋‹ค.

๋ฉ”์†Œ๋“œ:

  • ๊ฒฐ๊ณผ๊ฐ€ ์„ค์ •๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” isSetOrExpired()

  • ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” getResult()

  • ๊ฒฐ๊ณผ๋ฅผ ์„ค์ •ํ•˜๋Š” setResult()์™€ setErrorResult()

  • ๊ฐ์ข… ์ฝœ๋ฐฑ์„ ์„ค์ •ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋“ค: onTimeout(), onError(), onCompletion()

  • ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•  DeferredResultHandler ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

์ด ํด๋ž˜์Šค๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์›น ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ์„œ๋ฒ„๋Š” DeferredResult ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ”๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ๊ณ„์‚ฐ์ด๋‚˜ ์ฒ˜๋ฆฌ๋ฅผ ๊ณ„์†ํ•˜๊ณ , ๊ฒฐ๊ณผ๊ฐ€ ์ค€๋น„๋˜๋ฉด DeferredResult ๊ฐ์ฒด์— ๊ฒฐ๊ณผ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๊ฒฐ๊ณผ๋ฅผ ์ž๋™์œผ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

์˜ˆ์‹œ

  • ๋จผ์ €, ์„œ๋น„์Šค ๊ณ„์ธต์˜ ์–ด๋–ค ๊ธฐ๋Šฅ์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ •

@Service
public class SomeAsyncService {
    @Async
    public CompletableFuture<String> performLongRunningOperation() {
        // ์—ฌ๊ธฐ์„œ ๊ธด ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
        try {
            Thread.sleep(5000); // 5์ดˆ๊ฐ„ ๋Œ€๊ธฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ๋ณต์žกํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return CompletableFuture.completedFuture("๊ฒฐ๊ณผ๊ฐ€ ์ค€๋น„๋˜์—ˆ์Šต๋‹ˆ๋‹ค");
    }
}

๊ทธ๋ฆฌ๊ณ  ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ด ์„œ๋น„์Šค๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•

@RestController
public class SomeController {
    private final SomeAsyncService someAsyncService;

    public SomeController(SomeAsyncService someAsyncService) {
        this.someAsyncService = someAsyncService;
    }

    @GetMapping("/asyncOperation")
    public DeferredResult<String> executeAsync() {
        DeferredResult<String> deferredResult = new DeferredResult<>();

        someAsyncService.performLongRunningOperation().thenAccept(result -> {
            deferredResult.setResult(result);
        }).exceptionally(ex -> {
            deferredResult.setErrorResult("์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: " + ex.getMessage());
            return null;
        });

        return deferredResult;
    }
}

DeferredResult๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์œ ์šฉํ•˜๋‹ค

  • ์™ธ๋ถ€ ์‹œ์Šคํ…œ์œผ๋กœ๋ถ€ํ„ฐ์˜ ๋น„๋™๊ธฐ์ ์ธ ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆด ๋•Œ

  • ๊ฒฐ๊ณผ๊ฐ€ ์ค€๋น„๋˜๋Š” ๋ฐ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ๋•Œ

  • ์Šคํ”„๋ง MVC์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ ์œ ํ•˜์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ

Last updated

Was this helpful?