⚙️ Backend/스프링(Spring) Framework

스프링 - 프레임 워크란? 특징, 장점, 라이브러리 개념 등

코너(Corner) 2021. 5. 6.
반응형

학습 목표

이 수업을 들으려면 할 줄 알아야하는 것.

  1. 스프링 프레임워크를 이용해서 '의존성 주입'에 대한 이해와 테스트
  2. 스프링에서 XML을 이용하는 객체 관리 방법
  3. 스프링의 테스트 환경 구축

프레임 워크란?

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

개발자는 각 개개인의 능력차이가 큰 직종이고, 개발자 구성에 따라 프로젝트 결과 역시 큰 차이를 낳는다.

이런 상황을 극복하기 위한 코드의 결과물이 바로 프레임워크이다.

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

프레임워크와 라이브러리의 차이

제어의 주체가 개발자가 아닌 프레임워크이고, 그 안의 여러 기능들을 가져다 사용하는 방식이다.

만약 수정해야할 때에는 도구들을 사용해서 수정 및 추가가 가능하다.

라이브러리는 주체가 개발자이며, 핵심 로직에서 필요한 부분들만 가져다 사용하는 방식이다.

프레임워크의 장점

개발에 필요한 구조를 이미 코드로 만들어 놓았기 때문에, 실력이 부족한 개발자라 하더라도 반쯤 완성한 상태에서 필요한 부분을 조립하는 형태의 개발이 가능하다.

  • 회사 입장에서는 프레임워크를 사용하면 일정한 품질이 보장되는 결과물을 얻을 수 있다.
  • 개발자 입장에서는 완성된 구조에 자신이 맡은 코드를 개발해서 넣기 때문에 개발 시간을 단축할 수 있다.

스프링 프레임워크란?

경량 프레임워크(Light-Wight).

예전 프레임워크는 다양한 경우를 처리할 수 있는 다양한 기능을 가지도록 만들다 보니 하나의 기능을 위해서 너무 많은 구조가 필요했다.
기술이 너무나 복잡하고 방대했기 때문에, 전체를 이해하고 개발하기에는 어려움이 많았다.

그래서 스프링 프레임워크가 등장했고, 특정 기능을 위주로 간단한 jar파일 등을 이용해서 모든 개발이 가능하도록 구성되어 있다.

스프링 프레임워크의 장점

  • 복잡함에 반기를 들어서 만들어진 프레임워크
  • 프로젝트 전체 구조를 설계할 때 유용한 프레임워크
  • 다른 프레임워크들의 포용(여러 프레임워크를 혼용해서 사용가능)
  • 개발 생산성과 개발도구의 지원

스프링 프레임워크의 특징

  • POJO 기반의 구성

    • POJO(Plain Old Java Object) 기반의 구성
    • 오래된 방식의 간단한 자바 객체라는 의미이며, Java 코드에서 일반적으로 객체를 구성하는 방식을 스프링 프레임워크에서 그대로 사용할 수 있다는 말이다.
    • ( 요약 : 스프링에서 Java를 쓸 수 있다. )
  • 의존성 주입(DI)을 통한 객체 간의 관계 구성

    • 의존성(Defendency)이란 하나의 객체가 다른 객체 없이 제대로 된 역할을 할 수 없다는 것을 의미한다.
      예를 들어 A객체가 B객체 없이 동작이 불가능한 상황을 'A'가 'B'에 의존적이다. 라고 표현한다.
    • 주입(Injection)은 말 그대로 외부에서 밀어 넣는 것을 의미한다.
      예를 들어 어떤 객체가 필요한 객체를 외부에서 밀어 넣는 것을 의미한다.
      주입을 받는 입장에서는 어떤 객체인지 신경 쓸 필요가 없고 어떤 객체에 의존하든 자신의 역할은 변하지 않게 된다.
      •  의존성으로 인해 높은 결합도를 느슨하게 유연하게 하기 위함.
의존

ⓐ -------> ⓑ

ⓐ객체에서 ⓑ객체를 직접 생성 (의존성)

 

의존성 주입

ⓐ ------???-----> ⓑ

