소프트웨어의 구체적인 부분에 해당하는 설계와 구현을 재사용이 가능하게끔 일련의 협업화된 형태로 클래스들을 제공하는 것
Framework는 뼈대
, 틀
이라는 의미를 가지고 있다.
즉, 소프트웨어적인 관점에서 어떤 애플리케이션을 만들기 위한 뼈대/틀/구조를 제공하는 것이라고 이해하면 된다.
우리가 굳이 직접 처음부터 만들지 않아도, 여러 기능들을 편리하게 사용할 수 있도록 만들어놓은 뼈대!
Spring 프레임워크 뿐만 아니라, 다양한 프레임워크가 존재한다.
그 예시로 Collection Framework
가 있다.
Collection Framework
은 자료 구조를 바탕으로 만든 Map, Set, List 같은 Collection들이 해당 데이터를 처리하기 쉽도록 여러 기능들을 제공하는 인터페이스와 클래스의 집합이다.
효율적
라이브러리는 다른 누군가가 필요한 기능을 미리 구현해둔 코드로, 우리는 평상 시에 필요한 라이브러리를 골라서 사용한다.
둘의 차이점은 "애플리케이션에 대한 제어권이 누구에게 있냐"이다.
- 라이브러리: 주도권이 개발자에게 있음
(우리는 선택적으로 라이브러리를 사용함)- 프레임워크: 주도권이 프레임워크에게 있음
(우리는 Spring Framework에 따라 코드를 작성함, 주도권이 개발자에게 없음)
Java 애플리케이션 개발을 위한 포괄적인 인프라를 지원하는 Java 플랫폼
✔️ 여러 Java Framework이 있지만, 사람들은 왜 특히 Spring을 많이 사용할까?
Spring은 재사용과 확장에 용이하여 개발 생산성을 향상 시키고, 애플리케이션 유지/보수가 쉽기 때문이다. 또한, 보안성, 시스템의 안정성, 효율성이 필요한 기업용 엔터프라이즈 시스템을 구축하기에 좋다.
하지만 Spring Framework도 단점이 있는데, 애플리케이션의 기본 구조를 잡는 설정 작업(web.xml)이 어렵다는 것이다.
이런 설정의 어려움을 개선해서 나온 framework가 Spring Boot
이다.
✅ 스프링은 POJO 프로그래밍을 지향하는 Framework이다.
✅ 스프링의 주요 기술인 IoC/DI, AOP, PSA는 애플리케이션을 POJO로 개발할 수 있게 해주는 기술들이다.
A 클래스가 B 클래스의 기능을 사용한다.
= A 클래스는 B 클래스의 도움을 받는다.
= A 클래스는 B 클래스에 의존한다.
= A, B 클래스는 의존 관계이다.
A 클래스가 B 클래스에 의존한다면, A 클래스 내부에 B 클래스의 객체를 생성해야 한다.
객체를 생성해서 의존 관계를 형성하는 방법은 2가지가 있다.
new
키워드 사용: 강하게 결합됨예를 들어, 베스킨라빈스에서 파인트를 구매한다고 생각해보자.
DI를 사용하지 않은 상태는 다음과 같을 것이다.
파인트 클래스 내부에는 바닐라, 초코, 체리 아이스크림의 클래스가 new 키워드
를 통해서 생성되어 있다.
즉 상위 모듈인 Pint
는 하위 모듈인 Vanilla
, Chocolate
, Cherry
에 의존하고 있고, 강하게 결합되어 있다.
이는 객체 지향 설계에 맞지 않다!
객체 지향 설계에 맞게 수정하려면, Vanilla
, Chocolate
, Cherry
클래스를 추상화한 Icecream
인터페이스가 있어야 하며 세 클래스는 인터페이스에 의존해야 한다.
또한, 상위 모듈인 Pint
도 Vanilla
, Chocolate
, Cherry
클래스에 의존하는 것이 아니라 Icecream
인터페이스에 의존해야 한다.
원래 상위 모듈이 하위 모듈에 의존했는데 이 의존 관계가 역전된 것이다.
✅ 상위 모듈은 하위 모듈에 의존하지 않고, 상위 모듈과 하위 모듈 둘 다 추상화(인터페이스)에 의존해야 한다.
위에서 말했듯이, new
키워드를 통해서 객체를 생성한다면, 두 클래스는 결합도가 높다.
결합도가 높으면 요구 사항의 변경에 유연하게 대처할 수 없다.
따라서 클래스 간의 결합도를 낮춰야 하고, DI를 통해 결합도를 낮출 수 있다.
1) 클래스 내부에서
new
키워드를 사용해 참조할 클래스의 객체를 직접 생성하지 않고, 생성자 등을 통해 외부에서 다른 클래스의 객체를 전달해준다.
2) 클래스가 인터페이스에 의존하도록 한다.
-> 생성자의 인자로 인터페이스를 두면, 주입되는 객체가 인터페이스의 구현체이기만 하면 어떤 클래스든 주입 받을 수 있기 때문에 결합도가 낮아진다.
AOP은 애플리케이션에서 비즈니스 로직과 공통 기능을 분리하여 재사용 가능한 모듈로 사용할 수 있도록 만드는 것이다.
✅ PSA(Portable Service Abstraction): 서비스를 추상화 시켜, 서비스의 기능에 접근하는 방식을 일관되게 유지한다.
✅ 추상화: 어떤 클래스의 본질적인 특성만을 추출해서 일반화하는 것
자바에서 추상화를 할 수 있는 방법은 두 가지이다.
상위 모듈(추상 클래스나 인터페이스)과 이를 구현한 하위 모듈이 있을 때, 상위 모듈의 타입인 변수에 구현 객체를 할당한다.
=> 업캐스팅
ex) Child
라는 상위 클래스가 있고, 이를 구현한 NewBornBaby
, Infant
, Toddler
클래스가 있다.
세 하위 클래스는 상위 클래스가 선언해둔 메소드를 모두 가지고 있고 각자의 클래스에 맞게 구체화되어 있다.
상위 모듈의 타입인 변수에 구현 객체를 할당하면 모든 하위 클래스의 기능들을 모두 사용할 수 있고, 어떤 하위 클래스를 사용하더라도 일관된 방식으로 서비스 기능을 사용할 수 있다.
public class ChildManageApplication {
public static void main(String[] args) {
Child newBornBaby = new NewBornBaby(); // (1)
Child infant = new Infant(); // (2)
Child toddler = new Toddler(); // (3)
newBornBaby.sleep();
infant.sleep();
toddler.sleep();
}
}
2) 서플릿 - 웹 요청 처리에 특화된 Java 클래스
서블릿 컨테이너
중 하나이다.3) 자바 콘솔 애플리케이션 vs 웹 애플리케이션
main 메서드
에서 프로그램이 시작되고 이를 엔트리 포인트라고 한다. main 메서드가 끝나면 애플리케이션도 종료된다.main 메서드
가 존재하지 않고, 항상 클라이언트의 요청을 받아야 하기 때문에 프로그램이 종료되지도 않는다. 클라이언트의 요청이 들어오면, 서플릿 컨테이너가 컨테이너 로직(service 메서드)에 따라 서블릿을 직접 실행시켜주기 때문에 main이 필요없다.main()
메서드처럼 애플리케이션이 시작되는 지점