์Šคํ”„๋ง ๊ธฐ๋ณธ ๋ณต์Šต 3 - ๋นˆ ์Šค์ฝ”ํ”„์™€ ์ƒ๋ช…์ฃผ๊ธฐ

1. ๊ฐœ์š”

์•ž์„œ ์Šคํ”„๋ง์ด ๋งŽ์€ ๊ฐ์ฒด๋“ค์„ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•˜์—ฌ ํ•„์š”ํ•œ ์‹œ์ ์— ์ œ๊ณตํ•œ๋‹ค๊ณ  ํ•™์Šตํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋นˆ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์€, ๋ฆฌ์†Œ์Šค๋ฅผ ์ ์œ ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๊ธฐ๋„ ํ•˜๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์œ ์ง€ํ•ด์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ์„๊นŒ?

๊ทธ๋ฆฌ๊ณ  ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ์†Œ๋ฉธ๋˜๋Š” ์ˆœ๊ฐ„์— ํ•„์š”ํ•œ ๋™์ž‘๋“ค(์˜ˆ: ์ปค๋„ฅ์…˜ ์—ฐ๊ฒฐ ๋“ฑ)์€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃจ์–ด์•ผ ํ• ๊นŒ?

๋งŒ์•ฝ ์„œ๋น„์Šค๋ฅผ ๊ฐœ๋ฐœํ•˜๋˜ ๋„์ค‘, ์„œ๋ฒ„๋กœ ์˜ค๋Š” ํŠน์ • API์— ๋Œ€ํ•ด UUID์™€ ์š”์ฒญ URL์„ ๋กœ๊น…ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์•ž์„  ๋‚ด์šฉ์„ ๊ณต๋ถ€ํ•ด๋ณด๋„๋ก ํ•˜์ž.

 

2. ๋นˆ ์Šค์ฝ”ํ”„

Hello ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ€์ƒ์˜ ์•„์ฃผ์•„์ฃผ ์ค‘์š”ํ•œ(…!) API ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž. ํ•ด๋‹น API ์˜ ์š”์ฒญ ์ปจํŠธ๋กค๋Ÿฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

@RestController
@RequestMapping("/hello")
public class HelloController {

    @GetMapping
    public ResponseEntity<String> hello() {
                //์•„์ฃผ ์ค‘์š”ํ•œ ๋กœ์ง
                //...
        return ResponseEntity.ok("Hello");
    }
}

 

๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ ๋กœ๊น…์ด ์‹คํ–‰ ๋  ๋นˆ์„ ์ƒ์„ฑํ•œ ํ›„ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•œ๋‹ค.

@Component
public class MyLogger {

    private String uuid;
    private HttpServletRequest request;

    public void setRequest(HttpServletRequest request) {
        this.request = request;
    }

    public void setUuid() {
        this.uuid = UUID.randomUUID().toString();
    }

    public void log() {
        System.out.printf("[%s] %s\\n", uuid, request.getRequestURL().toString());
    }

}

 

ํ•ด๋‹น ๋กœ๊ฑฐ๋ฅผ ๋“ฑ๋กํ•  ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

@Component
public class HelloInterceptor implements HandlerInterceptor {

    private final MyLogger myLogger;

    public HelloInterceptor(MyLogger myLogger) {
        this.myLogger = myLogger;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
                            Object handler) throws Exception {
        myLogger.setRequest(request);
        myLogger.setUuid();
        myLogger.log();
        return true;
    }
}

 

๋งˆ์ง€๋ง‰์œผ๋กœ ํ•ด๋‹น ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ๋“ฑ๋กํ•œ๋‹ค.

@Component
public class HelloConfigurer implements WebMvcConfigurer {

    private final HelloInterceptor helloInterceptor;

    public HelloConfigurer(HelloInterceptorhelloInterceptor) {
        this.helloInterceptor = helloInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistryregistry) {
        registry.addInterceptor(helloInterceptor)
        .addPathPatterns("/hello");
    }
}

 

์—ฌ๊ธฐ๊นŒ์ง€ ์ž‘์„ฑํ•œ ํ›„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ฉด ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ MyLogger ๊ฐ€ ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•˜๊ณ  ์žˆ๋Š” ๋“ฏ ๋ณด์ธ๋‹ค..!!!

 

Hello API ์— ๋Œ€ํ•œ ๋กœ๊น… ํ…Œ์ŠคํŠธ

 

