[Spring] @Cacheable ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€ ํ˜ธ์ถœ ๊ฐœ์„ ํ•˜๊ธฐ (feat. self invocation)

2023. 1. 7. 01:53ใ†Backend/๐ŸŒฟ Spring

๋ชฉ์ฐจ

  • ๋ฐฐ๊ฒฝ
  • ๋ฌธ์ œ
  • API ๊ฐœ์„  ์š”๊ตฌ์‚ฌํ•ญ
    • ํ˜„์žฌ API ์‚ฌํ•ญ
    • ๊ฐœ์„ ๋œ API ์š”๊ตฌ์‚ฌํ•ญ
  • ์ฒซ ๋ฒˆ์งธ ์‹œ๋„
  • ๋‘ ๋ฒˆ์งธ ์‹œ๋„
  • ์„ธ ๋ฒˆ์งธ ์‹œ๋„
  • Self-Invocation ํ•ด๊ฒฐ ๋ฐฉ์•ˆ (Proxy ์ƒ์„ฑ)
    • 1) ApplicationContext DI
    • 2) @Resource์œผ๋กœ AutoWiring ๋งˆ๋ฌด๋ฆฌ

๋ฐฐ๊ฒฝ

  1. ํด๋ผ์ด์–ธํŠธ์—์„œ ํŠน์ • ํ‚ค์›Œ๋“œ๋กœ ์กฐํšŒํ•˜๋ฉด, ํ•ด๋‹น ํ‚ค์›Œ๋“œ์— ํ•ด๋‹นํ•˜๋Š” ์ƒํ’ˆ ๋ชฉ๋ก์„ ๋ฐ›์•„์˜จ๋‹ค.
    1. ์‡ผํ•‘๋ชฐ API ์—์„œ ์ƒํ’ˆ์„ ๋ณด๋‚ด์ฃผ๋ฉฐ, 12๊ฐœ์˜ ์ƒํ’ˆ์„ ๋””ํดํŠธ๋กœ ๋ณด๋‚ด์ค€๋‹ค.
    2. ์‡ผํ•‘๋ชฐ API์—์„œ ํ•ด๋‹น ํ‚ค์›Œ๋“œ์˜ ์ƒํ’ˆ ์žฌ๊ณ ๊ฐ€ ๋ถ€์กฑํ•˜๋ฉด, 12๊ฐœ ๋ฏธ๋งŒ์œผ๋กœ ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ์ƒํ’ˆ์˜ ๊ฐœ์ˆ˜๊ฐ€ 9๊ฐœ ๋ฏธ๋งŒ์ด๋ฉด, ์žฌ๊ณ  ๋ณด์ถฉ notify ๋ฅผ ์œ„ํ•ด ์Šฌ๋ž™๋ด‡ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์†ก๋œ๋‹ค.

 

๋ฌธ์ œ

์ƒํ’ˆ ์žฌ๊ณ ๊ฐ€ ๋ถ€์กฑํ•œ ํ‚ค์›Œ๋“œ๋กœ api ์š”์ฒญ์ด ๊ณ„์† ๋“ค์–ด์˜ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

๋งค๋ฒˆ api ์š”์ฒญ๋งˆ๋‹ค ์Šฌ๋ž™๋ด‡์ด ์ „์†ก๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ต‰์žฅํžˆ ๊ท€์ฐฎ์€ ์ƒํ™ฉ์ด ๋ฒŒ์–ด์ง‘๋‹ˆ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ์š”.

 

๋จธ..๋ฉˆ์ถฐ..

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

 

API ๊ฐœ์„  ์š”๊ตฌ์‚ฌํ•ญ

- ํŠน์ • ํ‚ค์›Œ๋“œ์˜ ์ƒํ’ˆ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜จ๋‹ค.

- ์ƒํ’ˆ ๋ชฉ๋ก์˜ ์ˆœ์„œ๋Š” ๋งค ์š”์ฒญ๋งˆ๋‹ค ๋žœ๋ค์œผ๋กœ ๋‹ฌ๋ผ์ง„๋‹ค. (Shuffle ์ฒ˜๋ฆฌ)

- ์ƒํ’ˆ ์žฌ๊ณ ๊ฐ€ 9๊ฐœ ๋ฏธ๋งŒ์œผ๋กœ ๋–จ์–ด์ง€๋ฉด, ์žฌ๊ณ  ๋ณด์ถฉ์„ ์œ„ํ•ด ์Šฌ๋ž™๋ด‡ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•œ๋‹ค.

- ์Šฌ๋ž™๋ด‡ ๋ฉ”์‹œ์ง€๋Š” ๋™์ผํ•œ ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด ์ตœ์ดˆ 1ํšŒ๋งŒ ์ „์†ก๋˜์•ผ ํ•œ๋‹ค.

 

 

ํ˜„์žฌ API ์‚ฌํ•ญ

- ํŠน์ • ํ‚ค์›Œ๋“œ์˜ ์ƒํ’ˆ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜จ๋‹ค.

- ์ƒํ’ˆ ๋ชฉ๋ก์˜ ์ˆœ์„œ๋Š” ๋งค ์š”์ฒญ๋งˆ๋‹ค ๋žœ๋ค์œผ๋กœ ๋‹ฌ๋ผ์ง„๋‹ค. (Shuffle ์ฒ˜๋ฆฌ)

- ์ƒํ’ˆ ์žฌ๊ณ ๊ฐ€ 9๊ฐœ ๋ฏธ๋งŒ์œผ๋กœ ๋–จ์–ด์ง€๋ฉด, ์žฌ๊ณ  ๋ณด์ถฉ์„ ์œ„ํ•ด ์Šฌ๋ž™๋ด‡ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•œ๋‹ค.

- ์ƒํ’ˆ ์žฌ๊ณ ๊ฐ€ 9๊ฐœ ๋ฏธ๋งŒ์ธ ํ‚ค์›Œ๋“œ์˜ ๋งค ์š”์ฒญ๋งˆ๋‹ค ์Šฌ๋ž™๋ด‡ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์†ก๋œ๋‹ค. โฌ…๏ธ ๊ฐœ์„ ํ•˜๊ณ  ์‹ถ์€ ์‚ฌํ•ญ ๊ฐœ์„ ๋œ API ์š”๊ตฌ์‚ฌํ•ญ

- ์Šฌ๋ž™๋ด‡ ๋ฉ”์‹œ์ง€๋Š”, ๋™์ผํ•œ ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด ์ตœ์ดˆ 1ํšŒ๋งŒ ์ „์†ก๋ผ์•ผ ํ•œ๋‹ค.

 

์Šฌ๋ž™๋ด‡ ๋ฉ”์‹œ์ง€๋ฅผ 1๋ฒˆ๋งŒ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด ์บ์‹œ๋ฅผ ์ ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๊ณ , ๊ฒฝ๋Ÿ‰ ์บ์‹œ์ธ Ehcache๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ฒซ ์‹œ๋„

์‹œํ–‰์ฐฉ์˜ค ๊ณผ์ •์„ ์œ„ํ•ด ์ฒ˜์Œ ์ง  ์ฝ”๋“œ๋ถ€ํ„ฐ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

("๋ญ์•ผ, ํ•ด๊ฒฐ์ฑ…์ด๋‚˜ ๋ณด์—ฌ์ค˜์š”" ํ•˜์‹œ๋Š” ๋ถ„๋“ค์€ ์„ธ๋ฒˆ์งธ ์‹œ๋„ ๋ชฉ์ฐจ๋กœ ๊ฐ€์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค ๋€จ)

@Cacheable(cacheNames = "products", key = "#searchKeyword")
public List<ProductDto> getProductOfReview(String searchKeyword) {

    List<ProductDto> result = getProduct(searchKeyword); // <- mall api ์—์„œ ์ƒํ’ˆ ์ •๋ณด ์กฐํšŒ
    if (result.size() < 9) {
        sendSlackMessage(); // <- slackbot ์ „์†ก ๋ฉ”์„œ๋“œ
    }
    
    Collections.shuffle(result); // <- shuffle ์ฒ˜๋ฆฌ
    return result;
}


// slackbot ์ „์†ก ๋ฉ”์„œ๋“œ
public void sendSlackMessage() {

    try {
        ...
        Slack.chatPostMessage(request);
        ...
    } catch (SlackApiException | IOException exception) {
        log.error("Slack Error" + exception.getMessage());
        throw new BusinessException(SlackErrorCode.SLACK_ERROR);
    }
}

 

