Day 82

ChangWoo·2022년 12월 29일
0

중앙 HTA

목록 보기
26/51

SPRING

스프링

  • 오픈소스 프레임워크다.
    • 오픈소스 : 라이센스 무료, 가공/수익창출 허용
    • 프레임워크 : 특정한 아이디(개발방식, 개발패턴, 아키텍처)의 구현체다.
      • 라이브러리와 프레임워크
        • 라이브러리 : 개발에 필요한(자주 사용되는) 기능의 구현체다.
          필요한 기능이 구현되어 있는 라이브러리를 다운받아서 그 라이브러리의 기능을 사용한다.
        • 프레임워크 : 개발방식, 개발 패턴의 구현체다.
          개발자는 해당 프레임워크에 제시하는 방식에 맞게 클래스나 인터페이스, 환경설정 정보를 구성하면 프레임워크가 제공하는 기능을 제공받을 수 있다.
  • JaVa 기반의 엔터프라이즈 애플리케이션 개발을 지원하는 프레임워크다.
  • DI(의존성 주입)의 구현체다.
    * 의존성 주입은 스프링의 가장 핵심적인 개념이다.
    • 인터페이스를 이용해 클래스와 클래스간의 결합을 느슨하게 유지하고, 의존성 주입으로 의존하는 객체를 주입한다면, 코드의 변경없이 의존하는 객체를 변경할 수 있다.
    • 즉, 확정성이 매우 뛰어난 애플리케이션을 개발할 수 있다.
  • AOP(관점지향 프로그래밍)의 구현체다.
    * 관점지향 프로그램은 프로그램의 공통관심사항을 핵심기능으로부터 분리시키는 것이다.
    • 관점은 코드를 바라보는 시각이다. ("메소드 안에 무엇이 있지?"로 보는 것)
    • 공통관심사항 = 모든 메소드 안에 공통적으로 포함되어 있는 것 Ex)로그 출력
    • 핵심관심사항 = 각 메소드 안에 있는 다른 메소드와 다른 것 Ex)
    • 공통관심사항을 제거하는 것!
    • 관점은 코드를 핵심관심사항(핵심기능)과 공통관심사항(공통기능)으로 구분하는 것이다.
    • 스프링의 AOP는 공통관심사항을 별도의 모듈(Advice와 Pointcut)로 개발하고, 공통관심사항이 적용될 대상과 시점을 지정하면 핵심기능이 구현된 메소드가 실행될 때마다 공통기능을 실행시킨다.
    • 즉, 메소드에서 공통관심사항 코드를 제거할 수 있다. (중복코드의 제거)
  • 스프링은 객체를 생성하는 공장이다. (Bean Factory다. Bean은 객체다.)
  • 스프링은 객체를 조립한다.(객체간의 의존관계를 분석해서 필요로 하는 객체를 주입한다.)

스프링 컨테이너

- 애플리케이션에서 사용되는 객체의 라이프사이클(객체 생성, 조립, 유지/관리)을 관리한다.
- 스프링 컨테이너의 종류
	BeanFactory
    	spring-bean.jar에 포함되어 있는 스프링 컨테이너 인터페이스다.
        객체 생성, 객체 조립과 같은 간단한 기능만 제공하는 스프링 컨테이너다.
        구현클래스 : XmlBeanFactory
    ApplicationContext
    	spring-context.jar에 포함되어 있는 스프링 컨테이너 인터페이스다.
        객체 생성, 객체 조립, 관점지향 프로그래밍 지원, 국제화, EJB 연동 등 다양한 기능을 제공하는 스프링 컨테이너다.
        구현 클래스 : ClasspathXmlApplicationContext, FilesystemXmlApplicationContext, GenericXmlApplicationContext, WebApplicationContext
    WebApplicationContext
    	spring-web.jar에 포함되어 있는 스프링 컨테이너 인터페이스다.
        ApplicationContext 인터페이스와 기능은 유사하고, 웹 환경에 최적화되어 있는 스프링 컨테이너 인터페이스다.
        구현 클래스 : XmlWebApplicationContext
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] [%-5level] %logger{36}.%M - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
spring/context-1.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 class="com.sample.controller.UserController"></bean>
	<bean class="com.sample.dao.UserOracleDao"></bean>
	
</beans>
App1.java
package com.sample.app;

	import org.springframework.context.ApplicationContext;
	import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App1 {

	public static void main(String[] args) {
		// 스프링 설정파일의 경로
		String resource = "spring/context-1.xml";
		// 스프링 컨테이너 생성하기
		ApplicationContext ctx = new ClassPathXmlApplicationContext(resource);
	}
}

실행결과

실행결과(id를 입력했을 때)

context-1.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="userContoller" class="com.sample.controller.UserController"></bean>
		<bean id="userOracleDao" class="com.sample.dao.UserOracleDao"></bean>
	