ํ•˜์ง€๋งŒ ์ด ๋กœ๊ฑฐ๋Š” ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์น˜๋ช…์ ์ธ ๋ฌธ์ œ์ ์ด ๋ช‡๊ฐ€์ง€ ์กด์žฌํ•œ๋‹ค.

 

1. ์‚ฌ์šฉํ•˜์ง€ ์•Š์„๋•Œ๋„ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ์œ ์ค‘์ด๋‹ค.

2. Thread Safe ํ•˜์ง€ ์•Š๋‹ค.

 

์ž˜ ๋ณด๋ฉด ๋กœ๊ฑฐ์— request ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •๊ณผ ์‹ค์ œ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๊ณผ์ • ์‚ฌ์ด์— ์„œ๋กœ ๋‹ค๋ฅธ ์œ ์ €๊ฐ€ ์ „์—ญ ๋ณ€์ˆ˜(request, uuid) ์— ๊ฐ„์„ญ์„ ์ผ์œผํ‚ฌ ์—ฌ์ง€๊ฐ€ ์ถฉ๋ถ„ํ•˜๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ํ•ด๋‹น ๋กœ๊ฑฐ๊ฐ€ ํ•˜๋‚˜์˜ Request ์— ๋Œ€ํ•ด ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํ•ด๋‹น ์š”์ฒญ์ด ๋๋‚œ ํ›„ ์‚ฌ๋ผ์ง„๋‹ค๋ฉด ์œ„์˜ ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ๋™์‹œ์— ํ•ด๊ฒฐ ๋œ๋‹ค.

 

์ด๋ฅผ ์œ„ํ•œ ๊ธฐ๋Šฅ์ด ๋ฐ”๋กœ Bean Scope ์ด๋‹ค.

 

Bean Scope ๋Š” ์Šคํ”„๋ง ๋นˆ์ด ์Šคํ”„๋ง ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ์ƒ์„ฑ๋˜๊ณ  ์‚ฌ๋ผ์ง€๋Š” ์ผ์ข…์˜ ์ƒ๋ช…์ฃผ๊ธฐ์ธ๋ฐ ๋‹ค์Œ๊ณผ ์˜ต์…˜๋“ค์ด ์žˆ๋‹ค.

์Šค์ฝ”ํ”„

  • ์‹ฑ๊ธ€ํ†ค : ์Šคํ”„๋ง ๊ธฐ๋ณธ ์Šค์ฝ”ํ”„. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์‹œ์ž‘๊ณผ ์ข…๋ฃŒ๊นŒ์ง€ ํ•จ๊ป˜ํ•˜๋Š” ๊ฐ€์žฅ ๋„“์€ ๋ฒ”์œ„์ด๋‹ค.
  • ํ”„๋กœํ† ํƒ€์ž… : ๋นˆ์˜ ์ƒ์„ฑ๊ณผ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…๊นŒ์ง€๋งŒ ๊ด€์—ฌํ•˜๊ณ  ๊ทธ ํ›„์—๋Š” ๋”์ด์ƒ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ์›น ๊ด€๋ จ ์Šค์ฝ”ํ”„๋“ค
    • request : ์›น ์š”์ฒญ๊ณผ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ™์ด ํ•˜๋Š” ์Šค์ฝ”ํ”„์ด๋‹ค.
    • session : ์›น ์„ธ์…˜๊ณผ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ™์ด ํ•˜๋Š” ์Šค์ฝ”ํ”„์ด๋‹ค.
    • application : ์›น ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์™€ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ™์ด ํ•˜๋Š” ์Šค์ฝ”ํ”„์ด๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ MyLogger ํด๋ž˜์Šค์— request ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•˜์—ฌ ์š”์ฒญ๊ณผ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๋™์ผํ•˜๊ฒŒ ๋งž์ถ”์–ด ๋ณด์ž.

์Šค์ฝ”ํ”„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