์ƒํ’ˆ์„ ์กฐํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ž์ฒด์— ์บ์‹œ๋ฅผ ๊ฑธ์—ˆ์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ searchKeyword์˜ ์บ์‹œ ์ฒ˜๋ฆฌ๋Š” ์ž˜ ๋˜์ง€๋งŒ 2๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

1) ์ƒํ’ˆ์ด shuffle ๋˜์ง€ ์•Š์Œ -> ์ƒํ’ˆ์ด ๋ฌด์ž‘์œ„๋กœ ๋–จ์–ด์ง€์ง€ ์•Š๊ณ , ๋™์ผํ•œ ์ˆœ์„œ๋กœ ์กฐํšŒ๋œ๋‹ค. (๊ธฐํš ์ •์ฑ…๊ณผ ๋‹ค๋ฆ„)

2) ํ•œ๋ฒˆ ์บ์‹ฑ๋˜๋ฉด, ์ƒํ’ˆ์ด 9๊ฐœ ๋ฏธ๋งŒ์œผ๋กœ ๋–จ์–ด์ง€๋”๋ผ๋„, ์Šฌ๋žซ๋ด‡์ด ์šธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. (์žฌ๊ณ ๊ฐ€ ๋ถ€์กฑํ•ด์ง€๋”๋ผ๋„ ๋…ธํ‹ฐ ํ•  ์ˆ˜ ์—†์Œ)

3) ์Šฌ๋ž™๋ด‡์ด ์ตœ์ดˆ 1ํšŒ์กฐ์ฐจ ์ „์†ก๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

 

์œ„์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‘ ๋ฒˆ์งธ ์‹œ๋„๋กœ ๊ฐ‘๋‹ˆ๋‹ค.

 

๋‘๋ฒˆ์งธ ์‹œ๋„

1. ์Šฌ๋ž™๋ด‡ ์ „์†ก ๋ฉ”์„œ๋“œ sendSlackMessage() ๋งŒ ์บ์‹œ์ฒ˜๋ฆฌ

- ์Šฌ๋ž™๋ด‡ ์ „์†ก ๋ฉ”์„œ๋“œ๋งŒ ์บ์‹ฑ๋จ

- ์ตœ์ดˆ ํ•œ ๋ฒˆ๋งŒ ์Šฌ๋ž™๋ด‡์ด ๋™์ž‘ํ•˜๊ณ , ๊ทธ ์ดํ›„๋ก  ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์†ก๋˜์ง€ ์•Š๋Š”๋‹ค.

 

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ฒซ ๋ฒˆ์งธ ์‹œ๋„์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1. ์ƒํ’ˆ์ด ์ •์ƒ์ ์œผ๋กœ shuffle ๋œ๋‹ค.

2. ์ƒํ’ˆ์ด 9๊ฐœ ๋ฏธ๋งŒ์œผ๋กœ ๋–จ์–ด์ง€๋ฉด, ์Šฌ๋ž™๋ด‡ ์ „์†ก ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

 

public List<ProductDto> getProductOfReview(String searchKeyword) {

    List<ProductDto> result = getProduct(searchKeyword);
    if (result.size() < 9) {
        log.info(">>> [Before] Caching method");
        // slackbot ์ „์†ก ๋ฉ”์„œ๋“œ
        sendSlackMessage(searchKeyword); 
    }
    
    Collections.shuffle(result);
    return result;
}


// slackbot ์ „์†ก ๋ฉ”์„œ๋“œ ์บ์‹œ ์ ์šฉ
@Cacheable(cacheNames = "products", key = "#searchKeyword")
public void sendSlackMessage(String searchKeyword) {
    log.info(">>> [After] Slackbot message caching");
    try {
        ...
        Slack.chatPostMessage(request);
        ...
    } catch (SlackApiException | IOException exception) {
        log.error("Slack Error : {}", exception.getMessage());
        throw new BusinessException(SlackErrorCode.SLACK_ERROR);
    }
}

์ด์ œ ๋ฌธ์ œ์ ์„ ๋ชจ๋‘ ํ•ด๊ฒฐํ–ˆ์œผ๋‹ˆ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ, ์บ์‹ฑ์ด ์ž˜ ๋˜๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ ํ‚ค์›Œ๋“œ๋กœ API ์š”์ฒญ์„ 2๋ฒˆ ๋ณด๋ƒˆ์„ ๋•Œ ๋กœ๊ทธ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค.

์บ์‹œ๊ฐ€ ์ œ๋Œ€๋กœ ๋™์ž‘ํ–ˆ๋‹ค๋ฉด ์ตœ์ดˆ ํ•œ ๋ฒˆ๋งŒ >>> [After] Slackbot message caching ๋กœ๊ทธ๊ฐ€ ์ถœ๋ ฅ ๋ผ์•ผ ํ•˜์ง€๋งŒ, ๋‘ ๋ฒˆ์งธ ํ˜ธ์ถœ์—๋„ ๋กœ๊ทธ๊ฐ€ ์ถœ๋ ฅ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ ์บ์‹œ๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์„๊นŒ์š”?

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„  Spring AOP์˜ self invocation ์— ๋Œ€ํ•ด ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

์„ธ ๋ฒˆ์งธ ์‹œ๋„

์„ธ ๋ฒˆ์งธ ์‹œ๋„ ์ „์— self invocation ์ด ๋ฌด์—‡์ธ์ง€ ๊ฐ„๋‹จํžˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Self invocation ์ด๋ž€?

์ปจํŠธ๋กค๋Ÿฌ ๋‹จ์—์„œ proxyCall() ์ด๋ž€ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋‚ด๋ถ€์—์„œ selfInvocation() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰ ๋™์ผํ•œ ๊ฐ์ฒด ๋‚ด์—์„œ ์ž์‹  ์™ธ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ self-invocation์ด๋ผ ๋ถ€๋ฅด๋Š”๋ฐ, Proxy์—์„œ๋Š” ์ด๋Ÿฌํ•œ self-invocation์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

 

Spring AOP

Spring AOP๋Š” @Cacheable ์ด ์ ์šฉ๋œ ๋ฉ”์„œ๋“œ๋ฅผ ์บ์‹ฑํ•˜๊ธฐ ์œ„ํ•ด ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€์˜ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ•๋‹ˆ๋‹ค. Proxy๋ฅผ ํ†ตํ•ด ๋“ค์–ด์˜ค๋Š” ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๋งŒ ์ธํ„ฐ์…‰ํŠธํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋™์ผ ํด๋ž˜์Šค ๋‚ด๋ถ€(this)์—์„œ ์ ‘๊ทผ๋œ ๊ฒฝ์šฐ๋Š” ์บ์‹œ๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ •๋ฆฌํ•˜์ž๋ฉด Spring AOP๋Š”@Cacheable์˜ ๋™์ž‘์„ ์œ„ํ•ด ์™ธ๋ถ€์˜ ์š”์ฒญ์„ ์ธํ„ฐ์…‰ํŠธํ•˜์—ฌ ์บ์‹ฑํ•˜์ง€๋งŒ, ๋‚ด๋ถ€ ํ˜ธ์ถœ์€ proxy ๊ฐ€ ์•„๋‹Œ ์‹ค์ œ ๊ฐ์ฒด๊ฐ€ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— Spring AOP ๊ฐ€ ์บ์‹ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ฒซ ๋ฒˆ์งธ ์‹œ๋„์—์„œ๋Š” ์บ์‹œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ–ˆ์ฃ . getProductOfReview() ๋ฉ”์„œ๋“œ๋Š” ์ปจํŠธ๋กค๋Ÿฌ์—์„œ (์™ธ๋ถ€) ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋‘ ๋ฒˆ์งธ ์‹œ๋„์—์„  ์บ์‹œ๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜๋Š”๋ฐ, sendSlackMessage() ๋ฉ”์„œ๋“œ๊ฐ€ ์™ธ๋ถ€์—์„œ ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ณ  getProductOfReview() ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ๋๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ฆ‰ Self-invocation ๋์Šต๋‹ˆ๋‹ค.

 