</beans>

  • 스프링은 따로 지정하지 않으면, 싱글턴 객체로 만든다.
OrderController

package com.sample.controller;

import com.sample.dao.OrderOracleDao;
import com.sample.dao.UserOracleDao;

public class OrderController {

	private OrderOracleDao orderOracleDao;
	private UserOracleDao userOracleDao;
	
	public void setOrderOracleDao(OrderOracleDao orderOracleDao) {
		this.orderOracleDao = orderOracleDao;
	}
	public void setUserOracleDao(UserOracleDao userOracleDao) {
		this.userOracleDao = userOracleDao;
	}
	
	public void test() {
		System.out.println("### OrderController 객체에 조립된 객체 확인하기");
		System.out.println(orderOracleDao);
		System.out.println(userOracleDao);
	}
}
context-1.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="userContoller" class="com.sample.controller.UserController">
	<!-- 
		<bean>은 객체 생성 태그 / <property>는 객체 조립하는 태그
		"userController"에 있는 userOracleDao에게 "userOracleDao"의 userDao를 참조하게 한다.
	 -->
		<property name="userOracleDao" ref="userDao"></property>
	</bean>
	
	<bean id="orderController" class="com.sample.controller.OrderController">
		<property name="orderOracleDao" ref="orderDao"></property>
		<property name="userOracleDao" ref="userDao"></property>
	</bean>
	
	<bean id="userDao" class="com.sample.dao.UserOracleDao"></bean>
	<bean id="orderDao" class="com.sample.dao.OrderOracleDao"></bean>
	
</beans>
App1.java
package com.sample.app;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sample.controller.OrderController;
import com.sample.controller.UserController;

public class App1 {

	public static void main(String[] args) {
		// 스프링 설정파일의 경로
		String resource = "spring/context-1.xml";
		// 스프링 컨테이너 생성하기
		ApplicationContext ctx = new ClassPathXmlApplicationContext(resource);
		
		// 스프링 컨테이너에서 객체 가져오기
		UserController controller = ctx.getBean(UserController.class);
		controller.test();
		
		OrderController controller2 = ctx.getBean(OrderController.class);
		controller2.test();
	}
}

실행 결과

실행 과정

  • 스프링 컨테이너는 설정정보를 저장해서 조립을 해준다.
  • 의존성 주입을 사용하였다!

DI(의존성 주입)

의존성 주입을 사용하지 않은 예

의존성 주입을 사용한 예

  • @Autowired 라는 것을 통해 의존성을 조사한다.
  • 필요한 객체를 상관하지 않고 로직 구현만 신경쓸 수 있게 된다.

의존성 주입을 사용하지 않았을 때

  • 여러개의 클래스가 존재한다.
  • DB를 변경하게 되면, 기존의 클래스를 사용하지 못한다.
  • DB를 변경하게 되면, 소스코드를 변경해야 한다.
  • 매 번 바꿀 수는 없다. (유연성 / 확장성이 떨어진다.)

의존성 주입을 사용했을 때

  • 인터페이스를 생성
    (생성 목적 : 사용방법을 통일시키기 위해 / 구현객체를 JaVa코드 변경 없이 교체할 수 있다.)
  • UserDao 인터페이스 내부에는 UserDao 속성이 포함되어 있다.
  • Spring에 객체 생성을 의뢰 구현 클래스(UserController / OrderController / UserOOODao)
  • @Autowired가 있으면 그 타입의 객체를 찾는다.
  • 구현 클래스는 각 DB에 맞게 생성되었다.
  • 그러나 다른 종류의 DB로 변경해도 Spring의 설정 변경을 통해 다른 DB의 구현클래스를 생성을 의뢰할 수 있다.
  • 그렇게 코드 변경 없이 사용하는 객체를 변경할 수 있다.

주의 점

  • 인터페이스에 의존해야 한다!
  • Controller에 구체적인 클래스 이름이 등장하지 않아야 한다.(직접 만들면 안된다!)
  • 클래스가 클래스를 의존하게 하면 안된다! (인터페이스를 의존해야 한다!)
  • 인터페이스를 의존해야 어떤 DB와도 연결이 가능하다.

핵심

  • controller가 의존하는 객체를 코드 변경 없이 변경할 수 있다!
  • controller는 직접 클래스(객체)생성을 하면 안된다.
  • controller가 구체적인 클래스를 의존하게 하면 안된다.(인터페이스를 의존해야 한다.)
  • 클래스-클래스 간의 의존(강한 결함)x , 클래스-인터페이스 간의 의존(느슨한 결합)O

AOP(관점지향 프로그래밍)

  • 주황색 코드 : 모든 메소드 안에 공통적으로 포함되어 있는 것. (공통관심사항)
  • 빨강색/파랑색/초록색/보라색 코드 : 각 메소드 안에 있는 다른 메소드와 다른 것 (핵심관심사항)
  • 이러한 공통관심사항과 핵심관심사항을 나누고 공통관심사항을 핵심관심사항으로부터 분리시키는 것이 관점지향 프로그래밍이다.
  • 기존에는 공통관심사항이 존재한다. But, 아예 삭제는 불가능하다!(공통관심사항도 사용해야 하기 때문에)
  • 그래서, 공통관심사항을 전부 다 제거하고 핵심관심사항만 남긴다.
  • 그리고, "Advice"라는 특별한 클래스를 만든다.

Advice클래스

  • 로그/TransactionManager를 만들고 각각의 공통관심사항이 포함된 Advice 클래스를 만든다.
  • 각각의 프로그램에 Target을 지정한다.
  • Target은 어떤 Advice 적용 대상을 지정해준다.
  • Advice와 Target은 한 세트!

Advice의 작성 예

  • "@Aspect"(관점)을 적는다.
  • "@Autowired"(의존성 주입)를 적는다.
  • 공통관심사항 실행시점(@Before) : ~전에
  • 공통관심사항 적용대상("within(com.sample.service.'Service)") : (com.smple.service 클래스 안의 모든 Servcie가 실행 될 때)
  • 공통 관심사항(public void logging() {logger.info("로그출력")}) : (실행해라.)
  • 스프링의 관점지향 프로그래밍
    - AOP관련 @어노테이션을 이용해서 설정한다.
    - @Aspect: 관점지향 프로그래밍 관련 객체임을 나타내는 어노테이션이다.
    - @Before: 공통관심사항을 실행할 시점을 나타내는 어노테이션이다.
    - @Before, @After, @AfterReturning, @AfterThrowing, @Around
    - "within(com.sample.service."Service)" : 포인트컷(Pointcut Expression)이다.
    - 포인트컷은 공통관심사항 적용대상을 나타내는 표현식이다.
    - 예제의 표현식은 패키지명이 com.sample.service이고,
    - 클래스명이 Service로 끝나는 모든 클래스의 메소드가 적용대상이다.
  • 핵심기능이 구형된 메소드에서 공통관심사항 코드를 제거할 수 있다.(코드중복이 제거된다.)
  • 핵심기능이 구현된 메소드의 코드 변경없이 공통관심사항을 추가/삭제할 수 있다.
  • 핵심기능에 대한 유지 보수가 쉬워진다.
  • 핵심기능의 재사용성도 높아진다.
    (핵심기능밖에 없어도 특별한 라이브러리(로그출력라이브러리 등))

Maven

- 자바의 프로젝트 관리 도구다.
- 프로젝트의 라이브러리 의존성, 소스 커파일, 패키징, 배포 등의 작업을 자동화 할 수 있다.
- 프로젝트 생성/관리하는 도구다.
	* 메이븐 프로젝트는 pom.xml 파일을 포함하고 있다.
    	- pom.xml 파일은 프로젝츠 정보를 표현하는 파일이다.
        - pom.xml 파일은 프로젝트의 최상위 폴더에 위치하고 있다.
        - pom.xml의 POM(Porject Object Model)을 설정하는 파일이다.
        - POM은 메이븐에서 프로젝트를 표현하는 객체다.
* pom.xml의 주요 구성 요소
	- 프로젝트 정보
    	<groupId />
        	프로젝트를 생성하는 조직 또는 그룹명을 나타낸다.
            보통 URL의 역순으로 지정한다.
        <artifactId />
        	프로젝트의 고유한 아이디다.
            프로젝트 산출물의 교유한 아이디다.
            프로젝트의 명과 같은 이름이다.
        <version />
        	애플리케이션의 버전을 나타낸다.
            release는 출시 버전 /
        <packaging />
        	프로젝트 패키징 유형을 나타낸다.
            jar, war, ear, pom 중 하나를 지정한다. 지정하지 않으면 jar다.
        <name />
        	프로젝트 명이다.
        <description />
        	프로젝트에 대한 설명이다.
        <url />
        	프로젝트를 찾을 수 잇는 URL이다.
        <properties />
        	pom.xml에서 중복해서 사용되는 설정값을 지정한다.
    
    - 의존성 라이브러리 정보
    	의존성 라이브러리를 정의하는 부분이다.
        프로젝트에서 사용하는 라이브러리 정보를 정의한다.
        라이브러리정보는 groupId, artifactId, version 정보가 필요하다.
   
   - 빌드 정보
		프로젝트의 빌드/배포와 관련된 설정정보를 정의하는 부분이다.

제일 중요한 것은 스프링의 의존성 주입과 관점지향 프로그래밍이다!

profile
한 걸음 한 걸음 나아가는 개발자

0개의 댓글