@Component
@Scope(value = "request")
public class MyLogger {
        // ...

์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•œ ํ›„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ธฐ๋™ํ•˜๋ฉด ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ ์—๋Ÿฌ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜๋ฉด์„œ ๊ธฐ๋™์กฐ์ฐจ ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋•Œ ์ถœ๋ ฅ๋˜๋Š” ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Error creating bean with name 'myLogger': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;

์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ๋ช…์‹œ์ ์ธ ์ˆ˜์ค€์„ ๋„˜์–ด์„œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๊นŒ์ง€ ๋ชจ๋‘ ์ œ์‹œํ•ด์ฃผ๊ณ  ์žˆ๋‹ค ๐Ÿ˜‚

 

์—๋Ÿฌ๋ฉ”์‹œ์ง€๋Š” MyLogger ๋นˆ์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ํ•„์š”๋กœ ํ•˜๋Š” HelloIntercepter ๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•œ๋‹ค.

 

HelloIntercepter๊ฐ์ฒด๋Š” ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„์ด๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์‹œ์  (์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ธฐ๋™ ์‹œ์ ) ์— ์ƒ์„ฑ๋˜๊ณ  ์˜์กด์„ฑ์„ ์ฃผ์ž…๋ฐ›์•„์•ผ ํ•˜๋Š”๋ฐ MyLogger ํด๋ž˜์Šค๋Š” request ์Šค์ฝ”ํ”„์ด๊ธฐ ๋•Œ๋ฌธ์— ์š”์ฒญ์ด ์˜ฌ๋•Œ๊นŒ์ง€ ์ƒ์„ฑ์ด ๋  ์ˆ˜ ์—†๋‹ค.

 

์ฆ‰ ๋‘ ํ˜‘๋ ฅ๊ฐ์ฒด์˜ ์ƒ๋ช…์ฃผ๊ธฐ์˜ ๋ถˆ์ผ์น˜๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ธ๋ฐ ์ด ๋•Œ ํ•„์š”ํ•œ ๊ฒƒ์ด ๋ฐ”๋กœ ์•ž์—์„œ๋„ ๋‹ค๋ฃจ์—ˆ๋˜ ํ”„๋ก์‹œ ๊ฐ์ฒด์ด๋‹ค.

 

MyLogger๊ฐ์ฒด๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ€์งœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ HelloIntercepter ๊ฐ์ฒด์— ์ฃผ์ž…ํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ต์…˜ ํ•˜๋‚˜๋กœ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ง€์ • ๊ฐ€๋Šฅํ•˜๋‹ค.

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {
        //...

 

๊ทธ๋ฆฌ๊ณ  ์ถ”๊ฐ€์ ์œผ๋กœ HelloIntercepterํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์—๋„ MyLogger ์˜ ํด๋ž˜์Šค๋ฅผ ์ถœ๋ ฅ ํ•ด๋ณด์ž.

public HelloInterceptor(MyLogger myLogger) {
        this.myLogger = myLogger;
        System.out.println(myLogger.getClass());
}

 

Hello Interceptor ์˜ ์˜์กด์„ฑ ์ฃผ์ž… ๋กœ๊ทธ

 

 

๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ๋‹ค๋ฅธ ํ”„๋ก์‹œ ๊ฐ์ฒด๋“ค๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ”„๋ก์‹œ ๊ฐ์ฒด ์ƒ์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ CGLIB ๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์šฐ๋ฆฌ๊ฐ€ ์š”๊ตฌ์‚ฌํ•ญ๋Œ€๋กœ ๋งŒ๋“  ์‹ ๊ทœ ๋กœ๊น… ๊ธฐ๋Šฅ์ด ์ž˜ ๋™์ž‘ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

 

3. ๋นˆ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ

์•ž์„œ ๋งŒ๋“  ๋กœ๊น… ๊ธฐ๋Šฅ์€ ํ˜„์žฌ ๋งŒ์กฑ์Šค๋Ÿฝ๊ฒŒ ์ž‘๋™ํ•˜๊ณ  ์žˆ๋Š” ๋“ฏ ๋ณด์ธ๋‹ค. ํ•˜์ง€๋งŒ ์•„์ง ๋งˆ์Œ์— ๋“ค์ง€ ์•Š๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค.

๋ฐ”๋กœ ๊ฐœ๋ณ„ ์š”์ฒญ์— ๋Œ€ํ•œ UUID ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ฒ˜๋ฆฌ๋ฅผ ๋ณ„๋„๋กœ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

 

๋กœ๊ฑฐ ํด๋ž˜์Šค๊ฐ€ ๋ชจ๋“  Request ์— ๋Œ€ํ•ด ์ƒ์„ฑ๋˜๊ณ  ์‚ฌ๋ผ์ง„๋‹ค๋ฉด, ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์‹œ์ ์— UUID ๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ?

๊ทธ๋ฆฌ๊ณ  ๊ฐ์ฒด๊ฐ€ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ œ๊ฑฐ๋˜๋Š” ์‹œ์ ์— ํŠน์ • ๋™์ž‘(์˜ˆ: ํŒŒ์ผ ๊ธฐ๋ก ๋“ฑ)์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?

 

๋นˆ์ด ์ƒ์„ฑ๋˜๊ณ  ์ œ๊ฑฐ๋  ๋•Œ @PostConstruct ๋ฐ @PreDestroy ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๋‹น ์• ๋…ธํ…Œ์ด์…˜์„ ์ ์šฉํ•˜์—ฌ Logger ํด๋ž˜์Šค๋ฅผ ๊ฐœ์„ ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {

    private String uuid;
    private String log;
    private HttpServletRequest request;

    public void setRequest(HttpServletRequest request) {
        this.request = request;
    }

    public void log() {
        log = String.format("[%s] %s\\n", uuid, request.getRequestURL().toString());
        System.out.print(log);
    }

    @PostConstruct
    private void init() {
        uuid = UUID.randomUUID().toString();
    }

    @PreDestroy
    private void close() {
        try {
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("log.txt", true));
            bos.write(log.getBytes());
            bos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    }

 

์œ„์˜ ์˜ˆ์ œ์—์„œ ๋นˆ ์ƒ์„ฑ์‹œ์  (@PostConstruct ์‚ฌ์šฉ ์‹œ์ ) ์— ์ผ์–ด๋‚˜๋Š” ๋กœ์ง์€ ์‚ฌ์‹ค ์ƒ์„ฑ์ž์—์„œ ๋Œ€์ฒด ๋˜์–ด๋„ ๋ฌด๊ด€ํ•˜๋‹ค.

ํ•˜์ง€๋งŒ ์Šคํ”„๋ง์ด ์ฃผ์ž…ํ•ด์•ผ ํ•˜๋Š” ์˜์กด์„ฑ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด ์ƒ์„ฑ์ž์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.

์Šคํ”„๋ง์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ๋นˆ์˜ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค

  1. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ
  2. ์Šคํ”„๋ง ๋นˆ ์ƒ์„ฑ : ์ƒ์„ฑ์ž ๋™์ž‘
  3. ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…
  4. ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ : PostConstruct ๋™์ž‘
  5. ์‚ฌ์šฉ : ์œ„ ์˜ˆ์ œ์—์„  request ๋ฐœ์ƒ ์‹œ์ 
  6. ์†Œ๋ฉธ์ „ ์ฝœ๋ฐฑ : PreDestory ๋™์ž‘
  7. ์ข…๋ฃŒ

๊ทธ๋ฆฌ๊ณ  ์ฃผ์ž… ๋œ ์˜์กด์„ฑ์„ ํ™œ์šฉํ•˜์—ฌ ์™ธ๋ถ€ ์ปค๋„ฅ์…˜ ์—ฐ๊ฒฐ๊ณผ ๊ฐ™์€ ๋ฌด๊ฑฐ์šด ๋™์ž‘์„ ์ฒ˜๋ฆฌ ํ•˜๋Š” ๊ฒƒ์€ ์ƒ์„ฑ์ž์—์„œ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋ณด๋‹ค 4๋ฒˆ์˜ ์ดˆ๊ธฐํ™” ์‹œ์ ์— ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ ์œ ๋ฆฌํ•˜๋‹ค.

 

์ดˆ๊ธฐํ™”์™€ ์†Œ๋ฉธ ์ฝœ๋ฐฑ์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์œ„ ์• ๋…ธํ…Œ์ด์…˜ ์™ธ์—๋„ ๋‹ค์Œ ๋ฐฉ๋ฒ•๋„ ํ™œ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

- InitializingBean , DisposableBean ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์† (์Šคํ”„๋ง ์ „์šฉ)

- ๋นˆ ๋“ฑ๋ก ์ดˆ๊ธฐํ™” ์†Œ๋ฉธ ๋ฉ”์„œ๋“œ ์ง€์ • @Bean(initMethod = "init", destroyMethod = "close") ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋นˆ ์‚ฌ์šฉ์‹œ ํ™œ์šฉ

 

4. ์ •๋ฆฌ

์•ž์„œ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ง€์›ํ•˜๋Š” ํŠน์ˆ˜ํ•œ ์ƒ๋ช…์ฃผ๊ธฐ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜๋‹ค.

ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฐ์ฒด๋“ค์€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์™€ ๋™์ผํ•œ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง€๋Š”๊ฒŒ ์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ ์ข‹๋‹ค.

๋ช…ํ™•ํ•˜๊ฒŒ ์ƒ๋ช…์ฃผ๊ธฐ๊ฐ€ ์ •ํ•ด์ ธ์žˆ๊ณ , ์ž์ฃผ ํ˜ธ์ถœ๋˜์ง€ ์•Š์„ ๋งŒํ•œ ๋กœ์ง์—๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๋“ฏ ํ•˜๋‹ค.