Spring

Spring 01 - 스프링의 특징

나주나주 2024. 2. 27. 10:16

 

Spring

: 반자동화 (외부 api를 가져옴, 인터넷 연결 필수)

Tip) 파일아이콘우측상단S == 스프링이 반자동화 걸어둠ㅇ

 

Framework

: 뼈대나 근간을 이루는 코드들의 묶음

 

 프레임워크를 이용한다

: 프로그램의 기본 흐름이나 구조를 정하고, 모든 팀원이 이 구조에 자신의 코드를 추가하는 방식으로 개발한다

 

 

Spring Framework의 주요 특징

 

1. POJO

  : Plain Old Java Object, API 없이 Java 코드를 이용해서 객체를 구성하여 개발자가 특정한 라이브러리나 컨테이너의 기술에 종속적 X

 

2. 의존성 주입(Dependency Injection) 관계

    의존적이다 (ex) A 객체가 B 객체 없이 동작이 불가능한 상황

 

 

    • 의존성 주입 방식에서는 그림의 '바깥쪽 도형'같은 존재 ApplicationContext가 필요하다.
    • 객체Bean와 객체를 분리해서 생성하고, 필요한 객체를 주입
    • 엮는wiring 작업(XML 설정, Annotation 설정 등)을 하는 형태로 개발

 

3. AOP(Aspect-Oriented-Programming) 지원

  :  좋은 개발환경의 중요 원칙 → '개발자가 비즈니스 로직에만 집중할 수 있게 한다'

(ex) 반복적인 코드의 제거

 

대부분의 시스템이 공통으로 가지고 있는 보안이나 로그, 트랜잭션과 같이 (비즈니스 로직은 아니지만) 반드시 처리가 필요한 부분을 스프링에서는 횡단 관심사 cross-concern 라고 합니다. AOP는 횡단 관심사를 모듈로 분리하여 제작할 수 있습니다.

AspectJ 문법을 통해 작성하면서 개발자는

  1. 핵심 비즈니스 로직에만 집중해서 코드 개발
  2. 각 프로젝트마다 다른 관심사concern를 적용할 때 코드의 수정 최소화
  3. 원하는 관심사의 유지보수 수월

스프링은 트랜잭션(하나의 업무가 여러 작업으로 이루어짐) 관리를 Annotation이나 XML로 설정할 수 있어 개발자가 (1)매 상황에 맞는 코드를 작성할 필요가 없다 (2)수정 후 인코딩과 디코딩을 거치지 않아 유지보수가 수월하다

 

4. 편리한 MVC 구조

5. WAS의 종속적이지 않은 개발 환경

 

Tip) 스프링 프로젝트 대부분이 Web의 영역에서 많이 사용되지만, 근본적인 사상 자체는 OOP 구조를 뒷받침하고 구조를 설계하는 사상입니다. 의존성 주입Dependency Injection에 대한 점이 더욱 그렇습니다.

 

Spring version에 따른 눈에 띄는 변화

  • 2.5: Annotation을 활용하는 설정을 도입하면서 편리한 설정과 개발이 가능해짐
  • 3.0: 별도의 설정 없이도 Java 클래스 만으로 설정 파일을 대신할 수 있게 지원
  • 4.0: 모바일 환경과 웹 환경에서 많이 사용되는 REST 방식의 컨트롤러 지원
  • 5.0: Reactor를 이용한 Reactive 스타일의 개발 환경 지원

 

의존성 주입(Dependency Injection) 테스트

[설명] 예제는 XML과 Annotation을 이용하여 설정합니다. Lombok을 이용해서 setter 메서드를 자동으로 구현되도록 할 것이고, 스프링의 동작을 test할 것이므로 pom.xml에서 Lombok 라이브러리, spring-test 라이브러리를 이용합니다.

이전 그림과 다른 이유는, 아직 model 사용법을 배우지 않았기 때문이다

 

1. 예제 생성

  • pom.xml 을 작성하여 라이브러리 추가, 변경
<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
  • 취약점 발견된 log4j 대신 log4j2 활성화
