์Šคํ”„๋ง ์ˆœํ™˜์ฐธ์กฐ ๋ฌธ์ œ

์Šคํ”„๋ง์œผ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค๋ณด๋ฉด ์—ฌ๋Ÿฌ ๋นˆ๋“ค์˜ ์ˆœํ™˜์ฐธ์กฐ๋กœ ์ธํ•ด ์•ฑ ๊ธฐ๋™์ด ์•ˆ๋˜๋Š” ์ƒํ™ฉ์— ์ข…์ข… ๋งž๋”ฑ๋“œ๋ฆฌ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ตœ๊ทผ์— ์  ํ‚จ์Šค๋กœ ๋นŒ๋“œํ•œ ์•ฑ์ด ์ˆœํ™˜์ฐธ์กฐ ๋ฌธ์ œ๋กœ ์ธํ•ด ์ •์ƒ์ ์œผ๋กœ ๊ธฐ๋™์ด ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์›ƒ๊ธด๊ฑด ๋กœ์ปฌํ™˜๊ฒฝ์—์„œ๋Š” ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ์—†์ด ์ž˜ ๋Œ์•„๊ฐ„๋‹ค๋Š” ๊ฒƒ์ด์—ˆ์ฃ . ๊ฒฐ๊ตญ ๋‹ด๋‹น์ž์˜ ํ™•์ธํ•˜์— ์  ํ‚จ์Šค์˜ ํŒŒ์ดํ”„๋ผ์ธ ์˜ต์…˜ ์„ค์ •์œผ๋กœ ํ•ด๊ฒฐ์€ ํ–ˆ์Šต๋‹ˆ๋‹ค๋งŒ, setter injection (field injection) ์ด๋ผ๋„ ์ˆœํ™˜์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋””์ž์ธ์€ ์ข‹์ง€ ์•Š์ฃ . ๊ทธ๋ž˜์„œ ๊ด€๋ จ๋‚ด์šฉ์„ ์•Œ์•„๋ณด๋‹ค๊ฐ€ ๋„์ ์—ฌ๋ด…๋‹ˆ๋‹ค.

์ˆœํ™˜์ฐธ์กฐ๋ž€? (What is Circular Reference ? )

์ˆœํ™˜์ฐธ์กฐ๋ž€ ์„œ๋กœ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ๋นˆ๋“ค์ด ์„œ๋กœ ๋ฌผ๊ณ ๋Š˜์–ด์ ธ์„œ ๊ณ„์† ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์•„๋ž˜์ฒ˜๋Ÿผ A๋Š” B์—์„œ ํ•„์š”ํ•œ๋ฐ B๋Š” ๋˜ A์—์„œ ํ•„์š”ํ•œ ์ƒํƒœ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค.

Bean A → Bean B → Bean A

 

๋งŒ์•ฝ Bean A -> Bean B -> Bean C ์ฒ˜๋Ÿผ ์—ฐ๊ฒฐ๋˜์–ด์žˆ๋‹ค๋ฉด ์Šคํ”„๋ง์€ A๋ฅผ ๋จผ์ € ๋งŒ๋“ค๊ณ  A๋ฅผ ํ•„์š”๋กœ ํ•˜๋Š” B๋ฅผ ๋งŒ๋“ค๊ณ  B๋ฅผ ํ•„์š”๋กœ ํ•˜๋Š” C๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ˆœํ™˜์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์Šคํ”„๋ง์€ ์–ด๋Š ๋นˆ์„ ๋จผ์ € ์ƒ์„ฑํ•ด์•ผํ• ์ง€ ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ๋˜๊ณ  ์ˆœํ™˜์ฐธ์กฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ˆœํ™˜์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋Š”๊ฑด ๊ฒฐ๊ตญ ์„ค๊ณ„๊ฐ€ ์ž˜๋ชป๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋ ‡๋‹ค๊ณ  ์„ค๊ณ„๋ฅผ ๋‹ค ๋œฏ์–ด๊ณ ์น˜์ž๋‹ˆ ๋น„์šฉ์ด ๋„ˆ๋ฌด ๋งŽ์ด ๋“ค์–ด๊ฐˆ ์ˆ˜๋„ ์žˆ์ฃ . ์ˆœํ™˜์ฐธ์กฐ ์˜ค๋ฅ˜๋Š” ์ฐธ๊ณ ๋กœ ์Šคํ”„๋ง์˜ ์˜์กด์„ฑ ์ฃผ์ž…๋ฐฉ๋ฒ• ์ค‘์—์„œ๋„ ํŠนํžˆ ์ƒ์„ฑ์ž ์ฃผ์ž…๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋นˆ ์ƒ์„ฑ์‹œ ํ•„์š”ํ•œ ๋‹ค๋ฅธ ๋นˆ์ด ์„œ๋กœ ๋ฌผ๊ณ ๋Š˜์–ด์ ธ ์žˆ์œผ๋‹ˆ ์–ด๋–ค ๋นˆ๋„ ์ƒ์„ฑ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ์ƒํ™ฉ์ด ๋˜์–ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด์ฃ .

์ˆœํ™˜์ฐธ์กฐ ๋ฌธ์ œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

