๐Ÿš€ Spring @Async๋กœ ๋น„๋™๊ธฐ์˜ ์„ธ๊ณ„๋กœ ๋– ๋‚˜๋ณผ๊นŒ์š”? ๐ŸŒŸ

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ Spring @Async๋กœ ๋น„๋™๊ธฐ์˜ ์„ธ๊ณ„๋กœ ๋– ๋‚˜๋ณผ๊นŒ์š”? ๐ŸŒŸ

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ ์ •๋ง ํฅ๋ฏธ์ง„์ง„ํ•œ ์ฃผ์ œ๋กœ ์—ฌ๋Ÿฌ๋ถ„๊ณผ ํ•จ๊ป˜ ์ด์•ผ๊ธฐ๋ฅผ ๋‚˜๋ˆ ๋ณด๋ ค๊ณ  ํ•ด์š”. ๋ฐ”๋กœ 'Spring @Async๋ฅผ ์ด์šฉํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ'์— ๋Œ€ํ•ด์„œ์ฃ ! ๐Ÿ˜Ž

์•„, ๊ทธ๋Ÿฐ๋ฐ ์ž ๊น! ํ˜น์‹œ ์—ฌ๋Ÿฌ๋ถ„, '์žฌ๋Šฅ๋„ท'์ด๋ผ๋Š” ์‚ฌ์ดํŠธ๋ฅผ ๋“ค์–ด๋ณด์…จ๋‚˜์š”? ์ œ๊ฐ€ ์šด์˜ ์ค‘์ธ ์žฌ๋Šฅ ๊ณต์œ  ํ”Œ๋žซํผ์ธ๋ฐ์š”, ์—ฌ๊ธฐ '์ง€์‹์ธ์˜ ์ˆฒ'์ด๋ผ๋Š” ๋ฉ”๋‰ด์— ์ด ๊ธ€์ด ์˜ฌ๋ผ๊ฐˆ ์˜ˆ์ •์ด์—์š”. ์žฌ๋Šฅ๋„ท์—์„œ๋Š” ์ด๋Ÿฐ ๊ธฐ์ˆ ์ ์ธ ์ง€์‹๋ถ€ํ„ฐ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ๊นŒ์ง€ ๊ณต์œ ํ•˜๊ณ  ๊ฑฐ๋ž˜ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กญ์ฃ ? ๐Ÿ˜‰

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ Spring @Async์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊นŒ์š”? ๋งˆ์น˜ ์นดํ†ก์œผ๋กœ ๋Œ€ํ™”ํ•˜๋“ฏ์ด ํŽธํ•˜๊ฒŒ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ์ถœ๋ฐœ~! ๐Ÿƒโ€โ™‚๏ธ๐Ÿ’จ

๐Ÿค” ๋น„๋™๊ธฐ? ๊ทธ๊ฒŒ ๋ญ์ฃ ?

์ž, ์—ฌ๋Ÿฌ๋ถ„! ๋น„๋™๊ธฐ๋ผ๋Š” ๋ง, ๋“ค์–ด๋ณด์…จ๋‚˜์š”? ๋ญ”๊ฐ€ ์–ด๋ ค์›Œ ๋ณด์ด์ฃ ? ํ•˜์ง€๋งŒ ๊ฑฑ์ • ๋งˆ์„ธ์š”. ์•„์ฃผ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”!

๋น„๋™๊ธฐ๋Š” ๋ง ๊ทธ๋Œ€๋กœ '๋™์‹œ์— ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค'๋Š” ๋œป์ด์—์š”. ์Œ... ์ข€ ๋” ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด ์ด๋ ‡๋‹ต๋‹ˆ๋‹ค.

์ƒ์ƒํ•ด๋ณด์„ธ์š”: ์—ฌ๋Ÿฌ๋ถ„์ด ์นดํŽ˜์—์„œ ์ปคํ”ผ๋ฅผ ์ฃผ๋ฌธํ–ˆ์–ด์š”. ๊ทธ๋Ÿฐ๋ฐ ๋ฐ”๋ฆฌ์Šคํƒ€๊ฐ€ "์†๋‹˜, ์ปคํ”ผ ๋‚˜์˜ฌ ๋•Œ๊นŒ์ง€ ์—ฌ๊ธฐ ์„œ์„œ ๊ธฐ๋‹ค๋ฆฌ์„ธ์š”!"๋ผ๊ณ  ํ•œ๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”? ๋‹ต๋‹ตํ•˜๊ฒ ์ฃ ? ๐Ÿ˜…

์ด๊ฒŒ ๋ฐ”๋กœ '๋™๊ธฐ(Synchronous)' ๋ฐฉ์‹์ด์—์š”. ํ•œ ์ž‘์—…์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋‹ค๋ฅธ ์ผ์„ ๋ชปํ•˜๊ณ  ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜๋Š” ๊ฑฐ์ฃ .

๋ฐ˜๋ฉด์— ๋น„๋™๊ธฐ๋Š” ์–ด๋–จ๊นŒ์š”?

๋น„๋™๊ธฐ๋ผ๋ฉด: "์†๋‹˜, ์ฃผ๋ฌธ๋ฒˆํ˜ธ 30๋ฒˆ์ด์„ธ์š”. ์ปคํ”ผ ์ค€๋น„๋˜๋ฉด ํ˜ธ์ถœํ•ด๋“œ๋ฆด๊ฒŒ์š”. ๊ทธ๋™์•ˆ ์ž๋ฆฌ์— ์•‰์•„์„œ ํŽธํ•˜๊ฒŒ ์‰ฌ์„ธ์š”~" ์ด๋ ‡๊ฒŒ ๋งํ•˜๊ฒ ์ฃ ? ๐Ÿ‘

์ด๊ฒŒ ๋ฐ”๋กœ ๋น„๋™๊ธฐ(Asynchronous) ๋ฐฉ์‹์ด์—์š”. ์ปคํ”ผ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋Š” ๋™์•ˆ ์—ฌ๋Ÿฌ๋ถ„์€ ๋‹ค๋ฅธ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์ฃ . ์ฑ…์„ ์ฝ๊ฑฐ๋‚˜, ์นœ๊ตฌ์™€ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆ„๊ฑฐ๋‚˜, ์‹ฌ์ง€์–ด ์ž ๊น ํ™”์žฅ์‹ค์— ๋‹ค๋…€์˜ฌ ์ˆ˜๋„ ์žˆ์–ด์š”!

ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ์˜ ๋น„๋™๊ธฐ๋„ ์ด์™€ ๋น„์Šทํ•ด์š”. ๊ธด ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ , ๋‹ค๋ฅธ ์ผ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฑฐ์ฃ . coolํ•˜์ง€ ์•Š๋‚˜์š”? ๐Ÿ˜Ž

๋™๊ธฐ vs ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋™๊ธฐ ์ฒ˜๋ฆฌ ์ž‘์—… 1 ์ž‘์—… 2 ์ž‘์—… 3 ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์ž‘์—… 1 ์ž‘์—… 2 ์ž‘์—… 3

์œ„ ๊ทธ๋ฆผ์„ ๋ณด์„ธ์š”. ๋™๊ธฐ ์ฒ˜๋ฆฌ์—์„œ๋Š” ์ž‘์—…๋“ค์ด ์ฐจ๋ก€๋Œ€๋กœ ์ง„ํ–‰๋˜์ง€๋งŒ, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์—์„œ๋Š” ์ž‘์—…๋“ค์ด ๋™์‹œ์— ์‹œ์ž‘๋  ์ˆ˜ ์žˆ์–ด์š”. ๋ฉ‹์ง€์ฃ ? ๐ŸŒˆ

๐ŸŒŸ Spring @Async๋ž€?

์ž, ์ด์ œ Spring์˜ @Async์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊นŒ์š”? @Async๋Š” Spring Framework์—์„œ ์ œ๊ณตํ•˜๋Š” ์•„์ฃผ ๋ฉ‹์ง„ ๊ธฐ๋Šฅ์ด์—์š”. ์ด ๋…€์„์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”์†Œ๋“œ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

@Async์˜ ๋งˆ๋ฒ•: ๋ฉ”์†Œ๋“œ ์œ„์— @Async๋งŒ ๋ถ™์ด๋ฉด, ๊ทธ ๋ฉ”์†Œ๋“œ๋Š” ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋ผ์š”. ๋งˆ์น˜ ๋ฉ€ํ‹ฐํƒœ์Šคํ‚น์„ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”! ๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ป

์–ด๋–ค๊ฐ€์š”? ์ •๋ง ๊ฐ„๋‹จํ•˜์ฃ ? ํ•˜์ง€๋งŒ ์ด ๊ฐ„๋‹จํ•œ ์• ๋…ธํ…Œ์ด์…˜ ํ•˜๋‚˜๋กœ ์šฐ๋ฆฌ๋Š” ์—„์ฒญ๋‚œ ํž˜์„ ์–ป์„ ์ˆ˜ ์žˆ์–ด์š”!

@Async์˜ ๋งˆ๋ฒ• @Async Thread 1 Thread 2 Thread 3 ๋น„๋™๊ธฐ์  ์‹คํ–‰์˜ ๋งˆ๋ฒ•!

์œ„ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ, @Async๋Š” ๋งˆ๋ฒ• ์ง€ํŒก์ด์ฒ˜๋Ÿผ ๋ฉ”์†Œ๋“œ๋ฅผ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋กœ ๋‚˜๋ˆ„์–ด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค˜์š”. ์ด์ œ ์šฐ๋ฆฌ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์Šˆํผํžˆ์–ด๋กœ์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ผ์„ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฑฐ์ฃ ! ๐Ÿฆธโ€โ™‚๏ธ๐Ÿฆธโ€โ™€๏ธ

๊ทธ๋Ÿฐ๋ฐ ๋ง์ด์ฃ , ์ด @Async๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ช‡ ๊ฐ€์ง€ ์ค€๋น„ ์ž‘์—…์ด ํ•„์š”ํ•ด์š”. ๊ฑฑ์ • ๋งˆ์„ธ์š”, ์–ด๋ ต์ง€ ์•Š๋‹ต๋‹ˆ๋‹ค! ํ•จ๊ป˜ ์•Œ์•„๋ณผ๊นŒ์š”?

๐Ÿ› ๏ธ @Async ์‚ฌ์šฉ ์ค€๋น„ํ•˜๊ธฐ

์ž, ์ด์ œ @Async๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ค€๋น„๋ฅผ ํ•ด๋ณผ๊นŒ์š”? ๋งˆ์น˜ ์š”๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์žฌ๋ฃŒ๋ฅผ ์ค€๋น„ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”! ๐Ÿฅ•๐Ÿง…๐Ÿฅฉ

  1. @EnableAsync ์• ๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€ํ•˜๊ธฐ

    ๋จผ์ €, ์šฐ๋ฆฌ์˜ Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๊ฒŒ "์•ผ, ์šฐ๋ฆฌ ์ด์ œ ๋น„๋™๊ธฐ ์“ธ ๊ฑฐ์•ผ!"๋ผ๊ณ  ์•Œ๋ ค์ค˜์•ผ ํ•ด์š”. ์ด๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ๋ฐ”๋กœ @EnableAsync์˜ˆ์š”.

    
    @Configuration
    @EnableAsync
    public class AsyncConfig {
        // ์„ค์ • ๋‚ด์šฉ
    }
        

    ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Spring์ด "์˜ค์ผ€์ด, ์•Œ์•˜์–ด! ๋น„๋™๊ธฐ ๊ธฐ๋Šฅ ์ผค๊ฒŒ~"๋ผ๊ณ  ๋Œ€๋‹ตํ•˜๋Š” ๊ฑฐ์˜ˆ์š”. ๐Ÿ˜‰

  2. ThreadPoolTaskExecutor ์„ค์ •ํ•˜๊ธฐ

    ๋‹ค์Œ์œผ๋กœ, ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์Šค๋ ˆ๋“œ ํ’€์„ ๋งŒ๋“ค์–ด์•ผ ํ•ด์š”. ์ด๊ฑด ๋งˆ์น˜ ์ผ๊พผ๋“ค์„ ๊ณ ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”!

    
    @Configuration
    @EnableAsync
    public class AsyncConfig {
    
        @Bean(name = "taskExecutor")
        public Executor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(2);
            executor.setMaxPoolSize(5);
            executor.setQueueCapacity(100);
            executor.setThreadNamePrefix("AsyncThread-");
            executor.initialize();
            return executor;
        }
    }
        

    ์—ฌ๊ธฐ์„œ ๊ฐ ์„ค์ •์˜ ์˜๋ฏธ๋Š” ์ด๋ž˜์š”:

    • setCorePoolSize(2): ๊ธฐ๋ณธ์ ์œผ๋กœ 2๋ช…์˜ ์ผ๊พผ์„ ๊ณ ์šฉํ•ด์š”.
    • setMaxPoolSize(5): ์ผ์ด ๋งŽ์•„์ง€๋ฉด ์ตœ๋Œ€ 5๋ช…๊นŒ์ง€ ๊ณ ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
    • setQueueCapacity(100): ์ผ๊พผ๋“ค์ด ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•œ ์ผ์„ ์ตœ๋Œ€ 100๊ฐœ๊นŒ์ง€ ๋Œ€๊ธฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”.
    • setThreadNamePrefix("AsyncThread-"): ๊ฐ ์ผ๊พผ์—๊ฒŒ "AsyncThread-1", "AsyncThread-2" ๊ฐ™์€ ์ด๋ฆ„์„ ๋ถ™์—ฌ์ค˜์š”.

