데이터융합 JAVA응용 SW개발자 기업 채용연계 연수과정 56일차 강의 정리

misung·2022년 6월 6일
0

Spring

스프링 프레임워크 개요

프레임워크 - 뼈대를 이루는 코드들의 묶음

  • 프레임워크란 기본 뼈대로, 자동차를 만들 때 뼈대를 구성한 다음 만드는 것을 생각하면 된다.
  • 프레임워크는 방향성을 제시하고, 원하는 기능을 빠르게 만들 수 있게 한다.
  • 스프링 프레임워크는 주요기능으로 DI, AOP, MVC, JDBC 등을 제공한다.

현대차 E-GMP 처럼 스케이트보드 플랫폼을 깔아놓고 껍데기를 뭘 씌우냐에 따라 SUV가 되냐, 승용차가 되냐 등.. 그렇게 다양하게 바꿔치울 수 있음.

모듈?

  • 라이브러리
  • 프레임워크 안에 미리 만들어져 있는 기능

스프링 프레임워크 특징

현재로서는 개념들에 대해 '아 그렇구나' 하는 수준에서 넘어갈 것

POJO(Plain Old Java Object) 기반의 프레임워크

자바 객체의 라이프사이클을 스프링 컨테이너가 직접 관리하려, 스프링 컨테이너로부터 필요한 객체를 얻어올 수 있습니다.

DI(Dependency Injection)을 지원

각 계층이나 서비스들 사이 또는 객체들 사이에 의존성이 존재할 경우, 스프링 프레임워크가 서로를 연결시켜줍니다. 이는 클래스들 사이에 약한 결합을 가능케 합니다.

방송국은 방송국만 있어서 되는 게 아니라, 연예인이 필요하고, 연예인에게는 소속사가 필요하고, 소속사에는 소속사 관계자가 필요하고.. 등 A는 B없이 동작할 수 없다는 개념

기존의 경우에는 객체가 필요할 때 그때그때 생성했겠지만, 스프링 프레임워크를 사용하면서부터는 객체를 미리 생성해놓고 가져다달라고 요청하는 방식이 될 것.

AOP(Aspect Oriented Programming)를 지원

트랜잭션, 로깅, 보안 등 여러 모듈에서 공통적으로 지원하는 기능을 분리하여 사용할 수 있습니다.

확장성이 높다.

스프링 프레임워크의 소스는 모두 라이브버리들로 분리시켜 놓음으로써 필요한 라이브러리만 가져다 쓸 수 있습니다. 그리고 많은 외부 라이브러리들도 이미 스프링 프레임워크와 연동되고 있습니다.

Model2 방식의 MVC Framework를 지원

스프링 프레임워크 런타임

다양한 라이브러리가 하나로 합쳐져서 구성되어있다.
각 부분에 대한 설명은 생략

스프링의 프레임워크에서 제공하고 있는 모듈

스프링 프레임워크에서 제공하고 있는 모듈(라이브러리)를 사용하려면, 모듈에 대한 의존설정을 개발 프로젝트에서 XML 파일등을 이용해서 개발자가 직접 진행하면 된다.

스프링 컨테이너 (IoC)

스프링에서 객체를 생성하고 조립하는 컨테이너(container)로, 컨테이너를 통해 생성된 객체를 빈(Bean)이라고 부른다.

아까 위에서 설명한 것 처럼, 제어의 역전이 일어나 객체를 미리 생성해 놓고 꺼내서 사용하는 형태로 변경

스프링 개발 환경 설정

  1. 이클립스 켜고 File - Switch Workspace - 새 폴더 생성 - spring_basic 폴더 생성

  2. Window - Preferences - 검색 창에 enc 검색 이후 General/Workspace 에서 Text file encoding을 other - UTF-8로 설정

  3. 그 밑의 WEB/CSS, HTML, JSP의 Encoding들도 모두 UTF-8로 설정해주고 Apply & Close

프로젝트 생성

  1. File - New - Maven Project
  2. Create a Simple Project 체크
  3. Group Id : com.spring (spring.com을 거꾸로 지정한 것)
    Artifact Id : basic 설정 후 Finish 눌러서 생성