<!-- log4j2 활성화 : resources log4j2.xml 변경 https://logging.apache.org/log4j/2.x/maven-artifacts.html -->
		<dependency> 
		    <groupId>org.apache.logging.log4j</groupId>
		    <artifactId>log4j-api</artifactId>
		    <version>2.18.0</version>
		  </dependency>
		  <dependency>
		    <groupId>org.apache.logging.log4j</groupId>
		    <artifactId>log4j-core</artifactId>
		    <version>2.18.0</version>
		</dependency>
	    <dependency>
		    <groupId>org.apache.logging.log4j</groupId>
		    <artifactId>log4j-slf4j-impl</artifactId>
		    <version>2.18.0</version>
  		</dependency>

 

  • 클래스 작성
<!-- 일반적으로 Chef를 인터페이스로 설계하는 것이 좋지만 최소한의 코드를 이용해 보았다 -->

package org.zerock.sample;

import org.springframework.stereotype.Component;
import lombok.Data;

@Component
@Data
public class Chef {

}
package org.zerock.sample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.Data;
import lombok.Setter;

@Component
@Data //setter(), 생성자, toString(), hashcode() 등을 자동으로 생성
public class Restaurant {
	@Setter(onMethod_ = @Autowired)
    private Chef chef;
}

 

2. XML로 의존성 주입 설정

Spring Legacy Project의 경우 기본적으로 XML을 이용해서 스프링에서 관리해야 하는 객체들을 처리합니다.

WEB-INF > spring > root-context.xml은 Bean(스프링에서 관리해야 하는 객체)을 설정합니다. 탭 NameSpaces를 클릭하여 context 항목을 체크한 뒤 저장합니다. 다시 Source 탭을 선택하여 아래의 코드를 추가합니다.

변경된 XML을 저장하고 Bean Graph 탭을 선택해 객체 설정을 확인해 봅니다.

 

 

3. 동작 순서 확인

  • 스프링 프레임워크가 시작되면 스프링이 사용하는 메모리 영역을 만들게 되는데 이를 Context라고 합니다. 스프링에서는 ApplicationContext객체(객체 생성, 주입 등의 관리 역할)가 만들어집니다.
  • root-context.xml에 설정되어 있는 <context:component-scan> 태그의 내용을 통해 'org.zerock.sample' 패키지를 스캔
  • 해당 패키지에 있는 클래스들 중에서 스프링이 사용하는 @Component(어노테이션이 존재하는 클래스)의 인스턴스 생성
  • Restaurant 객체는 Chef 객체가 필요한 어노테이션 설정 Setter(onMethod_ = @Autowired) 이 있으므로 스프링은 Chef 객체의 레퍼런스를 Restaurant 객체에 주입합니다.

 

4. 테스트 확인

  • 프로젝트 src/test/java 폴더 내에 org.zerock.sample.SampleTests 클래스를 추가합니다
  • 클래스는 spring-test 모듈과 Junit(반드시 4.10 이상)을 이용해서 간단하게 스프링을 가동시킵니다.
package org.zerock.sample;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j2;

@RunWith(SpringJUnit4ClassRunner.class) //현재 코드가 스프링을 실행할 것
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml") //참고할 파일[A]
@Log4j2 //Log4j2를 이용해서 콘솔에 로그 출력[B]
public class SampleTests {

	@Setter(onMethod_ = @Autowired) //lombok 자동 주입[C]
    private Restaurant restaurant; //테스트용 필드 생성
    
    @Test //메서드 단위 테스트
    public void testExist() {
    
    assertNotNull(restaurant); //assertNotNull: 객체가 없어도 중단되지 않음
    
    Log.info(restaurant);
    Log.info("--------------------------");
    Log.info(restaurant.getChef());
    }
}

[A] @ContextConfiguration: 필요한 객체들을 스프링 내에 빈으로 등록 'classpath:' 나 'file:'을 이용하여 root-context.xml의 경로 지정

[B] Lombok을 이용해서 로그를 기록하는 Logger를 변수로 생성, 별도의 Logger 객체의 선언 없이도 Log4j2 라이브러리와 설정이 존재한다면 바로 사용 가능. (로그에 대한 설정은 src/main/resources, src/test/resources에 존재한다)