ⓐ는 ⓑ가 필요하다는 신호만 보내고, ⓑ객체를 주입하는 것은 외부에서 이루어진다.

 

의존성 주입방식을 사용하기 위해서는 (???)라는 존재가 필요하게 된다.

스프링 프레임워크에서는 ApplicationContext가 바로 ???라는 존재이며,

필요한 객체들을 생성하고, 필요한 객체들을 주입해주는 역할을 한다.

따라서 개발자들은 기존의 프로그래밍과 달리 객체와 객체를 분리해서 생성하고,

이러한 객체들을 엮는(wiring) 작업의 형태로 개발하게 된다.

 

ApplicationContext가 관리하는 객체들을 '빈(Bean)'이라 부르고, 빈과 빈 사이의 의존 관계를 처리하는 방식으로 XML설정, 어노테이션 설정, Java 설정

 

  • AOP(Aspect-Oriented-Programming) 지원

관점 지향 프로그래밍.

좋은 개발환경에서는 개발자가 비지니스 로직에만 집중할 수 있게 한다.

스프링 프레임워크는 반복적인 코드를 제거해줌으로써 핵심 비지니스 로직에만 집중할 수 있는 방법을 제공한다.

보안이나 로그, 트랜잭션, 예외 등과 같이 비지니스 로직은 아니지만, 반드시 처리가 필요한 부분을 횡단 관심사(cross-concern)이라고 한다.

스프링 프레임워크는 이러한 횡단 관심사를 분리해서 제작하는 것이 가능하고, 횡단 관심사를 모듈로 분리하는 프로그래밍을 AOP라고 한다.

이를 통해서 3가지의 이점이 생긴다.

1) 핵심 비지니스 로직에만 집중하여 코드 개발

2) 각 프로젝트마다 다른 관심사 적용 시 코드 수정 최소화

3) 원하는 관심사의 유지보수가 수월한 코드 구성 가능

  • 편리한 MVC 구조

  • WAS에 종속적이지 않은 개발 환경

  • 트랜잭션 관리 용이

트랜 잭션의 지원.

DB 작없 시 트랜잭션 관리를 매번 상황에 맞게 코드로 작성하지 않고, 어노테이션이나 XML로 트랜잭션 관리를 설정할 수 있다.


스프링 STS 이클립스 Market Place 설치, 환경 설정

STS(Spring Tool Suite) 설치

  • spring boot (쉬움)
  • eclipse 플러그인 (선택)
    • 이클립스 실행 > Help > Install New Software-> Select All > Next > Next > progress 창 확인
    • -> http://download.springsource.com/release/TOOLS/update/e4.18/
      -> Add > Name : STS > Ok    
      링크의 e4.18은 이클립스의 버전을 뜻한다. 즉, Eclipse IDE 버전이 Photon이라면 4.8이다.  
      본인은 2020-12 버전을 사용중이기 때문에 e4.18이다. 확인은 이클립스 다운로드 사이트에서 확인 가능.

 

대기

Restart Now를 누른다.

Spring Legacy Project 클릭

Spring MVC Project 클릭 후 Next 

yes를 누르고 넘어간다.

프로젝트 처음 생성 후 빨간 오류가 뜨는 것은 당연하다. 아래와 같이 설정을 따라한다.

  • 프로젝트 생성(Maven, Project Object Model)
  • Maven은 필요한 라이브러리를 특정 문서(pom.xml)에 정의해 놓으면 사용할 라이브러리 뿐만 아니라 해당 라이브러리가 작동하는 데에 필요한 다른 라이브러리들까지 관리하여 네트워크를 통해서 자동으로 다운받아 준다.

초기 세팅 / 환경 설정

    <version>1.0.0-BUILD-SNAPSHOT</version>
    <properties>
        <java-version>1.8</java-version>
        <org.springframework-version>5.0.7.RELEASE</org.springframework-version>
        <org.aspectj-version>1.6.10</org.aspectj-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
    </properties>
-----------------------------------------------------------
 			// 137번줄 
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>

설정 후 저장 