프로젝트 생성 후 설명

  • src/main/java : 원하는 클래스나 인터페이스를 생성하는 곳
  • src/main/resources : 내부 자원들, 스프링 컨테이너 설정 .xml 파일이라던가 DB 설정 파일들을 넣어두는 폴더
  • src/test/java, src/test/resources : 테스트용으로 사용하는 폴더. 나중에 어떻게 써먹는지 알려줄 것.
  • JRE System Library : 프로젝트 내에서 자바를 사용할 수 있도록 해 주는 시스템 라이브러리
  • src/main ... & src/test ... : test 쪽은 테스트용이라 신경쓸 필요 없고, main 쪽은 실제로 '구현' 할 내용들이 들어갈 부분들이다.
  • target : 직접 만든 클래스나 인터페이스들의 컴파일 결과물이 들어오는 곳
  • pom.xml : 라이브러리 설정 파일.

라이브러리 설치

  1. https://mvnrepository.com/ 로 이동

  2. spring-context 검색

  3. 사용 많이 하는 버전으로 고르는데. 5.3.18 버전이 가장 많이 사용되는 것 같으니, 그것으로 결정.

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.18</version>
</dependency>

이 내용을 복사 후 이클립스로 이동

  1. pom.xml에 <dependencies> 태그 열고 (닫는 태그도 있어야 함) 그 안에 위에서 복사한 내용 붙여넣기.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.spring</groupId>
  <artifactId>basic</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <dependencies>
  	<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-context</artifactId>
	    <version>5.3.18</version>
	</dependency>
  </dependencies>
</project>

대략 이런 모양이 될 것임.

  1. Ctrl+S 로 저장 시 의존성 주입에 의해 라이브러리가 웹으로부터 다운로드 될 것. 하이어라키에 보면 Maven Dependencies가 추가되고 안에 spring jar들이 추가됨.

  2. 다시 종전의 사이트로 이동해서 jstl의 가장 많은 사용을 하고 있는 버전 코드 복사.

<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
  1. <dependencies> 태그 밖에 아래와 같은 코드 추가.
<build>
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
               <source>11</source>
               <target>11</target>
               <encoding>utf-8</encoding>
            </configuration>
         </plugin>
      </plugins>
</build>
  • 이 녀석(Maven)은 자바용 프로젝트 관리 도구이다.
  • 배포를 위한 빌드 도구. 빌드 뿐만이 아니라 프로젝트의 전체적 라이프 사이클을 관리하기도 한다.
  • 필요한 라이브러리를 특정 문서 (pom.xml)에 정의해서 사용할 라이브러리, 해당 라이브러리를 동작하기 위해 필요한 부가 라이브러리까지 관리하여 자동으로 다운로드를 받아 준다.
  • 스프링 프로젝트도 Maven 플랫폼을 기반으로 한다.
  1. 사용하기 전에, Maven 버전이 일치하지 않는 문제가 발생할텐데 버전 업데이트를 위해 Alt + F5를 누르거나,
    프로젝트명 우클릭 후 - Maven - Update Project 에 진입할 것. 그 후 뜨는 창에서 OK를 눌러 빌드할 것.

아마 JRE 문제나 버전 문제가 발생할 수 있는데,
이클립스가 2020-06 이후의 버전인 경우 JAVA 11 버전이 요구되므로 JAVA SE8 버전으로 프로젝트를 진행하려는 경우 문제가 될 수 있으니 이클립스를 2020-06 버전을 사용하면 됨.

그리고 그래도 문제 생긴다 싶으면 프로젝트 우클릭 - properties - Java Build Path - Libraries - 여기서 JRE 버전이 1.8이 아닌 경우 삭제한 다음 - Add Libraries - JRE System Library - Execution environment 에서 JAVASE 1.8 해주면 됨.

실습

SpringTest.java

src/main/java 에 생성. 자동으로 basic 패키지 안에 생성될 것.

package basic;

public class SpringTest {
	public void hello() {
		System.out.println("스프링 객체 주입 테스트 : 하이요~");
	}
}

HelloSpring.java

똑같은 위치에 생성하되, main을 체크한 상태에서 생성.

package basic;

public class HelloSpring {

	public static void main(String[] args) {
		/*
			기존의 객체를 선언하고 사용하던 방식.
			SpringTest test = new SpringTest();
			test.hello();
		*/
		
	}

}

기존의 객체를 선언하고 사용하던 방식은 이랬지만, 이제는 이런 식으로 사용하게 되진 않을 것임.

test-config.xml

src/main/resources 에 xml 파일 생성
생성 후 파일 눌러본 후, Design 탭 말고 Source 탭으로 이동.

그리고 이동한 탭(소스코드 창)에 아래 코드 붙여넣기

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans  
http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- 스프링 컨테이너 내에 디자인한 객체 클래스를 등록 -->
	<bean id="test" class="basic.SpringTest"/>
</beans>

Maven Dependencies에 스프링에 필요한 핵심 객체를 받아놓긴 했는데, 그 안의 내용(문법)을 사용하기 위해 네임스페이스를 지정하는 부분이 바로 위의 코드이다.

나중에 스프링 프로젝트를 할 때는, 알아서 스프링쪽에서 다 해주지만 현재는 메이븐 프로젝트부터 접근하고 있으므로 직접 붙여넣는 과정이 필요하다. 물론 저 태그를 외우지는 않아도 된다.

<!-- --> 아래 부분은 붙여넣기하지 않고 직접 작성했던 부분이긴 한데, 아까 만들었던 SpringTest 클래스를 등록하는 과정의 부분이다.

HelloSpring.java 수정

package basic;

import org.springframework.context.support.GenericXmlApplicationContext;

public class HelloSpring {

	public static void main(String[] args) {
		/*
			기존의 객체를 선언하고 사용하던 방식.
			SpringTest test = new SpringTest();
			test.hello();
		*/
		
		// classpath라고 씀으로서 한번에 src/main/resources를 지정할 수 있음.
		GenericXmlApplicationContext ct =
				new GenericXmlApplicationContext("classpath:test-config.xml");
		
		// "test" 는 등록된 객체의 ID를 지정한 것이다. 아까 xml에 id="test" 라고 써져 있었다.
		SpringTest st = ct.getBean("test", SpringTest.class);
		st.hello();
		
		ct.close();
	}

}

전체를 다 외우려 하진 말고 어떤 식의 흐름인지 이해하기를 바람.

이전에 new 키워드를 이용해 새로 객체를 만들어 쓰는 것과 달리, xml에 등록해 놓고, 그대그때 가져다 쓰는 방식으로 변했음을 알아야 한다.

DI (Spring DI/IoC)

Java의 Class 상속 / Interface 를 이용한 추상화를 기반으로 하는 개발 방법. Spring은 아래 DI/IoC를 강력하게 지원하는 프레임워크.

IoC : Inversion of Control

프로그램을 제어하는 패턴 중 하나.
DI는 IoC 패턴의 구현 방법중 하나.
DI에 따라 프로그램의 흐름이 완전히 변경됨.

사진을 아까 보기도 했고, 방금 실습에서 한 예제가 미리 생성해놓고 쓰는 것이기 때문에 이해가 좀 갈 것이다.

DI : Dependency Injection

스프링 Container에 만들어둔 각종 클래스(bean)들은 서로 의존적이다.
A객체가 B객체 없이 동작이 불가능한 상황

스프링은 DI를 기준으로 많은 프레임워크 모듈들이 만들어짐.

Spring은 DI Framework 혹은 IoC Framework 라고 부른다.

DI란?

배터리 일체형

CarToy 클래스는 Battery 클래스를 들고 있다.
객체를 처음 생성할 때 battery가 생성되지만, 외부에서 battery에 접근할 방법이 없으므로 교체가 불가하다.

배터리 분리형

여기서는 setter() 메서드가 존재하므로 새 배터리를 전달하여 교체하면 된다.

배터리 탈부착형

기존에 쓰던 배터리를 리턴받을수도 있도록 만든다.

실습

Hotel.java

basic 패키지 밑에 basic.ex01 패키지 만들고 그 아래에 Hotel.java 만들 것.

 package basic.ex01;

public class Hotel {
	
	private Restaurant res;
	
	public Hotel(Restaurant res) {
		System.out.println("호텔이 생성됨!");
		this.res = res;
	}
	
	public void reserveRestaurant() {
		System.out.println("레스토랑을 예약합니다.");
		res.orderDinner();
	}
}

Restaurant.java

package basic.ex01;

public class Restaurant {
	
	private Chef chef;
	
	public Restaurant() {
		System.out.println("레스토랑이 생성됨!");
	}
	
	public void setChef(Chef chef) {
		this.chef = chef;
	}
	
	public void orderDinner() {
		System.out.println("저녁 식사를 주문받습니다.");
		chef.cook();
	}
}

Chef.java

package basic.ex01;

public class Chef {
	public Chef() {
		System.out.println("요리사가 생성됨!");
	}
	
	public void cook() {
		System.out.println("요리사가 요리를 합니다.");
	}
}

MainClass.java

package basic.ex01;

public class MainClass {

	public static void main(String[] args) {
		/*
		 	도중에 nullpointerexception 남.
		 	호텔 객체는 있지만 레스토랑부터 객체가 존재하지 않으므로.
		 	
		 	그래서 각 클래스들의 내부를 좀 많이 고쳐서 해결했지만,
		 	스프링에서는 이런 식으로 사용하지는 않을 것이다.
		*/
		Chef chef = new Chef();
		Restaurant res = new Restaurant();
		res.setChef(chef);
		Hotel hotel = new Hotel(res);
		hotel.reserveRestaurant();
	}

}

원래 Hotel에는 생성자에서 Restaurant 를 받아오지 않았고, Restaurant에서는 Chefset()하는 메서드가 없었다.

그렇게 되면 순차 호출 시 레스토랑 객체가 생성되어 있지 않아 NullPointerException 이 발생하고, 게다가 셰프도 없어서 잘 돌아갈 리가 없다.

그래서 어떻게든 돌아가게 하려면 레스토랑 생성 이전에 셰프부터 만들어놓고 레스토랑을 만들면서 셰프를 설정하고, 그 다음에 호텔을 생성하면서 레스토랑을 집어넣어줘야 한다.

하지만 스프링에선 이런 식으로 사용하지는 않을 것이다.

Spring 에서 하는 방식으로 변경

testConfig.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans  
http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- 스프링 컨테이너 내에 디자인한 객체 클래스를 등록 -->
	<bean id="test" class="basic.SpringTest"/>

	<!-- Hotel 객체와 의존객체들의 빈 등록 및 의존성 주입 -->
	<bean id="chef" class="basic.ex01.Chef"/>
	
	<!-- 
		property name="set을 제외한 setter 메서드의 이름" 이 들어간다.
		setter 메서드의 이름은 대부분 관례적으로 set + 멤버변수 이름이기 때문에,
		변수명이라고 편하게 얘기했다. 사실은 setter 메서드의 이름이 들어가는 것이 맞다.
	 -->
	<bean id="res" class="basic.ex01.Restaurant">
		<property name="chef" ref="chef"/>
	</bean>
	
	<bean id="hotel" class="basic.ex01.Hotel">
		<constructor-arg ref="res"/>
	</bean>
</beans>

셰프는 따로 해당 클래스에서 들고 있는 녀석이 없으므로 혼자만 등록시켜 둔다.

의존성 주입 방법 2가지

"변수명" 에는 엄밀히 말해서는 setter() 의 이름이 들어가야 한다.

값으로 설정하는 경우에는 int, String 등의 값을 전달하고, 객체를 전달해야 하는 경우 ref에 객체를 전달하여 미리 주입시켜 두면 된다.

스프링 설정 파일에 추가

이건 따로 위에서 이미 했던 부분이긴 한데, 각 부분에 대한 간략한 설명은 위와 같다. 외울 필요 없음!

0개의 댓글