์ž, ์ด์ œ ์ค€๋น„๋Š” ๋๋‚ฌ์–ด์š”! ์šฐ๋ฆฌ์˜ Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ด์ œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‹ต๋‹ˆ๋‹ค. ๐Ÿ‘

๋น„๋™๊ธฐ ์ž‘์—… ์ค€๋น„ ๊ณผ์ • @EnableAsync ThreadPool TaskExecutor ๋น„๋™๊ธฐ ์ค€๋น„ ์™„๋ฃŒ! Thread 1 Thread 2 Thread 3 Thread 4 Thread 5

์œ„ ๊ทธ๋ฆผ์„ ๋ณด์„ธ์š”. @EnableAsync๋กœ ๋น„๋™๊ธฐ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•˜๊ณ , ThreadPoolTaskExecutor๋กœ ์Šค๋ ˆ๋“œ ํ’€์„ ์„ค์ •ํ•˜๋ฉด, ์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์œ„ํ•œ ์ค€๋น„๋ฅผ ๋งˆ์น˜๊ฒŒ ๋ผ์š”. ๋งˆ์น˜ ์Šˆํผํžˆ์–ด๋กœ ํŒ€์ด ๊ฒฐ์„ฑ๋œ ๊ฒƒ ๊ฐ™์ง€ ์•Š๋‚˜์š”? ๐Ÿฆธโ€โ™‚๏ธ๐Ÿฆธโ€โ™€๏ธ๐Ÿฆนโ€โ™‚๏ธ๐Ÿฆนโ€โ™€๏ธ๐Ÿฆธโ€โ™‚๏ธ

์ด์ œ ์šฐ๋ฆฌ๋Š” @Async๋ฅผ ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์–ด์š”! ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์‹ค์ œ๋กœ @Async๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ๊ธฐ๋Œ€๋˜์ง€ ์•Š๋‚˜์š”? ๐Ÿ˜ƒ

๐ŸŽญ @Async ์‚ฌ์šฉํ•˜๊ธฐ

์ž, ์ด์ œ ๋“œ๋””์–ด @Async๋ฅผ ์‚ฌ์šฉํ•ด๋ณผ ์‹œ๊ฐ„์ด์—์š”! ๐Ÿ˜ƒ ์ค€๋น„๋Š” ๋๋‚ฌ๊ณ , ์ด์ œ ์‹ค์ „์ด์—์š”. ๋งˆ์น˜ ์š”๋ฆฌ ์žฌ๋ฃŒ๋ฅผ ๋‹ค ์ค€๋น„ํ•˜๊ณ  ์ด์ œ ์š”๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”! ๐Ÿณ

@Async๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ •๋ง ๊ฐ„๋‹จํ•ด์š”. ๊ทธ์ € ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ๋ฉ”์†Œ๋“œ ์œ„์— @Async ์• ๋…ธํ…Œ์ด์…˜๋งŒ ๋ถ™์ด๋ฉด ๋ผ์š”. ์‰ฝ์ฃ ?


@Service
public class EmailService {

    @Async
    public void sendEmail(String to, String subject, String content) {
        // ์ด๋ฉ”์ผ ๋ณด๋‚ด๋Š” ๋กœ์ง
        System.out.println("Sending email to " + to);
        try {
            Thread.sleep(3000); // ์ด๋ฉ”์ผ ๋ณด๋‚ด๋Š”๋ฐ 3์ดˆ ๊ฑธ๋ฆฐ๋‹ค๊ณ  ๊ฐ€์ •
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Email sent to " + to);
    }
}

์œ„ ์ฝ”๋“œ์—์„œ sendEmail ๋ฉ”์†Œ๋“œ๋Š” @Async ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด์žˆ์–ด์š”. ์ด๊ฒŒ ๋ฌด์Šจ ์˜๋ฏธ์ผ๊นŒ์š”?

@Async์˜ ๋งˆ๋ฒ•: ์ด ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ, Spring์€ "์–˜๋“ค์•„, ์ด ์ผ์€ ๋„ˆํฌ๊ฐ€ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•ด!"๋ผ๊ณ  ๋งํ•˜๋ฉฐ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—๊ฒŒ ์ด ์ž‘์—…์„ ๋งก๊ธฐ๋Š” ๊ฑฐ์˜ˆ์š”. ๊ทธ๋ฆฌ๊ณ  ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ์ชฝ์€ "์•Œ๊ฒ ์–ด, ๋„ˆํฌ๊ฐ€ ์•Œ์•„์„œ ํ•˜๊ฒ ์ง€?"ํ•˜๊ณ  ๋‹ค์Œ ์ผ์„ ํ•˜๋Ÿฌ ๊ฐ€๋Š” ๊ฑฐ์ฃ . ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด๋ฉ”์ผ์„ ๋ณด๋‚ด๋Š” ์ž‘์—…์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋”๋ผ๋„, ๋‹ค๋ฅธ ์ž‘์—…๋“ค์€ ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  ๊ณ„์† ์ง„ํ–‰๋  ์ˆ˜ ์žˆ์–ด์š”. coolํ•˜์ฃ ? ๐Ÿ˜Ž

@Async ๋™์ž‘ ๋ฐฉ์‹ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ @Async ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ ๋น„๋™๊ธฐ ์ž‘์—… ์‹คํ–‰

์œ„ ๊ทธ๋ฆผ์„ ๋ณด์„ธ์š”. ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ @Async ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, ๊ทธ ์ž‘์—…์€ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ๋กœ ๋„˜๊ฒจ์ ธ์š”. ๊ทธ๋ฆฌ๊ณ  ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋Š” ๊ณ„์†ํ•ด์„œ ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ๋งˆ์น˜ ์š”๋ฆฌ์‚ฌ๊ฐ€ ์˜ค๋ธ์— ์š”๋ฆฌ๋ฅผ ๋„ฃ๊ณ  ๋‹ค๋ฅธ ์ค€๋น„๋ฅผ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”! ๐Ÿ‘จโ€๐Ÿณ๐Ÿฝ๏ธ

ํ•˜์ง€๋งŒ ์ฃผ์˜ํ•  ์ ์ด ์žˆ์–ด์š”!

์ฃผ์˜์‚ฌํ•ญ: @Async ๋ฉ”์†Œ๋“œ๋Š” ๋ฐ˜๋“œ์‹œ public ๋ฉ”์†Œ๋“œ์—ฌ์•ผ ํ•ด์š”. ๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ํด๋ž˜์Šค ๋‚ด์˜ ๋‹ค๋ฅธ ๋ฉ”์†Œ๋“œ์—์„œ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ ๋ผ์š”. ์™œ๋ƒํ•˜๋ฉด Spring์˜ ํ”„๋ก์‹œ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋•Œ๋ฌธ์ด์—์š”. ๐Ÿšซ

์ž, ์ด์ œ @Async๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ ๋˜์—ˆ์–ด์š”. ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ๋์ด ์•„๋‹ˆ์—์š”! @Async๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ˜ํ™˜ ๊ฐ’์€ ์–ด๋–ป๊ฒŒ ๋ฐ›์„ ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋‹ค์Œ ์„น์…˜์—์„œ ์•Œ์•„๋ณด๋„๋ก ํ•ด์š”! ๐Ÿค”

๐ŸŽ @Async์™€ ๋ฐ˜ํ™˜ ๊ฐ’

์ž, ์ด์ œ @Async๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋น„๋™๊ธฐ๋กœ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์–ด์š”. ๊ทธ๋Ÿฐ๋ฐ ๋ง์ด์ฃ , ๊ฐ€๋”์€ ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ์–ด์š”. ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋ ๊นŒ์š”? ๐Ÿค”

Spring์€ ์ด๋ฅผ ์œ„ํ•ด Future์™€ CompletableFuture๋ผ๋Š” ๋ฉ‹์ง„ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ด์š”. ์ด ๋‘ ๊ฐ€์ง€์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊นŒ์š”?

1. Future ์‚ฌ์šฉํ•˜๊ธฐ

Future๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋‚˜์ค‘์— ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ˆ์š”. ๋งˆ์น˜ ๋ ˆ์Šคํ† ๋ž‘์—์„œ ์ฃผ๋ฌธ ๋ฒˆํ˜ธ๋ฅผ ๋ฐ›๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ด์š”!


@Service
public class CalculationService {

    @Async
    public Future<integer> calculateSum(int a, int b) {
        try {
            Thread.sleep(5000); // ๊ณ„์‚ฐํ•˜๋Š”๋ฐ 5์ดˆ ๊ฑธ๋ฆฐ๋‹ค๊ณ  ๊ฐ€์ •
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<>(a + b);
    }
}
</integer>

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, calculateSum ๋ฉ”์†Œ๋“œ๋Š” ์ฆ‰์‹œ Future ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์‹ค์ œ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋Š” ๋‚˜์ค‘์— ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”.


Future<integer> futureResult = calculationService.calculateSum(10, 20);
// ์—ฌ๊ธฐ์„œ ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”
Integer result = futureResult.get(); // ๊ฒฐ๊ณผ๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์š”
System.out.println("Result: " + result);
</integer>

2. CompletableFuture ์‚ฌ์šฉํ•˜๊ธฐ

CompletableFuture๋Š” Future์˜ ๊ฐœ์„ ๋œ ๋ฒ„์ „์ด์—์š”. ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ณ , ์—ฌ๋Ÿฌ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค˜์š”. ๋งˆ์น˜ ๋ ˆ๊ณ  ๋ธ”๋ก์ฒ˜๋Ÿผ ๋น„๋™๊ธฐ ์ž‘์—…๋“ค์„ ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿงฑ


@Service
public class CalculationService {

    @Async
    public CompletableFuture<integer> calculateSum(int a, int b) {
        try {
            Thread.sleep(5000); // ๊ณ„์‚ฐํ•˜๋Š”๋ฐ 5์ดˆ ๊ฑธ๋ฆฐ๋‹ค๊ณ  ๊ฐ€์ •
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return CompletableFuture.completedFuture(a + b);
    }
}
</integer>

CompletableFuture๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋” ์œ ์—ฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”:


CompletableFuture<integer> futureResult = calculationService.calculateSum(10, 20);
futureResult.thenAccept(result -> System.out.println("Result: " + result));
// ์—ฌ๊ธฐ์„œ ๋ฐ”๋กœ ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”!
</integer>
Future vs CompletableFuture Future - ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆผ - ๋‹จ์ˆœํ•œ ์‚ฌ์šฉ CompletableFuture - ๋น„๋™๊ธฐ ์ฒด์ด๋‹ - ๋” ๋งŽ์€ ๊ธฐ๋Šฅ ๊ฒฐ๊ณผ ๋Œ€๊ธฐ ๋น„๋™๊ธฐ ์ฒด์ธ

์œ„ ๊ทธ๋ฆผ์„ ๋ณด์„ธ์š”. Future๋Š” ๋‹จ์ˆœํžˆ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฐ˜๋ฉด, CompletableFuture๋Š” ์—ฌ๋Ÿฌ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋งˆ์น˜ ๋„๋ฏธ๋…ธ์ฒ˜๋Ÿผ ํ•˜๋‚˜๊ฐ€ ๋๋‚˜๋ฉด ๋‹ค์Œ ์ž‘์—…์ด ์‹œ์ž‘๋˜๋Š” ๊ฑฐ์ฃ ! ๐ŸŽญ

์ž, ์ด์ œ @Async๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์–ด์š”. ์ •๋ง ๋ฉ‹์ง€์ง€ ์•Š๋‚˜์š”? ๐ŸŒŸ

ํ•˜์ง€๋งŒ ์ž ๊น! ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ํ•ญ์ƒ ์ข‹์€ ๊ฒƒ๋งŒ์€ ์•„๋‹ˆ์—์š”. ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” @Async ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ๋“ค์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? ๐Ÿš€

โš ๏ธ @Async ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ

์ž, ์ด์ œ @Async์˜ ๋ฉ‹์ง„ ๊ธฐ๋Šฅ๋“ค์„ ์•Œ๊ฒŒ ๋˜์—ˆ์–ด์š”. ํ•˜์ง€๋งŒ ๋ชจ๋“  ๋„๊ตฌ๊ฐ€ ๊ทธ๋ ‡๋“ฏ, @Async๋„ ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•ด์š”. ๋งˆ์น˜ ์š”๋ฆฌํ•  ๋•Œ ์นผ์„ ์กฐ์‹ฌ์Šค๋Ÿฝ๊ฒŒ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”! ๐Ÿ”ช

์—ฌ๊ธฐ @Async ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•ด์•ผ ํ•  ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ๋“ค์ด ์žˆ์–ด์š”:

  1. ๊ฐ™์€ ํด๋ž˜์Šค ๋‚ด ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ

    ๊ฐ™์€ ํด๋ž˜์Šค ์•ˆ์—์„œ @Async ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์•„์š”. ์™œ๋ƒํ•˜๋ฉด Spring์˜ ํ”„๋ก์‹œ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋•Œ๋ฌธ์ด์—์š”.

    
    @Service
    public class MyService {
        public void methodA() {
            methodB(); // ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด @Async๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์•„์š”!
        }
    
        @Async
        public void methodB() {
            // ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰๋˜๊ธธ ์›ํ•˜๋Š” ์ฝ”๋“œ
        }
    }
        
  2. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

