Java/Spring

[Spring] 3. 스프링 프레임워크의 핵심 기능 알아보기

Sigfriede 2023. 6. 3. 10:47

  A 클래스에서 다른(B) 클래스를 사용하려면 new 키워드를 이용하여 다른 클래스의 인스턴스를 생성하고 다른 클래스의 메서드를 사용합니다. 이때 다른 클래스에서 구현했던 메서드를 변경하면 A 클래스에서도 해당 메서드를 변경해야 합니다. 이때 A 클래스는 B 클래스에 의존한다고 합니다.

    의존의 유형에는 클래스 의존(구현 의존)과 인터페이스 의존이 있습니다. 먼저 클래스를 의존하는 경우입니다. A 클래스에서 B 클래스의 인스턴스를 생성하고 메서드를 호출합니다. 그러나 설계가 변경되어 B 클래스가 아닌 C 클래스를 호출하도록 변경해야 합니다. 이를 위해서는 예를 들어, 인스턴스를 생성하는 부분 또는 메서드를 호출하는 부분 등 B 클래스를 직접적으로 지정하는 모든 부분을 C로 변경해주어야 합니다. 만약 이러한 수정을 해야 하는 부분이 많을수록 시간을 많이 소요할 뿐만 아니라 실수할 위험이 높아집니다.

  그러나 인터페이스 의존은 이러한 단점을 보완합니다. A 클래스에서 다른 클래스의 메소드를 호출하고자 할 때, 클래스와 클래스 사이에 인터페이스를 둠으로써 간접적으로 호출하는 방식입니다. 인터페이스는 B 클래스의 메서드를 호출하고 A 클래스는 인터페이스에 의존하게 합니다. 만약 B 클래스의 메서드에서 C 클래스의 메서드로 변경하여 호출해야 한다면 인스턴스를 생성하는 부분 단 한 군데만을 B에서 C로 변경하면 됩니다.

  의존성 주입(Dependency Injection)은 DI로 표현할 수 있으며 의존하는 부분을 외부에서 주입하는 것입니다. 의존하는 부분이란 사용하는 객체 클래스에 사용되는 객체 클래스가 작성된 부분을 의미합니다. 외부로부터 주입이란 사용하는 객체 클래스 밖에서 사용되는 객체 인스턴스 주입을 의미합니다.

  인스턴스 생성과 같은 작업을 프레임워크에 맡길 수 있습니다. 이 역할을 하는 것이 DI 컨테이너입니다. 스프링 프레임워크는 임의로 구현한 클래스를 인스턴스로 만들어주는 기능을 제공합니다. DI 컨테이너에 인스턴스 생성을 맡긴 뒤 다음 다섯 가지 규칙을 지킨다면 사용하는 객체 클래스를 수정하지 않아도 되게끔 할 수 있습니다.

 

  1. 인터페이스를 이용하여 의존성을 만든다.
  2. 인스턴스를 명시적으로 생성하지 않는다.
  3. 어노테이션을 클래스에 부여한다.
  4. 스프링 프레임워크에서 인스턴스를 생성한다.
  5. 인스턴스를 이용하고 싶은 곳에 어노테이션을 부여한다.

 

  의존성 주입은 네 가지 역할을 담당하는 객체 및 인터페이스를 전제로 합니다. 사용될 (모든) 서비스, 사용하는 서비스에 의존하는 클라이언트, 클라이언트의 서비스 사용 방법을 정의하는 인터페이스, 서비스를 생성하고 클라이언트로 주입하는 책임을 갖는 주입자로 이루어져 있습니다. 특히 클라이언트는 의존성의 특정 구현에 대해 구체적인 지식이 필요 없고, 인터페이스는 클라이언트가 구체적인 지식을 이해할 필요가 없도록 보장해주는 기능을 합니다.

  의존성 주입의 장점으로는 단순히 코드 유지보수가 쉬워진다는 것 외에도 여러 가지를 꼽을 수 있습니다. 코드를 유연하고 확장 가능하도록 합니다. 코드의 재사용성을 높여주고 중복되는 코드를 방지합니다. 코드 간 결합도를 낮추어, 테스트 코드 작성이 용이해지는 등 다양한 장점이 있습니다.

 

  어노테이션(annotation)은 주석을 의미합니다. '@xxx'와 같은 형태로 작성하고, 외부 소프트웨어에 필요한 처리 내용을 전달합니다. 어노테이션을 사용하면 에러를 출력하거나 프로그램의 동작을 변경하는 등 다양하게 할 수 있습니다.

  애플리케이션을 만들 때 레이어를 구분하는 것이 좋습니다. 레이어를 나누는 법은 다양하지만 이 책에서는 도메인 주도 설계를 기준으로 설명합니다. 도메인 주도 설계에서는 클라이언트와의 데이터 입출력을 제어하는 애플리케이션 레이어, 애플리케이션의 중심이 되는 레이어로서 업무 처리를 수행하는 도메인 레이어, 데이터베이스에 대한 데이터 영속성(Presistence Context) 등을 담당하는 인프라스트럭처 레이어가 있습니다. 이에 따라 인스턴스 생성 어노테이션도 레이어별로 구분할 수 있습니다.

 

