[스프링 기초] 스프링이란?

스프링 프레임워크를 알아보기 전에 먼저!


도대체 프레임워크는 뭐고 라이브러리는 뭘까

프레임워크와 라이브러리를 각각 구글에 검색을 하면 다음과 같이 나옵니다.

프레임워크

프레임워크는 어떠한 목적을 달성하기 위해 복잡하게 얽혀있는 문제를 해결하기 위한 구조며, 소프트웨어 개발에 있어 하나의 뼈대 역할을 한다.

라이브러리

소프트웨어 개발 시 사용되는 프로그램의 구성요소로, 공통으로 사용될 수 있는 특정한 기능(들)을 모듈화한 것

자바 관련 회사에 면접을 보러가면 기술질문에서 많이 나오는 대표적인 질문 중에 하나이지만 아무리 스프링을 접해보고 관련 공부를 한 사람이라고 해도 개념을 정확하게 이해하고 있지 않으면 이해하기 힘든 문장입니다.

이미지 출처


네. 붕어빵 기계입니다.

붕어빵을 만들기 위해서 단지 붕어(?) 모양의 틀 안에 반죽을 넣고 원하는 재료를 추가한 후 일정한 주기마다 뒤집어주기만 하면 맛있는 붕어빵이 완성됩니다.
프레임워크도 마찬가지입니다. 프레임워크를 조금 더 쉽게 표현을 하자면 소프트웨어의 특정 문제를 해결하기 위해서 상호 협력하는 클래스와 인터페이스의 집합 이라고 말할 수 있는데 저 문장을 풀어서 해석하자면

  • 붕어 모양의 틀 혹은 기계 == 프레임워크
  • 소프트웨어의 특정 문제 == 붕어빵 만들기
  • 상호 협력하는 클래스와 인터페이스 == 붕어빵 기계를 구성하는 부품

라고 볼 수 있습니다.

그렇다면 라이브러리는 뭘까요?

라이브러리는 간단하게 말하면 도구들의 집합 입니다.

사람이 붕어빵을 만들 때 미리 준비 해 둔 반죽을 틀에 넣을 때 다양한 도구들을 사용할 수 있는데 주전자를 통해서 넣어도 되고 국자를 사용해서 넣어도 됩니다. 그리고 막 만들어진 붕어빵을 꺼낼 때 집게를 사용해도 되고 장갑을 끼고 직접 꺼내도 되죠.

여기서 사용되는 도구들이 라이브러리입니다.

이제 프레임워크와 라이브러리의 차이에 대해서 알아보았으니 본 주제인 프레임워크에 대해 좀 더 깊게 들어가봅시다.

스프링 프레임워크의 핵심 개념

스프링 프레임워크는 2002년에 로드존슨이라는 개발자가 자신의 개발 경험과 노하우를 바탕으로 샘플로 만든 프레임워크가 책을 통해서 알려지고 대중적으로 사용되면서 지금의 수준까지 발전하게 되었습니다.

IOC(제어의 역전)

스프링에 대해서 공부를 하게 되면 가장 먼저 접하게 되는 개념들 중 하나가 IOC(제어의 역전) 입니다. 이 제어의 역전이라는 개념은 스프링에서 애플리케이션 컨텍스트 라는 컨테이너가 개발자가 사용하고자 하는 을 생성, 소멸시켜주고 사용자가 필요할 때 제공을 해주는 작업을 해줍니다.

이러한 빈을 수동으로 등록하는 방법에는 크게 2가지가 있습니다.

XML을 사용한 방법

<bean id="inventoryService"
	  class="com.example.InventoryService">
</bean>

<bean id="productService"
	  class="com.example.ProductService">
    <constructor-arg ref="inventoryService">
</bean>

자바 기반 구성

@Configuration
public class ServiceConfiguration {

	@Bean
	public InventoryService inventoryService(){
    	return new InventoryService();
    }
    
    @Bean
    public ProductService productService(){
    	return new ProductService(inventoryService());
    }
}