    @Async ๋ฉ”์†Œ๋“œ์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋Š” ํ˜ธ์ถœํ•œ ์ชฝ์œผ๋กœ ์ „ํŒŒ๋˜์ง€ ์•Š์•„์š”. ๋”ฐ๋ผ์„œ ๋ณ„๋„์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ด์š”.

    
    @Async
    public CompletableFuture<string> riskyMethod() {
        try {
            // ์œ„ํ—˜ํ•œ ์ž‘์—…
        } catch (Exception e) {
            return CompletableFuture.failedFuture(e);
        }
        return CompletableFuture.completedFuture("Success");
    }
        </string>
  3. ํ…Œ์ŠคํŠธ์˜ ์–ด๋ ค์›€

    ๋น„๋™๊ธฐ ์ฝ”๋“œ๋Š” ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์–ด์š”. ํŠนํžˆ ์‹œ๊ฐ„์— ๋ฏผ๊ฐํ•œ ํ…Œ์ŠคํŠธ์˜ ๊ฒฝ์šฐ ๋”์šฑ ๊ทธ๋ž˜์š”.

  4. ์„ฑ๋Šฅ ์˜ค๋ฒ„ํ—ค๋“œ

    ์ž‘์€ ์ž‘์—…์— @Async๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์˜คํžˆ๋ ค ์„ฑ๋Šฅ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์–ด์š”. ์Šค๋ ˆ๋“œ ์ƒ์„ฑ๊ณผ ๊ด€๋ฆฌ์—๋„ ๋น„์šฉ์ด ๋“ค๊ฑฐ๋“ ์š”.

  5. ๋ฐ๋“œ๋ฝ ๊ฐ€๋Šฅ์„ฑ

    ๋น„๋™๊ธฐ ์ž‘์—…๋“ค์ด ์„œ๋กœ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Ÿฐ ๊ฒฝ์šฐ ๋ฐ๋“œ๋ฝ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

@Async ์ฃผ์˜์‚ฌํ•ญ @Async ๊ฐ™์€ ํด๋ž˜์Šค ์ฃผ์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํ•„์š” ํ…Œ์ŠคํŠธ ์–ด๋ ค์›€ ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜์„ธ์š”!

์œ„ ๊ทธ๋ฆผ์€ @Async ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ฃผ์š” ์‚ฌํ•ญ๋“ค์„ ๋ณด์—ฌ์ค˜์š”. ๋งˆ์น˜ ์•„๋ฆ„๋‹ค์šด ์žฅ๋ฏธ์—๋„ ๊ฐ€์‹œ๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, @Async๋„ ์žฅ์ ๊ณผ ํ•จ๊ป˜ ์ฃผ์˜ํ•  ์ ์ด ์žˆ๋‹ต๋‹ˆ๋‹ค. ๐ŸŒน

ํ•˜์ง€๋งŒ ๊ฑฑ์ •ํ•˜์ง€ ๋งˆ์„ธ์š”! ์ด๋Ÿฐ ์ฃผ์˜์‚ฌํ•ญ๋“ค์„ ์ž˜ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด, @Async๋ฅผ ๋”์šฑ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ๋งˆ์น˜ ์š”๋ฆฌ์‚ฌ๊ฐ€ ์นผ์„ ๋Šฅ์ˆ™ํ•˜๊ฒŒ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์ฃ ! ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ

์ž, ์ด์ œ ์šฐ๋ฆฌ๋Š” @Async์˜ ๋ชจ๋“  ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์–ด์š”. ๋ฉ‹์ง„ ๊ธฐ๋Šฅ๋„ ์•Œ์•˜๊ณ , ์ฃผ์˜ํ•  ์ ๋„ ์•Œ์•˜์ฃ . ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ @Async๋ฅผ ์ž์‹  ์žˆ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿš€

๐ŸŽ‰ ๋งˆ๋ฌด๋ฆฌ

์™€์šฐ! ์ •๋ง ๊ธด ์—ฌ์ •์ด์—ˆ์ฃ ? ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ๋ถ„, ์ •๋ง ์ž˜ ํ•ด๋ƒˆ์–ด์š”! ๐Ÿ‘๐Ÿ‘๐Ÿ‘

์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ๊นŒ์ง€ Spring์˜ @Async์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ์•Œ์•„๋ดค์–ด์š”. ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ฐœ๋…๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ, @Async์˜ ์‚ฌ์šฉ๋ฒ•, ๋ฐ˜ํ™˜ ๊ฐ’ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•, ๊ทธ๋ฆฌ๊ณ  ์ฃผ์˜์‚ฌํ•ญ๊นŒ์ง€! ๋งˆ์น˜ ๋ฉ‹์ง„ ๋ชจํ—˜์„ ๋– ๋‚œ ๊ฒƒ ๊ฐ™์ง€ ์•Š๋‚˜์š”? ๐Ÿž๏ธ

์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ @Async๋ฅผ ์‚ฌ์šฉํ•ด์„œ:

  • ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”. โฑ๏ธ
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‘๋‹ต์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿš€
  • ๋ณต์žกํ•œ ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐ŸŽ

ํ•˜์ง€๋งŒ ๊ธฐ์–ตํ•˜์„ธ์š”! ๊ฐ•๋ ฅํ•œ ํž˜์—๋Š” ํฐ ์ฑ…์ž„์ด ๋”ฐ๋ฅด๋Š” ๋ฒ•์ด์ฃ . @Async๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•ญ์ƒ ์ฃผ์˜์‚ฌํ•ญ์„ ์—ผ๋‘์— ๋‘์„ธ์š”. ๊ทธ๋ž˜์•ผ ์ง„์ •ํ•œ ๋น„๋™๊ธฐ ๋งˆ์Šคํ„ฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿฆธโ€โ™‚๏ธ๐Ÿฆธโ€โ™€๏ธ

์ž, ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ Spring @Async์˜ ์ „๋ฌธ๊ฐ€๊ฐ€ ๋˜์—ˆ์–ด์š”. ์ด ์ง€์‹์„ ํ™œ์šฉํ•ด์„œ ๋” ๋ฉ‹์ง„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”. ์„ธ์ƒ์„ ๋†€๋ผ๊ฒŒ ํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‚˜์š”? Let's go! ๐Ÿš€

@Async ๋งˆ์Šคํ„ฐ @Async ๋งˆ์Šคํ„ฐ ๐Ÿ’ก ๐Ÿš€ โšก ๐Ÿ”ง

์—ฌ๋Ÿฌ๋ถ„, ์ •๋ง ์ˆ˜๊ณ  ๋งŽ์œผ์…จ์–ด์š”! ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ์œ„ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ @Async์˜ ์ง„์ •ํ•œ ๋งˆ์Šคํ„ฐ๊ฐ€ ๋˜์—ˆ๋‹ต๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ์˜ ์„ธ๊ณ„์—์„œ ๋งˆ์Œ๊ป ๋‚ ์•„๋‹ค๋‹ ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‚˜์š”? ๐Ÿฆ…

๊ทธ๋ฆฌ๊ณ  ์žŠ์ง€ ๋งˆ์„ธ์š”, ์šฐ๋ฆฌ์˜ ์—ฌ์ •์€ ์—ฌ๊ธฐ์„œ ๋๋‚˜์ง€ ์•Š์•„์š”. ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์„ธ๊ณ„๋Š” ๋Š์ž„์—†์ด ๋ณ€ํ™”ํ•˜๊ณ  ๋ฐœ์ „ํ•˜๋‹ˆ๊นŒ์š”. ๊ณ„์†ํ•ด์„œ ๋ฐฐ์šฐ๊ณ , ์„ฑ์žฅํ•˜๊ณ , ๋„์ „ํ•˜์„ธ์š”! ๐Ÿ’ช

๋งˆ์ง€๋ง‰์œผ๋กœ, ์ด ๊ธ€์ด ์žฌ๋Šฅ๋„ท์˜ '์ง€์‹์ธ์˜ ์ˆฒ'์— ์˜ฌ๋ผ๊ฐ„๋‹ค๋Š” ๊ฑธ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ์—ฌ๋Ÿฌ๋ถ„์˜ ์ง€์‹์ด ๋‹ค๋ฅธ ์ด๋“ค์—๊ฒŒ๋„ ์ „ํ•ด์งˆ ๊ฑฐ์˜ˆ์š”. ํ•จ๊ป˜ ๋ฐฐ์šฐ๊ณ  ์„ฑ์žฅํ•˜๋Š” ๋ฉ‹์ง„ ์ปค๋ฎค๋‹ˆํ‹ฐ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€์š”! ๐ŸŒณ๐ŸŒณ๐ŸŒณ

์ž, ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์˜ ๋น„๋™๊ธฐ ์—ฌ์ •์„ ์‹œ์ž‘ํ•˜์„ธ์š”. ๋ฉ‹์ง„ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์‹ค ๊ฑฐ๋ผ ๋ฏฟ์–ด์š”. ํ™”์ดํŒ…! ๐Ÿ‘Š๐Ÿ˜„