클라이언트 애플리케이션
레이어
도메인
레이어
인프라
레이어
데이터베이스
@Controller @Service @Repository

 

  컨트롤러 어노테이션은 클라이언트의 요청을 처리하고 응답을 생성하는 역할을 수행하는 클래스에 붙입니다. 주로 URL 매핑과 요청 처리 메서드(특정 URL 경로에 대한 요청처리, 특정 HTTP 메서드에 대한 요청처리 등)를 정의합니다. 서비스 어노테이션은 비즈니스 로직을 처리하는 역할을 수행하는 클래스에 붙입니다. 데이터 조작, 트랜잭션 관리 등이 있습니다. 레포지토리 어노테이션은 데이터 액세스 객체를 나타내는 클래스에 붙입니다. 주로 DB 조작을 위한 CRUD(Create, Read, Update, Delete) 메서드를 정의합니다. 레포지토리는 스프링 프로젝트에서 데이터 접근에 관한 기능을 제공하는 스프링 데이터를 활용할 수 있습니다. JPA, JDBC 등 API 이용하여 DB와 상호작용을 할 수 있습니다. 특히 JPA를 사용하면 개발자가 SQL 쿼리를 작성하지 않아도 DB와 상호작용 할 수 있다는 장점이 있습니다.

 또 컴포넌트(Component) 어노테이션이 있습니다. 이는 앞서 설명한 세 개의 용도 이외의 인스턴스 생성 대상 클래스에 붙입니다. 이외에도 다양한 종류와 기능의 어노테이션이 있지만 직접 커스텀 어노테이션을 만들 수 있습니다.

 

  관점 지향 프로그래밍(Aspect Oriented Programming)이란 AOP로 표현할 수 있으며, AOP에서는 프로그램이 두 가지 요소로 구성됩니다. 중심적 관심사(Primary Concern)는 실현해야 할 기능을 나타내는 프로그램이고 횡단적 관심사(Crosscutting-Concerns)는 본질적인 기능은 아니지만 품질이나 유지보수 등 관점에서 반드시 필요한 기능을 나타내는 프로그램을 뜻합니다.

  데이터베이스 액세스 처리 코드를 작성할 때 실현해야 할 기능인 액세스 처리는 중심적 관심사, 예외 발생 시 처리하는 예외 처리 코드는 횡단적 관심사로 볼 수 있습니다. 스프링 프레임워크에서는 AOP 기능을 이용하여 중심적 관심사와 횡단적 관심사를 분리하여 프로그램을 만들 수 있습니다. AOP의 고유 용어는 다음과 같습니다.

 

용어 내용
어드바이스
(Advice)
- 횡단적 관심사의 구현(메서드), 로그 출력 및 트랜잭션 제어 등
애스펙트
(Aspect)
- 어드바이스를 정리한 것(클래스)
조인포인트
(JoinPoint)
- 어드바이스를 중심적인 관심사에 적용하는 타이밍
- 메서드(생성자) 실행 전, 메서드 실행 후 등 실행되는 타이밍
포인트컷
(Pointcut)
- 어드바이스를 삽입할 수 있는 위치
- 예를 들어 메서드 이름이 get으로 시작할 때만 처리하는 조건 정의
인터셉터
(Interceptor)
- 처리 제어를 인터셉트하기 위한 구조 또는 프로그램
타깃
(Target)
- 어드바이스가 도입되는 대상

 

  스프링 프레임워크에서는 인터셉터라는 메커니즘으로 횡단적 관심사(어드바이스)를 중심 관심사(타깃)에 삽입한 것처럼 보이게 합니다. 다음은 인터셉터의 동작 방식입니다.

  A 클래스에서 B 클래스의 X 메서드를 호출하는 경우입니다. B 클래스의 X 메서드를 중심적 관심사와 횡단적 관심사로 분리하여 애스펙트와 어드바이스를 만듭니다. AOP를 사용하면 A 클래스에서 B 클래스의 X 메서드(중심적 관심사)를 호출하는 것처럼 보입니다. 그러나 내부적으로는 AOP 프락시(스프링 프레임워크가 자동 생성)가 처리를 가로채고 X 메서드 및 어드바이스의 호출을 제어합니다.

  직접 어드바이스를 만드는 경우 패키지, 클래스, 메서드 등 어드바이스 삽입 대상을 조건으로 지정할 수 있습니다. 지정하는 조건 방법에는 포인트컷 식을 이용합니다.

 

  https://start.spring.io/

  Spring Initializr는 웹 브라우저에 접속하여 바로 사용할 수 있습니다. 스프링 부트에서 프로젝트를 시작할 때 통합 개발 환경(IDE)에 의존하지 않는 프로젝트를 만드는 방법입니다. IDE에 Spring Initializr 플러그인을 설치하여(IntelliJ의 경우 Ultimate 버전에서 가능) 간단하게 스프링 프로젝트를 생성할 수도 있습니다.

 

 

  ※ "스프링 프레임워크 첫걸음"이라는 책을 참고하여 쓴 게시글로, 책의 내용을 완전히 담지 않되 공부한 부분을 위주로 정리하여 작성하고자 했습니다. 따라서 글에는 책에서 다루지 않은 내용도 포함되어 있으며 문제가 되거나 부정확한 부분이 있다면 알려주시면 감사하겠습니다.

  ※ 책은 게시글보다 정확한 내용을 담고 있으며 코드, 그림, 예제를 이용하여 개념을 자세히 설명합니다.