간단한 Spring 설명 및 관련 이론

sycho·2023년 11월 13일
0

Spring-tips

목록 보기
1/2
post-thumbnail
  • Spring과 Spring Boot가 기본적으로 뭔지 및 관련 이론에 대해 알아보자.

  • Spring Boot에 대해서 알려면 일단 Spring에 대해서 자세히 알 필요가 있다. Spring의 파생형이 Spring Boot라고 볼 수 있기 때문.

What is Spring Core?

  • Core module of Spring, 즉 스프링의 핵심 모듈
  • dependency injection (DI)랑 inversion of control (IoC)기반 구성에 필요한 기능 제공

DI, IoC, DIP 기본 개념 및 spring과의 연관성

이 글 참고

그 외의 Spring 관련 특징

  • Aspect-Oriented Programming (AOP)를 지원한다. 프로그램의 여러 기능적 요소들에 동시에 영향을 줄 수 있는 요소들을 cross-cutting concern이라고 보통 말하며 보안이나 로그 관련 요소들이 해당되는데, 이것들을 기능적인 요소랑 잘 분리될 수 있도록 해주는 패러다임이다. AOP는 각 class에서 나오는 중복되는 코드들을 aspect 형태로 다시 모듈화한 것이다.

  • 데이터 접근이랑 Transaction과 관련된 framework을 제공해준다.

  • 일정 task가 주어졌을 대 이를 어떻게 실행할지 (병렬로, 주기적으로, 비동기형식으로) scheduling을 하는 TaskScheduler이랑 이를 실제로 수행하는 TaskExecutor이라는 녀석을 제공한다.

  • 이외에도 다음을 제공한다.

    • 유연하고 확장가능한 validation framework
    • type conversion system
    • 일관성 있는 messaging framework

messaging 관련

  • Spring에서 서로 다른 module이 소통을 하는데 사용될 수 있는 기능 중 하나가 event class instance를 주고받는 것이다.

  • 일관성 있는 event handling을 하기 위해 publish/subscribe model을 활용한다.

  • 실제 Event class를 만들려면 ApplicationEvent라는 녀석을 만들면 되며, 이것의 instance가 전달되는 Event가 될 수 있다.

  • Event class를 전달하려면 ApplicationEventPublisher을 (위의 DI에서 배운대로) injection 한다음에 event를 만들어서 전달하면 된다.

  • Event를 수신하고 그에 따른 행동을 하려면 ApplicationListener이라는 interface를 구현한 class를 활용해야 한다. 아니면 @EventListener을 사용해도 된다.

Spring Boot과 Spring의 차이

'Starters' allowing Simplified Dependency Management

  • 앞에 IoC를 구축함으로써 여러 software component 사이의 dependency가 존재는 하되, 독립적일 수 있도록 형성하는 것을 배웠다.

  • 그러나 어쨌든 사람이 수동으로 이 dependency를 관리해야 하는 것은 여전하다. 그리고 이것은 매우 번거로운 작업이다. 예를 들어, 특정 software component가 upate되었을 경우 결국 그거랑 의존 관계를 가지는 다른 software component를 테스트하고, 버그가 없는지를 확인하는 작업은 여전히 필요하고 이를 일일이 찾아보는 것은 매우 번거롭다.

  • 이 중 특정 애플리케이션을 만들 때 그 application에서 '흔히 사용되는 기능'과 관련된 dependency 형성이 가장 번거로우면서도 생산성이 전혀 없는 작업 중 하나다. 예를들어 어떤 API를 만든다고 할 때 흔히 요청을 받을 수 있는 endpoint를 만들고, 거기서 요청을 듣고, 요청이 오면 그걸 적절히 해독한 후에 처리하고, 그걸 다시 해당 프로토콜에 적절하게 encode 한 다음에 답변을 전송하게 될 것이다. 이건 뭔 API를 만들든 똑같은 구조인데 새로운 애플리케이션을 만들 때마다 관련 dependency를 Spring에서 직접 형성하는 것은 매우 피곤한 작업이다.

  • 이를 해결하기 위해 Spring Boot는 'Starter'이라는 것을 제공한다. 어떤 목적의 application에서 흔히 사용되는 기능과 관련된 통합된 dependency 딱 1개를 제공 해주는 것이다. 여기서 중요한건 '단 1개'라는 것이고, 또 이 starter 안의 요소들 사이의 dependency가, starter이 각 요소에 대해 사용한 버전에 대해서는 문제를 안 일으키는지가 전부 테스트가 되어 있다는 것이다. 자주 사용되는 기능들은 보통 Spring Boot에서 이렇게 starter로 보통 제공된다.

  • 이 때 starter에서 사용한 요소들의 버전보다 더 높은 버전을 필요로 하는 경우에는 override하는 것도 가능하다. 아니면 필요 없는 요소가 있다 싶으면, 그것을 빼는 것도 가능하다. 다만 그렇게 수정된 starter에 대해서 잘 동작한다는 보증은 없기 때문에 별도로 테스트를 해야 한다는 점 유의.

  • 여하튼 이 starter 덕분에 프로젝트 초기에 온갖 dependency를 형성해야 하는 피곤함을 줄이는 것이 가능하다. 즉 초기 애플리케이션 형성 때의 밑작업 과정에서 필요한 dependency 관리를 손쉽게 할 수 있도록 해준다.