self-invocation ์—์„  ์™œ @Cacheable ์ด ๋™์ž‘ํ•˜์ง€ ์•Š์„๊นŒ์š”? Spring AOP๋Š” ์บ์‹ฑ์„ ์œ„ํ•ด proxy ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ ํ›„ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜์ง€๋งŒ, self-invocation ๋ฉ”์„œ๋“œ๋Š” proxy ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ์‹ค์ œ ๊ฐ์ฒด(this)๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

Self-Invocation ํ•ด๊ฒฐ ๋ฐฉ์•ˆ (Proxy ์ƒ์„ฑ)

๋‚ด๋ถ€ ํ˜ธ์ถœ ์‹œ์—๋„ this ๊ฐ€ ์•„๋‹Œ proxy๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, proxy์— ์บ์‹ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ฆ‰ @Cacheable sendSlackMessage() ๋ฉ”์„œ๋“œ๋ฅผ self-invocation ์ด ์•„๋‹Œ proxy ๊ฐ์ฒด๋กœ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ,

1) ApplicationContext์—์„œ ๋™์ผํ•œ ํด๋ž˜์Šค์˜ proxy bean์„ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜

2) @Resource ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ self-autowiring ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1) ApplicationContext DI

getSpringProxy() ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ applicationContext.getBean(ReviewProductService.class)๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด getBean()์˜ ์ธ์ž์™€ ๋™์ผํ•œ ํƒ€์ž…์˜ Bean ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ฆ‰ getBean() ์˜ ์ธ์ž๊ฐ€ ReviewProductService ํƒ€์ž…์˜ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ผ๋ฉด, ๋™์ผํ•˜๊ฒŒ ReviewProductService ํƒ€์ž…์˜ ํ”„๋ก์‹œ๊ฐ€ ๋ฆฌํ„ด๋˜๋Š” ๊ฑฐ์ฃ .

ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ sendSlackMessage()๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋จ์œผ๋กœ, @Cacheable ์ด ์ ์šฉ๋œ sendSlackMessage()๋Š” ์ •์ƒ์ ์œผ๋กœ ์บ์‹œ ์ฒ˜๋ฆฌ ๋ฉ๋‹ˆ๋‹ค.

 

getBean() ์˜ ์ •์˜
getSpringProxy() ์˜ ๋ฆฌํ„ดํƒ€์ž…์€ CGLIB ํ”„๋ก์‹œ์ธ ๊ฒƒ์„ ๋””๋ฒ„๊ทธ๋กœ ํ™•์ธ

ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ sendSlackMessage() ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋จ์œผ๋กœ, @Cacheable ์ด ์ ์šฉ๋œ sendSlackMessage() ๋Š” ์ •์ƒ์ ์œผ๋กœ ์บ์‹œ ์ฒ˜๋ฆฌ ๋ฉ๋‹ˆ๋‹ค.

 

2) @Resource์œผ๋กœ AutoWiring

์Šคํ”„๋ง 4.3๋ถ€ํ„ด @Resource ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ self autowiring์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 1)์˜ ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ ApplicationContext๋ฅผ ํ†ตํ•ด Bean์„ ๊ฐ€์ ธ์˜ฌ ํ•„์š”์—†์ด ๊ฐ„๋‹จํžˆ ์ž์‹ ์˜ Bean ์„ ์ฃผ์ž…๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์ด๋ ‡๊ฒŒ ํ•˜์—ฌ API์˜ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋งŒ์กฑํ•˜๋Š” ๋™์‹œ์— ์Šฌ๋ž™๋ด‡์€ ํ•œ ๋ฒˆ๋งŒ ์ „์†ก๋˜๋„๋ก API๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

๋งˆ๋ฌด๋ฆฌ

๋ฌด์‹ฌ์ฝ” ์‚ฌ์šฉํ•œ @Cacheable ์–ด๋…ธํ…Œ์ด์…˜์—๋„ ์ˆ˜๋งŽ์€ ์›๋ฆฌ์™€ ์ด์œ ๊ฐ€ ์žˆ์Œ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์บ์‹œ ์ ์šฉ์ด๋ผ ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ๊ทธ ์†์—์„œ Self Invocation๊ณผ Spring AOP, Proxy๋ผ๋Š” ๋‹ค์†Œ ๋ณต์žกํ•œ ๊ฐœ๋…์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.