두 방법의 코드 모두 재고 정보를 관리하는 제품 서비스 컴포넌트(빈)와 재고의 상태를 나타내는 재고 서비스 컴포넌트를 정의합니다.

XML을 사용하였을 때는 <bean /> 태그를 통해서 빈이라는 것을 정의하고 <constructor-arg ref="inventoryService">   이 태그를 통해서 제품 서비스 컴포넌트가 재고 서비스 컴포넌트에 의존한다는 것을 정의하죠.

반면 자바 구성의 경우에는 @Configuration 어노테이션과 @Bean 어노테이션을 통해서 ServiceConfiguration 클래스가 스프링 애플리케이션 컨텍스트에 빈을 제공한다는 것을 명시해주고 등록된 빈들은 컨테이너의 관리를 받게 됩니다. 또한 return new ProductService(inventoryService());   를 보면 알 수 있듯이 ProductService 의 빈을 생성할 때 inventoryService() 를 호출해줌으로써 의존 관계를 설정해줍니다.

하지만 위의 자바 기반 구성은 자동 연결(authwiring)컴포넌트 검색(Component Scanning)이라는 스프링 기법을 사용할 수 없을 경우에만 필요하므로 저러한 방법이 있다라는 정도만 알면 됩니다.

DI(Dependency Injection)

실제로 프로젝트에서 빈을 등록하고 DI(의존성 주입)을 할 때는 다음의 방법들을 사용합니다.

  • 필드 주입(Field Injection)
@Service
public class OrderService{

	@Autowired
    private DesignService designService;
}
  • 수정자 주입(Setter Injection)
@Service
public class OrderService{
	
    private DesignService designService;

	@Autowired
    public void setOrderService(DesignService designService){
    	this.designService = designService;
    }
}
  • 생성자 주입(Constrocture Injection)
@Service
public class OrderService{
	
    private final DesignService designService;

	@Autowired
    public OrderService orderService(DesignService designService){
    	this.designService = designService;
    }
}

아마 대부분의 사람들이 간단하다는 이유로 필드 주입을 사용할텐데 정작 스프링에서는 생성자 주입을 권장하고 있습니다. 그 이유로는 여러가지가 있는데 첫 번째로 순환 참조 방지라는 특징이 있습니다.

@Service
public class OrderService{

    @Autowired
    private DesignService designService;
}
.
.
.

@Service
public class DesignService{

	@Autowired
	private OrderService orderService;
}

실제로 이렇게 코드를 작성할 일은 거의 없겠지만 다음과 같은 코드를 작성을 하게 되면 애플리케이션을 구동하고 해당 비지니스 로직을 처리하려고 한다면 두 컴포넌트가 서로를 끊임없이 참조를 하면서 StackOverflowError 발생하게 될 것입니다. 위에서 작성한 필드 주입 외에 수정자 주입도 마찬가지입니다. 하지만 생성자 주입의 경우에는 애플리케이션이 구동되는 시점에서 오류를 알려줘서 순환 참조를 방지할 수 있게 됩니다.

생성자 주입이 순환 참조를 방지할 수 있는 이유

생성자 주입의 경우 컨테이너에서 주입 받고자 하는 클래스의 빈이 생성되기 전에 생성자의 인자에 있는 클래스의 빈을 찾아서 빈을 생성하게 되는데 이 과정을 통해서 순환 참조를 하고 있다는 것을 알게됩니다. 즉 빈의 생성 시점에서 주입을 받느냐 아니면 등록 되어져 있는 빈을 호출할 때 주입을 받느냐의 차이입니다.

두 번째로 의존성 주입이 필요한 필드에 final 속성을 사용할 수 있다는 특징이 있는데, 이를 통해서 로직 처리 도중에 객체의 값이 변경되는 것을 방지할 수 있고 초기값에 null을 넣지 않는한 NullPointException 오류를 방지할 수 있습니다. 그 외에도 테스트 코드를 작성하기 편하다라는 점도 있습니다.

AOP(Aspect Oriented Programing)


다음은 AOP 혹은 관점 지향 프로그래밍이라고 불리는 개념으로 비지니스 로직이 실행이 될 때 핵심 기능과 부가 기능으로 구분하고, 공통적으로 사용되는 부가 기능들을 모듈화해서 별도의 클래스에서 관리를 함으로써 유지 보수가 수월해진다는 장점이 있습니다.

이미지 출처

대표적으로 로깅이나 트랜잭션 처리를 할 때 사용을 하며 스프링에서 해당 기능을 사용하기 위해서는 대표적으로 Spring AOP 혹은 AspectJ 라는 라이브러리를 통해서 사용할 수 있습니다. AOP의 핵심 개념과 두 라이브러리의 차이점에 대해서 자세하게 알고 싶은 분들은 여기에 알기 쉽게 나와있으니 참고해주세요.

POJO(Plain Old JavaBean Object)

마지막으로 소개할 스프링의 핵심 개념인 POJO 는 말그대로 해석하면 오래된 방식의 간단한 자바 오브젝트라고 할 수 있습니다. 스프링 프레임워크 이전에 사용된 EJB와 같은 프레임워크의 경우 객체를 사용하기 위해서는 특정 기술 클래스를 상속받아야만 사용할 수 있었고 그렇다보니 코드의 가독성이 떨어지고 유지보수가 힘들어지며 객체 지향의 핵심 개념인 다형성을 위배한 코드를 작성하게 됩니다. 그래서 이에 대한 반발로 생겨난것이 POJO로 이러한 개념을 사용해서 만들어진 다양한 프레임워크 중에 하나가 스프링 프레임워크입니다.


스프링 프로젝트 시작하기

프로젝트를 시작하기 전 세팅

이 게시물은 스프링 Initializr인 STS[Spring Tool Suite]를 통해 프로젝트를 구성하였고 서적에서는 Maven을 사용하였지만 지금 프로젝트에서는 Gradle을 사용합니다.

스프링 프로젝트 구조

위의 항목들에서 대표적으로 알아볼 것들은 다음과 같습니다.

  • src/main/java : 애플리케이션 소스 코드가 저장되는 항목
  • static : 브라우저에 제공되는 정적인 콘텐츠(이미지, css, javascript 등)을 저장
  • application.properties : 외부 설정 파일, key : value 형식으로 저장하면 애플리케이션에서 참조하여 사용 가능
  • src/main/test : 테스트 코드가 저장되는 항목
  • build.gradle : 프로젝트 전반적인 설정을 비롯해서 빌드할 때 필요한 라이브러리들의 의존 관계에 대해서 설정하는 파일 [build.gradle 설정에 자세한 설명]

애플리케이션 부스스트랩(구동)

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

프로젝트를 생성하게 되면 다음과 같은 부트스트랩 클래스가 있는 것을 확인할 수 있는데 간단하게 보이는 것과는 달리 중요한 기능들을 포함하고 있습니다.

첫 번째로 @SpringBootApplication 어노테이션에는 세 개의 어노테이션이 결합된 것인데 다음과 같습니다.

  • @SpringBootConfiguration : @Configuration 어노테이션의 특화 버전
  • @EnableAutoConfiguration : 스프링 부트 자동-구성을 활성화하는 어노테이션으로 스프링 부트가 실행될 때 클래스 패스에 있는 spring.factories를 찾아서 자동으로 빈을 생성해서 등록(spring.factories => 설정 클래스들의 정보들을 가지고 있음)
  • @ComponentScan : @Component 어노테이션 및 @Service, @Repository, @Controller 어노테이션을 사용한 클래스를 찾아 Bean으로 등록

즉 위의 세 어노테이션을 부트스트랩 클래스에 선언을 해주면 @SpringBootApplication 어노테이션과 동일한 효과를 기대할 수 있습니다.

마무리

지금까지 간단하게 프레임워크와 라이브러리의 차이, 스프링에 대해서 알아보았고 프로젝트를 만들어서 중요한 구성들에 대해서 알아보았습니다.

이 내용은 책 Spring in Action -크레이그 월즈- 의 내용을 참고하여 작성된 글입니다.

좋은 웹페이지 즐겨찾기