Simplified Deployment using Spring Boot Executable JARs

  • Application Server을 Java에서 만드는게 사실 엄청 피곤한 작업이었다. DB 구축, Application Server 구축, 서로 연결하기, application 만든 다음에 테스트까지 완료되면 Server에 deploy하기...

  • 이 과정을 Spring Boot는 엄청 압축시켰다는 것이 특징이다. 사실 여러 JAR 파일(Java Archive File. Java class file과 관련 메타데이터, 자원들을 포함하는 여러 package들을 하나로 만든 파일)들을 하나로 뭉쳐서 배포를 쉽게 하는 것인 uber JAR이라는 컨셉이 있는데, Spring Boot는 이 작업을 많이 개선했다.

  • 기존에는 shading이라는 것을 사용했다. 하나로 통합할 JAR들 안의 파일들을 전부 꺼낸 다음에 하나로 합치는 형태를 가졌기 때문. 각 JAR들이 가질 의존관계 및 조직이 어떤지를 직접 재구성해야 했기 때문에 여러가지 애로사항이 있었다. 같은 이름의 파일이 존재하는 경우라든가, 서로 다른 두 JAR이 공통된 JAR에 의존하는데 그 JAR의 서로 다른 버전에 대해서 의존을 한다든가 등.

  • 그러나 Spring Boot의 경우 그냥 단순히 해당 JAR들을 그대로 냅두고, 이를 전부 포괄하는 JAR을 하나 형성해버렸다. 이를 nested JAR approach라고 부르며, 그렇게 만들어진 JAR을 Spring Boot executable JAR이라고 한다.

  • 이 접근의 장점은 단순히 재구축 과정이 필요 없어서 복잡성이 덜하다는 것 뿐만이 아니라, 기존의 JAR들이 가지는 구조를 전부 유지하는 것이 가능하다는 것이다. 덕분에 당장 위에서 언급한 문제점들도 전부 해결이 가능하고, 서로 다른 license를 기반으로 형성이 된 JAR간의 융합도 문제없이 이루어진다. 또 안의 내용물을 추출하는 것도 쉽다.

  • 저게 완성이 되면 그냥 JVM에 실행하면 된다. 아니 심지어 java -jar ...과 같은 명령어 없이 그냥 executable 자체를 그냥 실행하는 형태로 Application을 실행하는 것도 가능해진다.

auto-configuration

  • 앞에서 초기 밑작업과 관련된 dependency 형성 과정에서의 복잡성은 starter이 해결한다고 했다. 이거는 해당 application의 기반용 dependency라고 생각하면 되며, 관련 dependency의 버전을 수정하는 일은 거의 없다. Maven이나 Gradle 관련 configuration을 간단하게 해주는 기능이라고 보면 된다.

  • Auto-configuration은 starter이랑 성향이 좀 다른데, 바로 집어넣은 JAR dependency에 있는 정보를 기반으로 Spring Boot가, 특정 세부 작업을 하는 코드를 프로그래머가 작성할 때 최소한의 코드만 작성할 수 있도록 흔히 반복되는 작업을 '알아서' configure하는 것이다.

  • 기반 dependency 형성 후에도, 특정 세부작업을 하기 위해서 우리가 여전히 코드를 어마무시하게 쓰고 그 과정에서 관련 dependency들을 고려해야 하는 것은 여전한 상황. 그런데 Spring Boot에서 이 dependency들을 고려해 반복되는 작업들을 '알아서' 해결해준다면? 프로그래머는 본인이 실제로 구현하려는 부분에 대해서만 집중하는 것이 가능하다. framework에서 개발자에게 이런 환경을 주는 것을 convention over configuration (설정보다 관습)이라고 부른다.

  • 게다가 통합된 환경에서 개발을 할 수 있다는 것도 이 기능의 연장선이라고 보면 된다.

  • 앞의 정의를 좀 더 딱딱하게 얘기하자면, 자동으로 class간의 dependency를 확인해가지고 spring application의 환경 설정을 알아서 하는 기능을 auto-configuration이라고 한다.

  • 덕분에 application 개발 시간 자체가 많이 단축될 수 있지만, 반대로 세세한 조정을 하기 힘들거나 자기 자신은 모르는 configuration이 작동 중일 수 있다는 문제점이 있으며 실제로 이 때문에 Spring을 여전히 사용하는 곳도 있다고 한다.

  • 다만 세세한 조정을 하고 싶으면 특정 상황에서 auto-configuration을 다르게 하도록 예외사항을 넣거나, 아예 특정 코드에서는 auto-configuration을 끄면 되긴 한다. 다만 이 경우 그만큼 복잡도가 증가한다는 문제점이 있음.

  • 앞의 세가지 기능을 활용해 빠르게, 동작가능한 application을 개발한 후 이를 또 빠르게 배포하는 것이 이 framework의 목표이기 때문에 '시작시 필요한 절차'와 관련된 bootstrap라는 이름을 따와서 이름이 Spring Boot다.

embedded server

  • Spring framework에서 개발된 application을 수행하려면 server을 따로 우리가 설정해줘야 한다.

  • 하지만 Spring Boot의 경우 Tomcat, jetty와 같은 embedded server을 제공해준다. 즉 application 자체에 저런 server들이 integrate되어 있다는 것인데, 그러면 우리가 따로 서버를 만들고 그거 환경설정한다음에 거기에 application을 올리는 번거로운 짓을 할 필요가 없다.

  • 특히 application code에 변경사항이 생겼을 때 그걸 다시 올리는 과정에서의 번거로움이 많이 줄어든다.

  • 다만 application의 일부로 취급이 되어 application 차원에서 사용하는 자원을 같이 나눠쓰기 때문에, intensive한 task를 수행하는 것이 힘들 수 있다. 이 때문에 매우 높은 트래픽에 대한 대응이 불안정하단 이유로 Spring을 여전히 쓰는 사람들도 있다.

그 외 장점

  • 최대한 코드를 쓰는 양을 단축하는 형식으로 디자인이 되어 있다. 예를들어 HTTP Basic Authentication에서 작성해야 하는 코드양이 적다든가.

  • in-memory database 지원을 한다. 저것의 장점은 disk 기반 DB 대비 속도가 빠르고, 단점은 휘발성이라 연결된 전원이 꺼지면 자료가 그대로 날라간다. 보통 날라가도 상관 없는 임시 데이터들을 저장한다.

  • XML configuration은 아예 필요가 없다.

  • 내장 CLI (Command Line Interface) tool이 있다. 이걸로 어느정도 테스팅을 하는 것도 가능하다.

  • Gradle, Maven과 같은 build tool과 관련된 plugin들을 제공해주고 이 덕분에 배포가 Spring보다 좀 더 편하다.

Spring Boot work-flow Architecture

  • 마지막으로 간단하게 Spring Boot에서 따르는 work-flow architecture에 대해 알아보도록 하자. 구조적 architecture과 workflow architecture에 대해 알아보도록 하겠다.

spring boot layers

  • 상하관계 형태로 4개의 층으로 이루어져 있으며, 각 층은 본인의 바로 위 아래 층하고만 소통을 한다.

  • Presentation layer : HTTP 요청 처리. JSOn parameter을 object로 변환. 요청이 정말로 정상적인지 인증 한 후 business layer에 전달을 한다. frontend 영역에 해당한다고 생각하면 된다.

  • Business Layer : business logic이 여기에 속한다. 접근 권한에 따른 제어랑 validation도 여기서 이루어진다. service class들로 이루어져있으며, data access layer에서 제공하는 서비스를 활용한다.

  • Persistence Layer : storage logic이 여기에 속한다. business object들을 DB의 실제 row로 변환, 그리고 앞의 역변환을 여기서 담당한다.

  • Database Layer : CRUD (create, retrieve, update, delete) operation이 이루어지는 곳이다.

example work flow architecture

  • 기본적으로 Spring이랑 매우 유사하며, Spring에서 사용하는 module들을 다 사용한다. Spring MVC라든가, Spring Data라든가. 이들이 뭔지는 나중에 알아볼 것이며, 일단은 저걸 사용하지만, DAO랑 DAOImpl class가 필요 없다는 것이 큰 차이점이라는 점에 유의

  • 간단한 Spring Boot application의 동작 방식은 다음과 같다.

    • client에서 controller에게 HTTP request를 했다고 하자.
    • request에 대해 적절한 service logic이 필요하다면, controller측에서 이를 수행한 다음에 business logic이 본격적으로 동작한다. business logic은 Service layer이 담당한다.
    • 이때 database에 있는 data는 JPA (Java Persistence Library)를 통해 Model이라는 application에서 활용하는 data structure로 변환이 된다. SErvice Layer은 이거를 조작해가지고 Database를 갱신하거나 읽으며, 실제 database 조작 operation은 CRUD service들을 활용해서 이루어진다.
    • 지금의 경우 단순 HTTPS request이기 때문에 오류가 없는 경우 JSP page가 완성이 되고 client에게 전달이 된다.
profile
안 흔하고 싶은 개발자. 관심 분야 : 임베디드/컴퓨터 시스템 및 아키텍처/웹/AI

0개의 댓글