프로젝트 우클릭 후 Update Project를 누른다.

프로젝트 우클릭 -> Maven -> update project

force update of snapshots/releases 체크

오류가 사라진 것을 확인해야 합니다.


Lombok 라이브러리 설치

이클립스와 스프링 플러그인만으로도 스프링 개발이 가능하지만,

Lombok(롬복)을 이용하면 Java 개발 시 getter/setter, toString(), 생성자 등을 자동으로 생성 해주므로 설치가 필요한 라이브러리 입니다.

 

이클립스 종료 후 

https://projectlombok.org/download

 

Download

 

projectlombok.org

위 링크에서 다운로드를 한다.

lombok.jar 이클립스가 실행된 경로에 jar파일을 두고,

jar 파일이 있는 경로에서 (Mac은 상관없이 바로 jar경로에서 터미널로 실행 하면 됨. 이클립스로 옮기지 않아도 된다.)

$ java -jar lombok.jar

커맨드로 실행해도 되고, jar파일을 직접 실행해도 됨

실행하면 아래와 같이 설치창이 실행되는데, Eclipse를 모두 체크 해제 후

Specify location.. 을 클릭

아래와 같은 Eclipse.app 경로에 eclipse.ini를 선택한다.

위와 같이 했다면 설치 종료.

 

주의!! MAC은 /Users/corner/Eclipse.app/Contents/Eclipse/eclipse.ini 로 경로를 잡고 설치해야한다.(윈도우도 에러날 경우 이 방법을 사용해야 한다.)

pom.xml 61번줄에 기존꺼 삭제하고 삽입

위 코드를 삭제

위 코드를 삭제하고 아래 코드를 삽입한다.

<dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.18.0</version>
         <scope>1.2.17</scope>
      </dependency>
      <dependency>
         <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
         <version>1.2.17</version>
      </dependency>

 

 

98번 줄 삽입 및 수정

위 코드를 아래 코드로 변경

<!-- Test -->
            <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-test</artifactId>
         <version>5.1.1.RELEASE</version>
      </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>       

저장 후 -> Maven Update

 

톰캣 server 생성 

톰캣 생성은 JDK Build Path와 맞아야 한다.


[프로젝트 기본 구성 요소]

src/main/java : 작성되는 코드의 경로

src/main/resources : 실행할 때 참고하는 기본 경로

src/test/java : 테스트 코드를 넣는 경로

src/test/resources : 테스트 관련 설정 파일 보관 경로

웹과 관련된 스프링 설정 파일 (Resources, View Resolver)

src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml

스프링 설정 파일 (Bean, IoC 컨테이너)

src/main/webapp/WEB-INF/spring/root-context.xml

Tomcat의 web.xml 파일 (Front Controller, DispatcherServlet)

src/main/webapp/WEB-INF/web.xml

템플릿 프로젝트의 jsp파일 경로

src/main/webapp/WEB-INF/views

Maven이 사용하는 pom.xml

[Project]/pom.xml

※만약 프로젝트에 오류 발생 시
C:\Users\여러분계정폴더.m2\repository 폴더 삭제 후 이클립스 재실행


 

* 의존성 주입 테스트

레스토랑 객체를 만들고 셰프 객체를 주입하는 예제

  • 생성자, setter 메소드를 이용한 주입으로 의존성 주입 구현.
  • 설정 방식은 XML, 어노테이션을 이용해서 처리

Beans Graph가 IoC 컨테이너 라고 하는 곳이다.(제어의 역전)

제 3자가 메모리를 할당 해주기 때문. (제3자는 스프링)

스프링 프레임워크 동작 시 생기는 일

  • 스프링 프레임워크가 시작되면 먼저 스프링이 사용하는 메모리 영역을 만든다.
    이것이 Context이다.
  • 스프링은 자신이 객체를 생성하고 관리해야 하는 객체들에 대한 설정이 필요하고 이 설정 파일이 바로 root-context.xml이다.
  • root-context.xml에 설정되어 있는 <context:component-scan>태그의 내용을 통해서 com.koreait.sample 패키지를 스캔하기 시작한다. (ex00/root-context.xml ⓵참고)
  • 해당 패키지에 있는 클래스들 중에서 스프링이 사용하는 @Component라는 어노테이션이 존재하는 클래스의 인스턴스를 생성한다. (ex00/com.koreait.sample⓶참고)
  • Restaurant객체는 Chef 객체가 필요하다는 어노테이션(@Autowired) 설정이 있으므로,
    Chef객체의 레퍼런스를 Restaurant객체에 주입한다. (ex00/com.koreait.sample.Resataurant.java)

/workspace/ex00/src/main/webapp/WEB-INF/spring/root-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
	<!-- ① -->
	<context:component-scan base-package="com.koreait.sample"></context:component-scan>
</beans>

/workspace/ex00/src/main/java/com/company/sample/Chef.java

package com.koreait.sample;

import org.springframework.stereotype.Component;

import lombok.Data;

/*②*/
@Component //스프링에게 해당 클래스가 스프링에서 관리해야 하는 대상임을 표시
@Data //Lombok의 setter를 생성하는 기능을 사용하기 위함과 생성자, toString()등을 자동으로 생성하기 위함
public class Chef {
}

/workspace/ex00/src/main/java/com/company/sample/Restaurant.java

package com.koreait.sample;

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

import lombok.Data;
import lombok.Setter;

/* ⓶ */
@Component // 모델 객체에서만 컴포넌트 사용
@Data
public class Restaurant {
    /* ⓷ */

    /* onMethod 속성은 생성되는 setChef에 @Autowired 어노테이션을 추가하도록 할 때 사용된다.
     * 버전에 따라 onMethod 혹은 onMethod_를 사용하게 된다. */
    @Setter(onMethod_ = @Autowired)
    private Chef chef;
}

테스트 서버 실행 코드

package com.koreait.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.Log4j;

// 테스트 코드가 스프링을 실행
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")// 지정된 클래스나 문자열을 이용해서 필요한 객체들을 스프링 내에 객체로 등록
@Log4j
public class SampleTests {

    @Setter(onMethod_ = @Autowired)
    private Restaurant restaurant;

    @Test
    public void testExist() {
        assertNotNull(restaurant); // restaurant가 null이 아니어야만 테스트 성공

        log.info(restaurant);
        log.info("-==================");
        log.info(restaurant.getChef());

//        INFO : com.koreait.sample.SampleTests - Restaurant(chef=Chef(name=null))
//        INFO : com.koreait.sample.SampleTests - -==================
//        INFO : com.koreait.sample.SampleTests - Chef(name=null)

        /*
         * 1. 테스트 코드가 실행되기 위해서 스프링 프레임워크가 동작.
         * 2. 동작하는 과정에서 필요한 객체들이 스프링에 등록
         * 3. 의존성 주입이 필요한 객체는 자동으로 주입이 이루어짐
         */
    }
}

WAS에 종속적이지 않다.

 


workspace/ex00/src/main/java/com/company/sample/Hotel.java

package com.koreait.sample;

import org.springframework.stereotype.Component;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@Component
@Getter
@ToString
//@AllArgsConstructor    //인스턴스 변수로 선언된 모든 것을 파라미터로 받는 생성자를 작성한다.
@RequiredArgsConstructor //특정 변수에 대해서만 생성자를 작성할 때 작성한다, @NonNull이나 final이 붙은 인스턴스 변수에 대한 생성자를 만들어 낸다.
public class Hotel {
    @NonNull
    private Chef chef;

//    public Hotel(Chef chef) {
//        super();
//        this.chef = chef;
//    }
}

HotelTests.java

package com.koreait.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.AllArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class) //테스트 코드가 스프링을 실행
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")//지정된 클래스나 문자열을 이용해서 필요한 객체들을 스프링 내에 객체로 등록
@Log4j
public class HotelTests {
    @Setter(onMethod_ = @Autowired)
    private Hotel hotel;

    @Test
    public void testExist() {
        assertNotNull(hotel);

        log.info(hotel);
        log.info("======================");
        log.info(hotel.getChef());
    }
}

 

반응형

댓글