[C] Autowired는 해당 인스턴스 변수가 스프링으로부터 자동으로 주입해 달라는 표시이며, 스프링은 정상적으로 주입이 가능하다면 obj 변수에 Restaurant 타입의 객체를 주입하게 됩니다. testExist()에 선언되어 있는 @Test는 JUnit에서 테스트 대상을 표시하는 어노테이션입니다. 해당 메서드를 선택하고 JUnit Test 기능을 실행합니다. assertNotNull()은 restaurant 변수가 null이 아니어야만 테스트가 성공한다는 것을 의미합니다. 

  • new Restaurant() 와 같이 Restaurant 클래스에서 객체를 생성한 적이 없는데도 객체가 만들어진 점: 스프링이 관리가 필요한 객체Bean를 어노테이션 등을 이용해서 객체를 생성하고 관리하는 일종의 컨테이너나 팩토리의 기능을 가지고 있다.
  • Restaurant 클래스의 @Data 어노테이션으로 Lombok을 이용해서 여러 메서드가 만들어진 점: Lombok은 자동으로 getter/setter 등을 만들어 주는데 스프링은 생성자 주입 혹은 setter 주입을 이용해서 동작합니다. Lombok을 통해 getter/setter 등을 자동으로 생성하고 onMethod 속성을 이용해서 작성된 setter에 @Autowired 어노테이션을 추가
  • Restaurant 객체의 Chef 인스턴스 변수(멤버 변수)에 Chef 타입의 객체가 주입되어 있다는 점: 스프링은 @Autowired와 같은 어노테이션을 이용해서 자동으로 관리합니다. (개발자가 직접 객체들과의 관계를 관리하지 않고)

[결론] 테스트 코드가 실행되기 위해 프레임 워크가 동작했고, 필요한 객체들이 스프링에 등록, 의존성 주입이 필요한 객체는 자동 주입되었다


1. Spring 개발 환경 구축 OR 학습정리

  • 스프링의 버전은 5.x 버전을 사용하고, 개발도구는 Spring Tool Suite(이하 sts) 혹은 Eclipse와 Maven으로 작성합니다.
  • 기존에 사용하던 XML과 Java Configuration(이하 Java 설정)과 Annotation 기반의 설정을 이용합니다. -최근 스프링 관련 예제나 프로젝트에서 XML 대신에 Java 설정을 이용할 때가 점점 증가하고 있으므로 이를 반영합니다.
  • OracleDatabase 11g Express Edition 버전을 사용합니다.
  • Spring Security를 추가해서 로그인 부분을 처리합니다.
  • Lombok 라이브러리를 활용하여 Getter/Setter등을 줄인 최소한의 코드로 프로젝트를 작성합니다.
  • MyBatis의 Mapper 인터페이스와 XML을 활용합니다. 기존의 DAO를 이용하던 개발 방식을 개선해서 더 적은 양의 코드로 개발할 수 있습니다.

 

 


webapp > spring > appServlet > servlet-context.xml: 프론트 관련
root-context.xml :백엔드 관련
web.xml: 톰캣 설정
pom.xml: maven이 사용하는 pom.xml

root-context.xml

: 스프링 프레임워크에서 관리해야 하는 객체(Bean)을 최종적으로 설정(연결)하는 파일

스프링은 빈 객체를 루트컨텍스트에서 관리

루컨에서 세팅 시 S가 붙음

 

중요

  1. 프레임워크가 시작되면 메모리 영역Context을 만드는데, 스프링에서는 ApplicationContext 객체 생성
  2. root-context.xml에 <context:component-scan>의 내용을 통해 패키지를 스캔한다
  3. 해당 패키지에서 @Component 되어 있는 클래스의 객체 생성
  4. Restaurant는 Chef가 필요하다는 설정(@Autowired)이 있으므로, 스프링이 Chef를 Restaurant에 주입

 

Tip) Spring Legacy Project로 생성되는 Spring (3.0ver), JDK (1.6ver) 으로 5.0.7버전을 이용하기 위해 (생성된 프로젝트의 라이브러리는 pom.xml 파일을 통해 관리되므로) pom.xml 수정 → Maven > Update → Project Explorer > Maven Dependencies 를 통해 스프링 프레임워크 라이브러리들이 변경되었는지 확인

 

 

http:// == :80 



Export > Archive File 엑스포트 방법츄~

Java Configuration 안 할 거임
DTO 생성 5규약을 지키면 Lombok이 알아서 만듦??



@Annotation

Lombok Annotation 의미
@Setter setter 메서드를 만들어준다 (ex) getter/setter, equals(), toString(), hashCode()
@Data @ToString, @EqualsAndHashCode, @Getter/@Setter, @RequiredArgsConstructor를 모두 결합
세부적인 설정이 필요 없는 경우 자주 사용
@Log4j2 Log 객체 생성 (존재하지 않을 경우 @Log 사용 해야)
Spring Annotation 의미
@Component 스프링에서 객체로 만들어 관리하는 대상임을 명시
@ComponentScan을 통해 지정되어 있으므로 해당 패키지에 있는 클래스들을 조사하면서 @Component가 존재하는 클래스들을 객체로 생성해서 Bean으로 관리
@Autowired 자신이 의존적으로 해당 타입의 빈을 주입하라는 표시 → 스프링은 스프링 내부 객체 중에서 자동 주입 
Test Annotation 의미
@Test jUnit 상에서 해당 메서드가 단위 테스트의 대상
@RunWith 테스트 시 필요한 클래스 지정
@ContextConfiguration 참고할 파일 명시

 

@AllArgsConstructor //모든 필드값을 가진 생성자 (필드 자동 주입)

@NonNull //생성자 자동 주입 X

@RequiredArgsConstructor //NonNull이나 final이 붙은 인스턴스 변수(필드)에 대한 생성자

 

1. Lombok Annotation

[설명] Lombok:

 

@Setter 

@Setter의 3가지 속성 의미
value 접근 제한 속성을 의미합니다
기본값은 lombok.AccessLevelPUBLIC
onMethod setter 메서드의 생성 시 메서드에 추가할 어노테이션 지정
( JDK 버전에 따라 _ 표기가 다름
 up to JDK7:
@Setter(onMethod=@_({@AnnotationsGoHere}))

from JDK8:
@Setter(onMethod_={@AnnotationsGoHere}) //note the underscore after onMethod
onParam setter 메서드의 파라미터에 어노테이션을 사용하는 경우에 적용

 

@Data

 

@Log4j2

 

2. Spring Annotation

 

@Component

: Spring이 관리해야 하는 객체 명시

@Component가 있는 클래스를 스프링이 읽어주도록 @ComponentScan을 통해 지정되어 있으므로 해당 패키지에 있는 클래스들을 조사하면서 객체로 생성, 빈으로 관리하게 됩니다.

 

@Autowired

: 특정한 객체에 의존적이므로 해당 타입의 객체(빈) 주입 명시

 

2-1. test Annotation

 

@ContextConfiguration

: 스프링이 읽어 들여야 할 설정 정보 명시, location을 이용해서 문자열의 배열로 XML 설정 파일 명시, classes 속성으로 @Configuration이 적용된 클래스 지정

 

@Runwith

: 테스트 시 필요한 클래스 지정

 

@Test

해당 메서드가 jUnit 상에서 테스트의 대상 명시


assertNotNull(): 객체가 없어도 중단되지 않음

Tip) 스프링은 관리가 필요한 객체Bean를 어노테이션 등을 이요해서 객체를 생성하고 관리하는 일종의 컨테이너나 팩토리의 기능을 가지고 있다

Tip) 스프링은 @Autowired와 같은 어노테이션을 이용해서 개발자가 직접 객체들과의 관계를 관리하지 않고, 자동으로 관리하도록 합니다

 

Tip) 어노테이션 import 시 오류 해결

Java Proposals (Task-Focused) 해제 후 저장

 

Java Proposals (Task-Focused) 해제 후 저장

 

'Spring' 카테고리의 다른 글

Spring 04  (0) 2024.02.29
기본적인 웹 게시물 관리  (0) 2024.02.28
Spring 03 - Spring MVC, 파일 업로드(기본)  (0) 2024.02.28
Spring 02 - ConnPool  (1) 2024.02.27
Spring 00 - 초기 설정 방법  (0) 2024.02.26