์ˆœํ™˜์ฐธ์กฐ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•ด์ฃผ๋Š”๊ฒŒ ์ œ์ผ ์ข‹๊ธด ํ•˜์ง€๋งŒ ์–ด์ฉ” ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์€ ๊ผญ ์ƒ๊ธฐ๊ธฐ ๋งˆ๋ จ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ์ˆœํ™˜์ฐธ์กฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? ๊ฐ€์žฅ ์šฐ์„ ์‹œ ํ•ด์•ผํ•  ๊ฒƒ์€ ์ˆœํ™˜์ฐธ์กฐ์˜ ๊ณ ๋ฆฌ๋ฅผ ๋Š์–ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์Šคํ”„๋ง์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ฉฐ ์„ค๊ณ„๋ฅผ ์กฐ๊ธˆ๋งŒ ๋ฐ”๊ฟ”์„œ ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๊ฐ€ ์ด์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋งŒ์•ฝ ์„ค๊ณ„์˜ ๋ณ€๊ฒฝ์ด ํž˜๋“  ๊ฒฝ์šฐ๋ผ๋ฉด @Lazy ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉ ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค ๋ผ๊ณ  ์–˜๊ธฐํ•œ ์ด์œ ๋Š” ์•„๋ž˜์— ๋‚˜์˜ต๋‹ˆ๋‹ค)

@Component
public class BeanA {

    private BeanB beanB;

    @Autowired
    public BeanA(BeanB beanB) {
        this.beanB = beanB;
    }
}

 

์ด๋ ‡๊ฒŒ ๋˜์–ด์žˆ๋˜ ์ฝ”๋“œ๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ฒƒ์ด์ฃ .

@Component
public class BeanA {

    private BeanB beanB;

    @Autowired
    public BeanA(@Lazy BeanB beanB) {
        this.beanB = beanB;
    }
}

 

ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Lazy initialization ์— ๋Œ€ํ•œ ๋ฌธ์ œ๋Š” Spring ๊ณต์‹๋ฌธ์„œ(Lazy Initialization)๋ฅผ ์ฐธ๊ณ ํ•˜์‹œ๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํžˆ ๋ง์”€๋“œ๋ฆฌ๋ฉด ์•ฑ ๊ธฐ๋™์‹œ์ ์ด ์•„๋‹Œ ์‹ค์ œ ํ•ด๋‹น ๋นˆ์ด ํ•„์š”ํ•œ ์‹œ์ ์— ๋นˆ์„ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŠน์ • http ์š”์ฒญ์„ ๋ฐ›์•˜์„ ๋•Œ ํž™๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์€ ์ƒํ™ฉ์ด์—ˆ๋‹ค๋ฉด ์žฅ์• ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ์–˜๊ธฐ์ฃ . ์•„๋ฌดํŠผ ์Šคํ”„๋ง์—์„œ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์ด๋‹ˆ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. 

 

๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ์ƒ์„ฑ์ž ์ฃผ์ž…๋ฐฉ๋ฒ• ๋Œ€์‹ ์— setter ์ฃผ์ž…๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์•„๋ž˜ setter ์ฃผ์ž… ์˜ˆ์ œ๋ฅผ ํ•œ๋ฒˆ ๋ณด์‹œ์ฃ .

@Component
public class BeanA {

    private BeanB beanB;

    @Autowired
    public void setBeanB(BeanB beanB) {
        this.beanB = beanB;
    }

    public BeanB getBeanB() {
        return beanB;
    }
}

@Component
public class BeanB {

    private BeanA beanA;

    @Autowired
    public void setBeanA(BeanA beanA) {
        this.beanA = beanA;
    }
}

 

 

ํ˜น์‹œ๋‚˜ ์ฃผ์ž…๋ฐฉ๋ฒ•์— ๋‹ค์‹œ ํ•œ๋ฒˆ ์งš๊ณ  ๋„˜์–ด๊ฐ€๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด ์Šคํ”„๋ง ์˜์กด์„ฑ ์ฃผ์ž… ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

 

Conclusion

์Šคํ”„๋ง์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค๊ฐ€ ์ˆœํ™˜์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ๊ฐ€์žฅ ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์€ ์ˆœํ™˜์ฐธ์กฐ์˜ ์—ฐ๊ฒฐ๊ณ ๋ฆฌ๋ฅผ ๋Š์–ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด๋ฉฐ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ๊น”๋”ํ•˜๊ฒŒ ์„ค๊ณ„๋œ ๋””์ž์ธ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šคํ”„๋ง์—์„œ๋„ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ์‹์ด์ฃ . ๊ทธ๋ž˜์„œ setter์ฃผ์ž…์ด ์•„๋‹Œ ์ƒ์„ฑ์ž ์ฃผ์ž…๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. ์šฐํšŒ์ ์œผ๋กœ ์ˆœํ™˜์ฐธ์กฐ๋ฅผ ์ž ์‹œ ํ”ผํ•œ๋‹ค ํ•˜๋”๋ผ๋„ ์–ธ์ œ ๋˜ ๋˜‘๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ• ์ง€ ์•„๋ฌด๋„ ์•Œ ์ˆ˜ ์—†์œผ๋ฉฐ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ(lazy initialization์˜ ๊ฒฝ์šฐ) ํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๊ธ‰์  ์ˆœํ™˜์ฐธ์กฐํ•ด์•ผํ•˜๋Š” ์„ค๊ณ„๋Š” ํ”ผํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

 

Reference

- www.baeldung.com/circular-dependencies-in-spring 

- docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependencies