스프링 프레임워크(Spring Framework)는 Java 기반 애플리케이션 개발을 지원하는 오픈소스 애플리케이션 프레임워크로 간단히 스프링(Spring)이라고도 불린다. 순수 자바 객체(POJO)만을 사용하여 복잡성을 제거하고, 단순하고 가벼운 코드로 기업용 애플리케이션을 개발하기 위한 목적으로 개발된 프레임워크(Framework)이다.


어떤 객체가 외부의 라이브러리나 외부의 모듈을 가져와서 사용하고 있다면, 그 객체는 POJO라고 할 수 없다. POJO는 말 그대로, 다른 기술을 사용하지 않는 순수한 Java만을 사용하여 만든 객체인 것이다
// 기본적인 POJO 예시
public class Person {
// 필드
private String name;
private int age;
// 기본 생성자
public Person() {
}
// 매개변수 있는 생성자
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getter 메서드
public String getName() {
return name;
}
// setter 메서드
public void setName(String name) {
this.name = name;
}
// getter 메서드
public int getAge() {
return age;
}
// setter 메서드
public void setAge(int age) {
this.age = age;
}
// toString 메서드 (객체 정보를 문자열로 반환)
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
POJO 프로그래밍을 위해 스프링이 지원하는 기술인 IoC/DI, AOP, PSA에 대해서 알아보자
스프링은 객체의 생명 주기 및 의존성 관리를 담당하는 IoC 컨테이너를 제공한다. 개발자는 객체의 생성과 관계 설정을 스프링에 위임할 수 있으며, 스프링 컨테이너가 객체의 생명 주기를 관리하고 필요한 의존성을 주입한다. 즉 프로그램의 흐름을 개발자가 직접 제어하지 않고, 프레임워크가 대신 제어하는 개념이다
스프링은 의존성 주입을 통해 객체 간의 관계를 설정한다. 의존성 주입은 애플리케이션의 결합도를 낮추고 유연성과 테스트 용이성을 향상시킨다.
public class UserService {
private UserRepository userRepository;
public UserService() {
this.userRepository = new UserRepository(); // 직접 생성
}
// ...
}
위의 코드에서는 'UserService'는 직접적으로 'UserRepository'를 생성하고 의존하고 있다. 이로 인해서 'UserService'와 'UserRepository' 간에 강한 결합이 형성되어 있다. 이런 경우 유지 보수성이 떨어지며, 코드 변경 시 여러 클랠스에 영향을 줄 수 있다.
1. Constructor Injection
생성자를 통해 의존성을 주입하는 방식이다. 클래스의 생성자를 정의하고, 의존하는 객체를 매개변수로 받아 필드에 할당한다.
public class UserService {
private UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// ...
}
2. Setter Injection
Setter 메서드를 통해 의존성을 주입하는 방식이다. Setter 메서드를 정의하고, 해당 메서드를 통해 의존하는 객체를 주입한다.
public class OrderService {
private PaymentGateway paymentGateway;
@Autowired
public void setPaymentGateway(PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
// ...
}
3. Field Injection
필드에 직접 의존성을 주입하는 방식이다. 주로 '@Autowired' 어노테이션을 사용하여 필드에 의존성을 주입한다.
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
// ...
}
4. Method Injection
메서드의 매개변수로 의존성을 주입하는 방식이다.
@Component
public class ReportGenerator {
private EmailService emailService;
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
public void generateReport() {
// Use the emailService here...
}
}
5. @Qualifier 어노테이션 사용 (빈의 특정 구현체 주입)
같은 타입의 여러 빈 중에서 어떤 빈을 주입할지 선택할 때 사용
public class OrderService {
private PaymentGateway paymentGateway;
@Autowired
public OrderService(@Qualifier("creditCardGateway") PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
// ...
}
6. XML 설정을 통한 의존성 주입
XML 파일을 사용하여 의존성 주입을 정의할 수 있다.
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="userRepository" />
</bean>
<bean id="userRepository" class="com.example.UserRepository" />
7. Java Config
Java 설정 클래스를 사용하여 의존성 주입을 정의할 수 있다.
@Configuration
public class AppConfig {
@Bean
public UserService userService(UserRepository userRepository) {
return new UserService(userRepository);
}
@Bean
public UserRepository userRepository() {
return new UserRepository();
}
}
스프링은 AOP를 지원하여 애플리케이션의 핵심 비즈니스 로직과 부가적인 기능(로깅, 트랜잭션 관리 등)을 분리하여 모듈화할 수 있다. 이는 중복 코드를 줄이고 코드의 가독성과 유지보수성을 높인다. 즉, AOP는 여러 객체에 공통으로 적용할 수 있는 기능을 구분함으로써 재사용성을 높여주는 프로그래밍 기법이다.
PSA란 환경의 변화와 관계없이 일관된 방식의 기술로의 접근 환경을 제공하는 추상화 구조를 말한다.

스프링은 Java 백엔드 개발에 있어 핵심적인 역할을 수행하는 프레임워크이며, 백엔드 개발에서 데이터베이스는 떼어놓기 어렵습니다. 웹 서버는 데이터베이스와 소통하며 웹 클라이언트의 요청을 처리해야 하기 때문입니다. 데이터베이스의 종류는 MySQL, Oracle, Maria DB, Mongo DB 등 실로 다양합니다.
만약, 여러분이 MySQL을 사용하여 개발을 완료했는데, Maria DB로 데이터베이스를 바꿔야 하는 상황을 가정해봅시다. 이 때, 각 데이터베이스마다 사용 방법이 다르다면 어떨것 같나요? 아마 기존에 작성한 코드를 전부 지우고 새로 작성해야 하거나, 기존 데이터베이스와 새로운 데이터베이스 간에 사용 방법이 다른 코드를 모두 찾아서 일일이 수정해주어야 할 것입니다.
그러나, 스프링을 사용하면 동일한 사용방법을 유지한 채로 데이터베이스를 바꿀 수 있습니다. 이는 스프링이 데이터베이스 서비스를 추상화한 인터페이스를 제공해주기 때문에 가능합니다. 즉, 스프링은 Java를 사용하여 데이터베이스에 접근하는 방법을 규정한 인터페이스를 제공하고 있으며, 이를 JDBC(Java DataBase Connectivity)라고 합니다.
각 데이터베이스를 만든 회사들은 자신의 데이터베이스에 접근하는 드라이버를 Java 코드의 형태로 배포하는데, 이 드라이버에 해당하는 Java 코드의 클래스가 JDBC를 구현합니다. 따라서, JDBC를 기반으로 하여 데이터베이스 접근 코드를 작성해두면, 이후에 데이터베이스를 바꾸어도 기존에 작성한 데이터베이스 접근 로직을 그대로 사용할 수 있습니다.
이러한 JDBC처럼 특정 기술과 관련된 서비스를 추상화하여 일관된 방식으로 사용될 수 있도록 한 것을 PSA(Portable Service Abstraction, 일관된 서비스 추상화)라고 합니다.
스프링은 강력한 기능을 제공하기 위해 많은 설정과 구성이 필요합니다. 이는 초기 설정의 복잡성을 증가시킬 수 있고, 초보자에게는 어렵게 느껴질 수 있습니다. 개발자들이 애플리케이션 컨텍스트 설정, 빈 정의, 다양한 컴포넌트 구성 등을 위해 많은 설정 코드를 작성해야 합니다.
스프링은 다른 프레임워크에 비해 학습이 필요한 부분이 많습니다. 다양한 개념과 기능을 이해하고 사용하기 위해 시간과 노력이 필요할 수 있습니다.
전통적인 스프링 프레임워크에서는 여러 의존성과 그들의 버전을 관리하는 것이 복잡할 수 있습니다. 스프링 레거시에서는 의존성 주입(Dependency Injection)을 구현하기 위해 XML 설정 파일에 많은 수의 빈(Bean)을 등록해야 합니다. 이는 코드의 가독성을 떨어뜨리고, 의존성 관리가 어려워질 수 있습니다
스프링을 웹상에서 사용하기 위해서는 별도의 Web Application Server(WAS)를 설치하고, 설정해야 합니다. 또한, 애플리케이션을 서비스하기 위해서 별도의 서버에 수동으로 배포해야 하는 번거로움이 있습니다.
스프링은 기존 기술의 복잡성을 크게 줄인 프레임워크이지만, 그럼에도 불구하고 스프링을 사용하기 위해서는 여러 가지의 사항들을 설정해주어야 한다. 스프링 부트를 사용하면 설정 정보를 간략하게 줄일 수 있다. 스프링 부트는 스프링으로 애플리케이션을 만들 때에 필요한 설정을 간편하게 처리해주는 별도의 프레임워크이다.
스프링 부트는 번거로운 XML 설정이 필요 없으며, 최소한의 설정으로 Spring을 사용할 수 있고, 기본적인 설정을 자동으로 처리하므로 개발자가 많은 설정 작업을 하지 않아도 됩니다. 설정으로 인한 불편사항을 해소하여 개발자는 애플리케이션 개발에 집중할 수 있다.
스프링 부트는 내장된 서버(내장 Tomcat, Jetty, Undertow)를 제공하여 별도의 서버 설정 없이 애플리케이션을 실행할 수 있다. 배포를 위해 War 파일을 생성해서 Tomcat에 배포할 필요 없으며, JAR 파일에는 모든 의존성 라이브러리가 포함되어 있어 외부 서버 없이도 애플리케이션을 실행할 수 있다. 이는 애플리케이션의 배포와 관리를 간편하게 만들어 준다.
스프링 부트는 여러 3rd party 라이브러리를 사용할 때, 발생하는 라이브러리 버전 충돌로 인한 문제를 해결하기 위해서, 이미 테스트된 여러 라이브러리들의 묶음 패키지를 제공한다.
3rd party 의존성 관리를 용이하게 하기 위한 ‘starter’ 의존성 통합 모듈을 제공하여 Maven/Gradel 설정 시 버전 관리가 간편하다. 스프링 부트에서 제공하는 의존성 세트를 통해 개발자는 버전 충돌이나 복잡한 의존성 설정에 대해 걱정하지 않고 필요한 의존성을 쉽게 지정할 수 있다.
스프링 부트는 애플리케이션의 상태 모니터링, 로깅, 보안 설정 등 운영에 필요한 기능들을 제공한다. 이를 통해 애플리케이션의 운영과 관리가 편리해지고 안정성이 향상된다.
출처
https://www.codestates.com/blog/content/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8
https://velog.io/@alghrksl/Spring-Spring-%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80
https://velog.io/@jinyeong-afk/%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-Spring-IoC-Inversion-of-Control%EC%99%80-DI-Dependency-Injection%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC