be_better

[Springboot] μŠ€ν”„λ§ λΆ€νŠΈλž€? λ³Έλ¬Έ

Springboot/이둠

[Springboot] μŠ€ν”„λ§ λΆ€νŠΈλž€?

NiceTry 2023. 10. 19. 03:19

λͺ©μ°¨

     πŸƒ μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬

    μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬(Spring Framework)λŠ” μžλ°”(Java) 기반의 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ ˆμž„μ›Œν¬μ΄λ‹€.

    μŠ€ν”„λ§μ€ λͺ©μ μ— 따라 λ‹€μ–‘ν•œ ν”„λ‘œμ νŠΈλ₯Ό μ œκ³΅ν•˜λŠ”λ°, 그쀑 ν•˜λ‚˜κ°€ μŠ€ν”„λ§ λΆ€νŠΈ(Spring Boot)이닀.

     

    μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λŠ” μžλ°”μ—μ„œ κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬λ‘œ, μ—”ν„°ν”„λΌμ΄μ¦ˆκΈ‰ κ°œλ°œμ„ νŽΈλ¦¬ν•˜κ²Œ λ§Œλ“€μ–΄μ£ΌλŠ” 'μ˜€ν”ˆμ†ŒμŠ€ κ²½λŸ‰κΈ‰ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ ˆμž„μ›Œν¬'둜 λΆˆλ¦°λ‹€.

    μ—”ν„°ν”„λΌμ΄μ¦ˆκΈ‰ κ°œλ°œμ΄λž€?
    λ„€μ΄λ²„λ‚˜ 카카였 같은 λŒ€κ·œλͺ¨ 데이터λ₯Ό μ²˜λ¦¬ν•˜λŠ” ν™˜κ²½μ„ μ—”ν„°ν”„λΌμ΄μ¦ˆ ν™˜κ²½μ΄λΌκ³  λΆ€λ₯Έλ‹€.

     

    μŠ€ν”„λ§μ˜ ν•΅μ‹¬κ°€μΉ˜λŠ” κ°œλ°œμžκ°€ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 κ΅¬ν˜„μ—λ§Œ 집쀑할 수 μžˆκ²Œλ” ν•˜λŠ” 것

     

    μ œμ–΄ μ—­μ „(IoC)

    일반적인 μžλ°” 개발의 경우 객체λ₯Ό μƒμ„±ν•˜κ³  μ‚¬μš©ν•˜λŠ” 일련의 μž‘μ—…μ„ κ°œλ°œμžκ°€ 직접 μ œμ–΄ν•˜λŠ” ꡬ쑰λ₯Ό κ°–λŠ”λ‹€.

    @RestController
    public class NoDIController {
        
        private MyService service = new MyService();
        
        @GetMapping("/no-di/hello")
        public String getHello() {
            return service.getHello();
        }
    }

     

    μ œμ–΄ μ—­μ „(IoC; Inversion of Control)을 νŠΉμ§•μœΌλ‘œ ν•˜λŠ” μŠ€ν”„λ§μ€ κΈ°μ‘΄ μžλ°” 개발 방식과 λ‹€λ₯΄κ²Œ λ™μž‘ν•œλ‹€.

    μ‚¬μš©ν•  객체λ₯Ό 직접 μƒμ„±ν•˜μ§€ μ•Šκ³  객체의 생λͺ…μ£ΌκΈ° 관리λ₯Ό 외뢀에 μœ„μž„ν•˜κ²Œ 되고 μ΄λ‘œμΈν•΄

    μ˜μ‘΄μ„± μ£Όμž…(DI; Dependency Injection), 관점 μ§€ν–₯ ν”„λ‘œκ·Έλž¨(AOP; Aspect-Oriented Programming) 이 κ°€λŠ₯ν•΄μ§„λ‹€.

    'μ™ΈλΆ€' λž€ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ(Spring Container) λ˜λŠ” IoC μ»¨ν…Œμ΄λ„ˆ(IoC Container)λ₯Ό μ˜λ―Έν•œλ‹€.

     

    μ˜μ‘΄μ„± μ£Όμž…(DI)

    μ˜μ‘΄μ„± μ£Όμž… μ΄λž€ μ™ΈλΆ€ μ»¨ν…Œμ΄λ„ˆκ°€ μƒμ„±ν•œ 객체λ₯Ό μ£Όμž…λ°›μ•„ μ‚¬μš©ν•˜λŠ” 방식을 μ˜λ―Έν•œλ‹€.

    μŠ€ν”„λ§μ—μ„œ μ˜μ‘΄μ„±μ„ μ£Όμž…λ°›λŠ” 방법은 μ„Έ κ°€μ§€κ°€ 있고, @Autowired λΌλŠ” μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 μ˜μ‘΄μ„±μ„ μ£Όμž…ν•  수 μžˆλ‹€.

     

    μƒμ„±μžλ₯Ό ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…

    @RestController
    public class DIController {
    
        MyService myService;
    
        @Autowired
        public DIController(MyService myService) {
            this.myService = myService;
        }
        
        @GetMapping("/di/hello")
        public String getHello() {
            return myService.getHello();
        }
    }

     

    ν•„λ“œ 객체 선언을 ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…

    @RestController
    public class FieldInjectionController {
    
        @Autowired
        private MyService myService;
        
    }

     

    setter λ©”μ„œλ“œλ₯Ό ν†΅ν•œ μ˜μ‘΄μ„± μ£Όμž…

    @RestController
    public class SetterInjectionController {
    
        MyService myService;
        
        @Autowired
        public void setMyService(MyService myService) {
            this.myService = myService;
        }
    
    }

     

    λ‹€λ₯Έ λ°©μ‹κ³ΌλŠ” λ‹€λ₯΄κ²Œ μƒμ„±μžλ₯Ό 톡해 μ˜μ‘΄μ„±μ„ μ£Όμž…λ°›λŠ” 방식은 레퍼런슀 객체 μ—†μ΄λŠ” 객체λ₯Ό μ΄ˆκΈ°ν™”ν•  수 μ—†κ²Œ 섀계할 수 있기 λ•Œλ¬Έμ— 제일 ꢌμž₯ν•˜λŠ” μ˜μ‘΄μ„± μ£Όμž… 방식이닀.

     

    관점 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°(AOP)

    관점 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°μ€ 객체 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°(OOP)λ₯Ό λ”μš± 잘 μ‚¬μš©ν•˜λ„λ‘ λ•λŠ” κ°œλ…μœΌλ‘œ λ³Έλ‹€.

     

    AOPλŠ” 관점을 κΈ°μ€€μœΌλ‘œ λ¬Άμ–΄ κ°œλ°œν•˜λŠ” 방식이닀. 관점(aspect)λž€ μ–΄λ–€ κΈ°λŠ₯을 κ΅¬ν˜„ν•  λ•Œ '핡심 κΈ°λŠ₯'κ³Ό 'λΆ€κ°€ κΈ°λŠ₯'으둜 ꡬ뢄해 각각을 ν•˜λ‚˜μ˜ κ΄€μ μœΌλ‘œ λ³΄λŠ” 것을 μ˜λ―Έν•œλ‹€.

     

    핡심 κΈ°λŠ₯은 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 μ²˜λ¦¬ν•˜λ €λŠ” λͺ©μ  κΈ°λŠ₯을 λ§ν•œλ‹€.

    λ‹€μ‹œλ§ν•΄ ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„° μš”μ²­μ„ λ°›μ•„ λ°μ΄ν„°λ² μ΄μŠ€μ— μ €μž₯ν•˜κ³ , μš”μ²­ν•œ 데이터λ₯Ό λ³΄μ—¬μ£ΌλŠ” 메인 κΈ°λŠ₯을 μ˜λ―Έν•œλ‹€.

     

    λΆ€κ°€ κΈ°λŠ₯은 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 사이에 λ‘œκΉ… 처리λ₯Ό ν•˜κ±°λ‚˜ νŠΈλžœμž­μ…˜μ„ μ²˜λ¦¬ν•˜λŠ” κΈ°λŠ₯ 등을 λœ»ν•œλ‹€.

     

    κΈ°μ‘΄ OOP λ°©μ‹μ—μ„œλŠ” κ°μ²΄λ§ˆλ‹€ 핡심기λŠ₯, λΆ€κ°€κΈ°λŠ₯ μ½”λ“œλ₯Ό μž‘μ„±ν•œλ‹€.

    μ΄λŸ¬ν•œ λ°©μ‹μ—μ„œλŠ” λΆ€κ°€κΈ°λŠ₯이 μ„œλ‘œ λ‹€λ₯Έ 핡심기λŠ₯λ“€μ—μ„œ λ™μΌν•œ κΈ°λŠ₯을 μˆ˜ν–‰ν•  ν™•λ₯ μ΄ λ†’λ‹€.

     

    AOP λ°©μ‹μ—μ„œλŠ” 핡심 κΈ°λŠ₯, λΆ€κ°€ κΈ°λŠ₯을 각각의 κ΄€μ μœΌλ‘œ 보기 λ•Œλ¬Έμ— λΆ„λ¦¬λ˜μ–΄μžˆλ‹€.

    λ™μΌν•œ κΈ°λŠ₯을 ν•˜λŠ” λΆ€κ°€ κΈ°λŠ₯을 λ”°λ‘œ 관리해 핡심 κΈ°λŠ₯이 μˆ˜ν–‰λ˜κΈ° μ „ λ˜λŠ” 후에 μˆ˜ν–‰λ˜κΈ°λ§Œ ν•˜λ©΄ λœλ‹€.

     

    AOPλ₯Ό κ΅¬ν˜„ν•˜λŠ” λ°©μ‹μ—λŠ” 크게 μ„Έ κ°€μ§€κ°€ μžˆλ‹€.

    • 컴파일 과정에 μ‚½μž…ν•˜λŠ” 방식
    • λ°”μ΄νŠΈμ½”λ“œλ₯Ό λ©”λͺ¨λ¦¬μ— λ‘œλ“œν•˜λŠ” 과정에 μ‚½μž…ν•˜λŠ” 방식
    • ν”„λ½μ‹œ νŒ¨ν„΄μ„ μ΄μš©ν•œ 방식 (μŠ€ν”„λ§μ΄ μ±„νƒν•œ 방식)

     

    μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ˜ λ‹€μ–‘ν•œ λͺ¨λ“ˆ

    μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λŠ” κΈ°λŠ₯λ³„λ‘œ κ΅¬λΆ„λœ μ•½ 20μ—¬ 개의 λͺ¨λ“ˆλ‘œ κ΅¬μ„±λ˜μ–΄ μžˆλ‹€.

    λͺ¨λ“  λͺ¨λ“ˆμ„ μ‚¬μš©ν•  ν•„μš”λŠ” μ—†κ³  μ• ν”Œλ¦¬μΌ€μ΄μ…˜ κ°œλ°œμ— ν•„μš”ν•œ λͺ¨λ“ˆλ§Œ μ„ νƒν•΄μ„œ μ‚¬μš©ν•˜κ²Œλ” μ„€κ³„λ˜μ–΄μžˆλŠ”λ°

    이λ₯Ό κ²½λŸ‰ μ»¨ν…Œμ΄λ„ˆ 섀계라고 λΆ€λ₯Έλ‹€.

     

    πŸƒ μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬ vs. μŠ€ν”„λ§ λΆ€νŠΈ

    μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λŠ” κΈ°μ‘΄ 개발 λ°©μ‹μ˜ λ¬Έμ œμ™€ ν•œκ³„λ₯Ό κ·Ήλ³΅ν•˜κΈ° μœ„ν•΄ λ‹€μ–‘ν•œ κΈ°λŠ₯을 μ œκ³΅ν•˜κ³  ν•„μš”ν•œ λͺ¨λ“ˆλ“€μ„ μΆ”κ°€ν•΄ μ‚¬μš©ν•˜κ²Œ ν–ˆμ§€λ§Œ 그만큼 섀정이 λ³΅μž‘ν•œ νŽΈμ΄λ‹€.

     

    μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λ³„λ„μ˜ λ³΅μž‘ν•œ 섀정을 ν•˜μ§€ μ•Šμ•„λ„ μ‚¬μš©ν•  수 μžˆλŠ” μŠ€ν”„λ§ λΆ€νŠΈκ°€ λ“±μž₯ν–ˆλ‹€.

     

    μ˜μ‘΄μ„± 관리

    μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ—μ„œλŠ” 각 λͺ¨λ“ˆμ˜ μ˜μ‘΄μ„±μ„ 직접 μ„€μ •ν•΄μ•Όν•˜κ³ , ν˜Έν™˜λ˜λŠ” 버전을 λͺ…μ‹œν•΄μ•Όν•˜κ³ , μ—°κ΄€λœ λ‹€λ₯Έ 라이브러리의 λ²„μ „κΉŒμ§€λ„ κ³ λ €ν•˜λ©° μ‚¬μš©ν•΄μ•Ό ν–ˆμ—ˆλ‹€.

     

    μŠ€ν”„λ§ λΆ€νŠΈμ—μ„œλŠ” μœ„μ™€ 같은 λΆˆνŽΈν•¨μ„ ν•΄μ†Œν•˜κΈ° μœ„ν•΄ 'spring-boot-starter'λΌλŠ” μ˜μ‘΄μ„±μ„ μ œκ³΅ν•œλ‹€.

    각 라이브러리의 κΈ°λŠ₯κ³Ό κ΄€λ ¨ν•΄μ„œ 자주 μ‚¬μš©λ˜κ³  μ„œλ‘œ ν˜Έν™˜λ˜λŠ” λ²„μ „μ˜ λͺ¨λ“ˆ μ‘°ν•© μ„ΈνŠΈλ₯Ό μ œκ³΅ν•œλ‹€.

     

    많이 μ‚¬μš©λ˜λŠ” spring-boot-starter λΌμ΄λΈŒλŸ¬λ¦¬μ—λŠ” λ‹€μŒκ³Ό 같은 것듀이 μžˆλ‹€.

    • spring-boot-starter-web: μŠ€ν”„λ§ MVCλ₯Ό μ‚¬μš©ν•˜λŠ” RESTful μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€κΈ° μœ„ν•œ μ˜μ‘΄μ„±.
      기본으둜 λ‚΄μž₯ ν†°μΊ£(Tomcat)이 포함돼 μžˆμ–΄ jar ν˜•μ‹μœΌλ‘œ μ‹€ν–‰ κ°€λŠ₯
    • spring-boot-starter-test: JUnit Jupiter, Mockito λ“±μ˜ ν…ŒμŠ€νŠΈμš© 라이브러리 포함
    • spring-boot-starter-jdbc: HikariCP 컀λ„₯μ…˜ 풀을 ν™œμš©ν•œ JDBC κΈ°λŠ₯ 제곡
    • spring-boot-starter-security: μŠ€ν”„λ§ μ‹œνλ¦¬ν‹°(인증, κΆŒν•œ, 인가 λ“±) κΈ°λŠ₯ 제곡
    • spring-boot-starter-data-jpa: ν•˜μ΄λ²„λ„€μ΄νŠΈλ₯Ό ν™œμš©ν•œ JPA κΈ°λŠ₯ 제곡
    • spring-boot-starter-cache: μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ˜ μΊμ‹œ κΈ°λŠ₯ 제곡

     

    μžλ™ μ„€μ •(Auto Configuration)

    μžλ™ 섀정은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μΆ”κ°€λœ 라이브러리λ₯Ό μ‹€ν–‰ν•˜λŠ” 데 ν•„μš”ν•œ ν™˜κ²½ 섀정을 μ•Œμ•„μ„œ μ°Ύμ•„μ€€λ‹€.

     

    μŠ€ν”„λ§ λΆ€νŠΈ ν”„λ‘œμ νŠΈλ₯Ό μƒμ„±ν•˜λ©΄ 메인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œλ₯Ό μžλ™μœΌλ‘œ λ§Œλ“€μ–΄μ£ΌλŠ”λ°

    μ΄λ•Œ @SpringBootApplication μ΄λΌλŠ” μ–΄λ…Έν…Œμ΄μ…˜μ„ λΆ™μ—¬μ€€λ‹€.

     

    @SpringBootApplication μ–΄λ…Έν…Œμ΄μ…˜μ€ @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan μ„Έ 개의 μ–΄λ…Έν…Œμ΄μ…˜μ„ 합쳐놓은 ꡬ성이닀.

     

    μŠ€ν”„λ§ λΆ€νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‹€ν–‰λ˜λ©΄ @ComponentScan 이 @Component μ‹œλ¦¬μ¦ˆ μ–΄λ…Έν…Œμ΄μ…˜μ΄ 뢙은 클래슀λ₯Ό λ°œκ²¬ν•΄ 빈(bean)을 λ“±λ‘ν•œλ‹€. @EnableAutoConfiguration μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 'spring-boot-autoconfigure' νŒ¨ν‚€μ§€ μ•ˆμ— spring.factories νŒŒμΌμ„ μΆ”κ°€ν•΄ λ‹€μ–‘ν•œ μžλ™ 섀정이 μ μš©λœλ‹€.

     

    spring.factories νŒŒμΌμ„ μ—΄λ©΄ λ‹€μ–‘ν•œ Auto Configure ν•­λͺ©λ“€μ΄ μ‘΄μž¬ν•˜λŠ”λ° 각 νŒŒμΌμ— μ„€μ •λœ @Conditional의 쑰건을 μΆ©μ‘±ν•  경우 λΉˆμ— λ“±λ‘λ˜κ³  μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μžλ™ λ°˜μ˜λœλ‹€.

     

    Component μ‹œλ¦¬μ¦ˆμ—λŠ”
    · @Controller
    · @RestController
    · @Service
    · @Repository
    · @Configuration
    이 ν¬ν•¨λ˜μ–΄ μžˆλ‹€.

     

    λ‚΄μž₯ WAS

    μŠ€ν”„λ§ λΆ€νŠΈμ˜ 각 μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—λŠ” λ‚΄μž₯ WAS(Web Application Server)κ°€ μ‘΄μž¬ν•œλ‹€.

    μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•  λ•Œ κ°€μž₯ 기본이 λ˜λŠ” μ˜μ‘΄μ„±μΈ 'spring-boot-starter-web' μ•ˆμ— 톰캣을 λ‚΄μž₯ν•œλ‹€.

     

    μŠ€ν”„λ§ λΆ€νŠΈμ˜ μžλ™ μ„€μ • κΈ°λŠ₯은 톰캣에도 μ μš©λ˜λ―€λ‘œ νŠΉλ³„ν•œ μ„€μ • 없이 ν†°μΊ£ μ‹€ν–‰ κ°€λŠ₯

     

    λͺ¨λ‹ˆν„°λ§

    μ„œλΉ„μŠ€ 운영 λ‹¨κ³„μ—μ„œλŠ” ν•΄λ‹Ή μ‹œμŠ€ν…œμ΄ μ‚¬μš©ν•˜λŠ” μŠ€λ ˆλ“œ, λ©”λͺ¨λ¦¬, μ„Έμ…˜ λ“±μ˜ μ£Όμš” μš”μ†Œλ“€μ„ λͺ¨λ‹ˆν„°λ§ ν•΄μ•Όν•˜λŠ”λ° μŠ€ν”„λ§ λΆ€νŠΈ 앑좔에이터(Spring Boot Actuator)λΌλŠ” 자체 λͺ¨λ‹ˆν„°λ§ 도ꡬ가 μžˆλ‹€.