본문 바로가기

교육 및 세미나/신입사원 교육

11일차(2018.01.17)

Spring

AOP(Aspect Oriented Programming) :관점지향프로그래밍

AOP는 어플리케이션 코드에 산재해서 나타나는 부가적인 기능을 독립적인 상태로 모듈화하는 프로그래밍 모델이다. 스프링은 AOP를 이용해서 다양한 엔터프라이즈 서비스를 적용하고도 깔끔한 코드를 유지할 수 있게 해준다. 관점 지향이 객체 지향 프로그램 안에 포함되어 있다고 생각할 수 있도록 하자. 주 업무와 보조 업무를 횡으로 나누는 작업이 포함된다.

OOP > (AOP + α)

- 기술 API

스프링은 엔터프라이즈 어플리케이션 개발의 다양한 영역에 바로 적용할 수 있는 방대한 양의 기술 API를 제공한다. UI 작성은 물론이고, 웹 프레젠테이션 계층, 비즈니스 서비스 계층, 기반 서비스 계층, 도메인 계층, 데이터 액세스 계층 등에서 필요한 주요 기술을 스프링에서 일관된 방식으로 사용할 수 있도록 지원해주는 기능과 전략 클래스를 제공한다.

스프링이 제공하는 API 와 지원 기술은 모두 스프링 프로그래밍 모델에 따라 작성되었기 때문에 이것들을 가져다 쓰는 것 만으로도 스프링 프로그래밍 모델을 코드에 자연스럽게 적용할 수 있다.

스프링의 모든 기술은 표준 자바 엔터프라이즈 플랫폼(Java EE) 에 기술을 두고 있다. 표준 기술과 더불어 유명 오픈소스 기술과 주요 상용 기술에 대한 지원 기능도 다양하게 제공된다.

스프링 프레임워크(Spring Framework) 의 주요 기능과 특징

1. 경량 컨테이너

자바 객체를 담고, 이들 자바 객체의 생성과 소멸의 라이프 사이클을 관리.

2. DI(Dependency Injection)

의존성(관계) 주입(삽입)을 지원.

설정 파일을 통해 객체간의 의존 관계를 정의.

3. AOP(Aspect Oriented Programming) 지원.

관점 지향 프로그래밍을 지원.

여러 모듈에 공통적으로 사용되는 기능을 분석 / 분리하여 각 모듈에 적용하는 것이 가능.

4. POJO 지원

가장 기본적인 자바 객체를 지원하여 기존 작성 코드의 유지성을 향상.

※ POJO(Plain Old Java Object) : 상속 X, 인터페이스 X, 순수하게 우리가 알고있는 클래스의 개념.

5. 트랜잭션 처리

JDBC 나 JTA 를 사용하는 설정 파일을 통해 트랜잭션을 관리하여 동일한 코드를 여러 환경에서 사용하도록 하는 것이 가능.

6. 다양한 프레임워크와의 조합

ibatis, hibernate, struts, JPA, JDO, JMS, Quertz 등 다른 프레임워크 뿐 아니라 사용자가 만든 프레임워크와의 연동성을 제공한다.

스프링 프레임워크(Spring Framework)에서 가장 중요한 개념

DI (Dependency Injection, 의존관계주입, 의존성주입)

객체를 생성하고 관리하는 의존성에 대해서 어떻게 처리하는가에 대한 개념

IoC (Inversion of Control, 제어의 역전, 역제어

인스턴스 생성부터 소멸까지의... 인스턴스 생명 주기 관리를 우리가 직접하는 것이 아니라 (스프링)컨테이너가 대신 해주는 개념.

스프링 프레임워크(Spring Framework) 를 이용한 주요 모듈

AOP

관점 지향 프로그래밍 방식

Web-MVC

웹 어플리케이션에서 MVC 모델을 구축해주는 모듈

JDBC

데이터베이스와 연동을 지원하는 모듈

Security

처리 과정의 보안을 설정하고 지원하는 모듈

Spring Framework 환경설정

1. 스프링 프레임워크(Spring Framework) 구성을 위해 스프링 프레임워크 관련 파일을 다운로드 받는다. URL → http://www.spring.io

- 기존 메뉴들이 변경되어 직접 수동으로 다운로드 받을 수 있는 경로를 제공하지 않는다. URL → http://docs.spring.io/downloads/nightly/release-downloads.php?project=SPR

- 리스트 형식으로 제공되던 파일 목록 또한 더 이상 제공하지 않는다. ※ 스프링 구성 버전 및 파일들 중... 적용 및 테스트(실습) 가 원활한 버전으로 개별 제공 spring-framework-3.0.2.RELEASE-dependencies.zip

→ 기본적인 스프링 프레임워크 구성에 필요한 필수적인 jar 파일과 스프링 프레임워크 설명문서(pdf 버전, html 버전)가 포함된 항목. 즉, 스프링 원래의 기본 jar 파일들. spring-framework-3.0.2.RELEASE-with-docs.zip

→ 스프링 프레임워크 구성에 의존성을 가진 jar 파일들이 포함된 항목. 어떤 기능을 수행해야 하는가에 따라 추가적으로 필요한 항목. 스프링이 참조하는 의존 jar 파일들.

※ 주의.

다운로드를 수행한 두 개의 압축 파일은 디렉터리 경로가 복잡하지 않은 곳으로 옮겨 압축을 해제할 것을 권장한다. (압축파일의 이름 경로 포함) 그렇지 않으면 경로 및 이름이 너무 긴 관계로 압축 해제 과정에서 에러 발생할 수 있다.

Spring DI 실습 01 (일반 버전)

- 콘솔 기반 프로젝트

- 성적 처리

- 국어, 영어, 수학 점수를 입력받아서 총점과 평균을 산출하는 프로그램

- 물리적인 프로그램 구성

· Record.java

  • 인터페이스
/*===============
 	Record.java
	- 인터페이스
	첫번째
 ================*/

package com.test.spr;

public interface Record
{
	public void setKor(int kor);
	public int getKor();
	
	public void setEng(int eng);
	public int getEng();
	
	public void setMat(int mat);
	public int getMat();
	
	public int getTotal();
	
	public double getAng();

}

· RecordImpl1.java

  • Record 인터페이스를 구현하는 클래스로 설계
  • 외부에서 국어, 영어, 수학 점수를 전달받아 총점, 평균을 연산하는 클래스로 설계
/*=============================================
 RecordImpl1.java
 - Record 인터페이스를 구현하는 클래스로 설계
 - 외부에서 국어, 영어, 수학 점수를 전달받아
   총점, 평균을 연산하는 클래스로 설계
   세 번째
 ==============================================*/

package com.test.spr;

public class RecordImpl1 implements Record
{
	private int kor, eng, mat;

	@Override
	public int getKor()
	{
		return kor;
	}

	@Override
	public void setKor(int kor)
	{
		this.kor = kor;
	}

	@Override
	public int getEng()
	{
		return eng;
	}

	@Override
	public void setEng(int eng)
	{
		this.eng = eng;
	}

	@Override
	public int getMat()
	{
		return mat;
	}

	@Override
	public void setMat(int mat)
	{
		this.mat = mat;
	}

	@Override
	public int getTotal()
	{
		int result = 0;
		
		// 총점 연산과 관련한 액션 처리
		result = this.getKor() + this.getEng() + this.getMat();
		
		return result;
	}

	@Override
	public double getAng()
	{
		double result = 0;
		
		//평균 연산과 관련한 액션 처리
		result = this.getTotal() / 3.0; //  double result = 10/3 하면 몫만 나타내서 3.0의 결과값이 나옴
		
		return result;
	}
	
	
}

· RecordImpl2.java

  • Record 인터페이스를 구현하는 클래스로 설계
  • 외부에서 국어, 영어, 수학 점수를 전달받아 총점, 평균을 연산하는 클래스로 설계
/*=============================================
 RecordImpl2.java
 - Record 인터페이스를 구현하는 클래스로 설계
 - 외부에서 국어, 영어, 수학 점수를 전달받아
   총점, 평균을 연산하는 클래스로 설계
   세 번째
 ==============================================*/

package com.test.spr;

public class RecordImpl2 implements Record
{
	private int kor, eng, mat;

	@Override
	public int getKor()
	{
		return kor;
	}

	@Override
	public void setKor(int kor)
	{
		this.kor = kor;
	}

	@Override
	public int getEng()
	{
		return eng;
	}

	@Override
	public void setEng(int eng)
	{
		this.eng = eng;
	}

	@Override
	public int getMat()
	{
		return mat;
	}

	@Override
	public void setMat(int mat)
	{
		this.mat = mat;
	}

	@Override
	public int getTotal()
	{
		int result = 0;
		
		// 총점 연산과 관련한 액션 처리
		result = this.getKor() + this.getEng() + this.getMat() + 50;
		// -- RecordImpl1 과 다르게 기본점수를 50점 부여하는 방식으로 정책을 설정한다.
		
		return result;
	}

	@Override
	public double getAng()
	{
		double result = 0;
		
		//평균 연산과 관련한 액션 처리
		result = this.getTotal() / 4.0; //  double result = 10/3 하면 몫만 나타내서 3.0의 결과값이 나옴
		// -- 기본 점수가 추가된 사항으로 평균을 종합할 수 있도록 정책을 설정한다.
		
		return result;
	}
	
	
}

· RecordView.java

  • 인터페이스
/*========================
	RecordView.java
	- 인터페이스
	두 번째
 =========================*/
package com.test.spr;

public interface RecordView
{
	// 입력 액션 전용 메소드
	public void input();
	
	// 출력 액션 전용 메소드
	public void output();
	
	// ★ 의존 객체를 주입받기 위한 준비
	// --> setter 메소드 준비
	public void setRecord(Record record); // -- setter Injection
	// -- 매개변수에는 의존객체의 인터페이스 자료형을 지정~!!!
	
	// 레코드타입을 넘겨받으려는 메소드
	// 인터페이스를 매개변수로 받게되면
	// public void setRecord(강원도 횡성 사는 운성); 이 아니라
	// public void setRecord(사람); 으로 받는다.
}

· RecordViewImpl1.java

  • RecordView 인터페이스를 구현하는 클래스로 설계
/*===================================================
	RecordViewImpl.java
	- RecordView 인터페이스를 구현하는 클래스로 설계
 ====================================================*/

package com.test.spr;

import java.util.Scanner;

public class RecordViewImpl implements RecordView
{
	// 의존객체를 저장하기 위한 멤버 변수 준비
	private Record record;
	// -- 데이터타입을 인터페이스 형 자료형을 취할 수 있도록 준비
	//    런 타임 시에는 이 변수에 RecordImpl1 또는 RecordImpl2 객체가 주입(전달)될 예정

	// 외부로부터 의존객체를 주입받기 위한 준비 (DI)
	@Override
	public void setRecord(Record record)
	{
		this.record = record;
	}

	@Override
	public void input()
	{
		// 콘솔을 통해 외부로부터 데이터 입력받는 액션 처리
		Scanner sc = new Scanner(System.in);
		
		System.out.print("국어 점수 입력 : ");
		int kor = sc.nextInt();
		System.out.print("영어 점수 입력 : ");
		int eng = sc.nextInt();
		System.out.print("수학 점수 입력 : ");
		int mat = sc.nextInt();
		
		// 입력받은 데이터를 Record 객체에 전달
		// Record 객체 필요.
		// Record(의존객체 - RecordImpl1 또는 RecordImpl2) 를
		// 외부로부터 주입받을 예정.
		// ==> DI(Dependency Injection)
		
		record.setKor(kor);
		record.setEng(eng);
		record.setMat(mat);
		
		sc.close();
		
	}

	@Override
	public void output()
	{
		// 산출된 결과를 출력하는 액션 처리
		// Record 객체 필요.
		// Record(의존객체 - RecordImpl1 또리 RecordImpl2)를
		// 외부로부터 주입받을 예정.
		// ==> DI(Dependency Injection)
		System.out.println("국어  영어  수학  총점 평균");
		System.out.printf("%3d  %4d  %4d  %5d  %3.1f%n"
				             , record.getKor(), record.getEng(), record.getMat()
				             , record.getTotal(), record.getAng());
	}


}

· Main.java

  • main() 메소드를 포함하는 외부 클래스
/*================================================
	Main.java
	- main() 메소드를 포함하는 외부 클래스
================================================== */

package com.test.spr;

public class Main
{

	public static void main(String[] args)
	{
		// [ 스프링이 관리하게 될 영역 ]
		// -----------------------------------------------------------------------------
		// RecordImpl1 (→ Record 인터페이스를 구현하는 클래스) 객체 생성
		// Record record = new RecordImpl1();
		
		// RecordImpl1 (→ Record 인터페이스를 구현하는 클래스) 객체 생성
		Record record = new RecordImpl2();
		
		// RecordViewImpl (→ RecordView 인터페이스를 구현하는 클래스) 객체 생성
		// Record 객체(의존객체 - RecordImpl1 또는 RecordImpl2) 필요
		RecordView view = new RecordViewImpl();
		
		// ★ 의존객체 주입
		// -- 의존객체 주입 방법을 사용하게 되면
		//    느슨한 결합을 구성할 수 있게 되고,
		//    한 쪽의 변동 상황이 다른 쪽에 영향을 덜 줄 수 있게 된다.
		view.setRecord(record);
		
		// -----------------------------------------------------------------------------
		
		view.input();
		view.output();
		
	}

}

Spring DI 실습 02 (데이터베이스 포함 버전)

- 콘솔 기반 프로젝트

- 오라클 데이터베이스에 대해서 원격 서버와 로컬 서버를 동시에 사용할 수 있도록 설정.

- 물리적 파일 구성

· MemberDTO.java

  • 데이터 전송 및 저장을 위한 자료형 클래스로 설계
/*==========================================================
	MemberDTO.java
	- 데이터 전송 및 저장을 위한 자료형 클래스로 설계
============================================================= */

package com.test.spr;

public class MemberDTO
{
	// TBL_MEMBERLIST 테이블의 컬럼 구조에 따라 속성 구성
	private String mid, name, tel;

	// getter / setter 구성
	public String getMid()
	{
		return mid;
	}

	public void setMid(String mid)
	{
		this.mid = mid;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String getTel()
	{
		return tel;
	}

	public void setTel(String tel)
	{
		this.tel = tel;
	}
}

· DAO.java

  • 인터페이스
/*=====================
	DAO.java
	- 인터페이스
======================= */

package com.test.spr;

import java.sql.SQLException;
import java.util.ArrayList;

public interface DAO
{
	public ArrayList<MemberDTO> lists() throws SQLException, ClassNotFoundException;
}

· LocalDAO.java

  • DAO 인터페이스를 구현하는 클래스로 설계
/*============================================
	LocalDAO.java
	- DAO 인터페이스를 구현하는 클래스로 설계
============================================== */

package com.test.spr;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class LocalDAO implements DAO
{

	@Override
	public ArrayList<MemberDTO> lists() throws SQLException, ClassNotFoundException
	{
		ArrayList<MemberDTO> result = new ArrayList<MemberDTO>();
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		String url = "jdbc:oracle:thin:scott/tiger@localhost:1521:xe";
		Connection conn = DriverManager.getConnection(url);
		
		String sql ="SELECT MID, NAME, TEL FROM TBL_MEMBERLIST ORDER BY MID";
		
		PreparedStatement pstmt = conn.prepareStatement(sql);
		ResultSet rs = pstmt.executeQuery();
		
		while(rs.next())
		{
			MemberDTO dto = new MemberDTO();
			dto.setMid(rs.getString("MID"));
			dto.setName(rs.getString("NAME"));
			dto.setTel(rs.getString("TEL"));
			
			result.add(dto);
		}
		rs.close();
		pstmt.close();
		conn.close();
				
		return result;
	}

}

· RemoteDAO.java

  • DAO 인터페이스를 구현하는 클래스로 설계
/*============================================
	RemoteDAO.java
	- DAO 인터페이스를 구현하는 클래스로 설계
============================================== */

package com.test.spr;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class RemoteDAO implements DAO
{

	@Override
	public ArrayList<MemberDTO> lists() throws SQLException, ClassNotFoundException
	{
		ArrayList<MemberDTO> result = new ArrayList<MemberDTO>();
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		String url = "jdbc:oracle:thin:scott/tiger@172.27.161.31:1521:xe";
		Connection conn = DriverManager.getConnection(url);
		
		String sql ="SELECT MID, NAME, TEL FROM TBL_MEMBERLIST ORDER BY MID";
		
		PreparedStatement pstmt = conn.prepareStatement(sql);
		ResultSet rs = pstmt.executeQuery();
		
		while(rs.next())
		{
			MemberDTO dto = new MemberDTO();
			dto.setMid(rs.getString("MID"));
			dto.setName(rs.getString("NAME"));
			dto.setTel(rs.getString("TEL"));
			
			result.add(dto);
		}
		rs.close();
		pstmt.close();
		conn.close();
				
		return result;
	}

}

· MemberDAO.java

  • DAO 객체의 lists() 메소드 호출 클래스
  • DAO 인터페이스를 구현한 클래스에 대해 의존관계 설정
/*=============================================================
	MemberDAO.java
	- DAO 객체의 lists() 메소드 호출 클래스
	- DAO 인터페이스를 구현한 클래스에 대해 의존관계 설정
 ==============================================================*/
package com.test.spr;

public class MemberDAO
{
	// 인터페이스 자료형 속성 구성
	private DAO dao;

	// setter
	public void setDao(DAO dao)
	{
		this.dao = dao;
	}
	
	public void lists()
	{
		try
		{
			for (MemberDTO dto : dao.lists())
			{
				System.out.printf("%s %s %s %n"
						, dto.getMid(), dto.getName(), dto.getTel());
			}
		} catch (Exception e)
		{
			System.out.println(e.toString());
		}
	}
	

}

· Main.java

  • main() 메소드를 포함하는 외부 클래스
/*==============================================
	Main.java
	- main() 메소드를 포함하는 외부 클래스
================================================ */

package com.test.spr;

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

public class Main
{

	public static void main(String[] args)
	{
		// XML 설정 파일을 이용하여 객체 생성 및 설정 정보를 읽어올 수 있도록 처리
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		// MemberDAO 객체를 요청하는 과정 (요청 대상은 스프링)
		// XML 설정 파일 안에서 『memberDAO』라는 아이디를 가진 객체를 요청
		// 그리고 이 객체를 반환 받는 과정에서 Object 타입이 아닌 MemberDAO 타입으로 반환받을 수 있도록 처리
		MemberDAO member = context.getBean("memberDAO", com.test.spr.MemberDAO.class);
		
		//위 과정을 통해 가져온 객체 안에 들어있는...
		// 특정 메소드(→ lists()) 호출
		member.lists();
		
	}

}

· applicationContext.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-3.0.xsd">

	<!-- LocalDAO 클래스에 대한 객체 생성 -->
	<!-- → com.test.spr.LocalDAO localDAO = new com.test.spr.LocalDAO(); → 구문을 스프링이 실행 -->
	<bean id="localDAO" class="com.test.spr.LocalDAO"></bean>
	
	<!-- RemoteDAO 클래스에 대한 객체 생성 -->
	<!-- → com.test.spr.RemoteDAO remoteDAO = new com.test.spr.RemoteDAO(); → 구문을 스프링이 실행 -->
	<bean id="remoteDAO" class="com.test.spr.RemoteDAO"></bean>
	
	<!-- MemberDAO 클래스에 대한 객체 생성 -->
	<!-- → com.test.spr.MemberDAO memberDAO = new com.test.spr.MemberDAO(); → 구문을 스프링이 실행 -->
	<bean id="memberDAO" class="com.test.spr.MemberDAO">
	
		<!-- ★ RemoteDAO 객체에 대한 의존성 삽입 -->
		<property name="dao">
			<ref bean="remoteDAO" />
		</property>
	</bean>

</beans>


'교육 및 세미나 > 신입사원 교육' 카테고리의 다른 글

12일차(2018.01.18)  (0) 2018.01.19
10일차(2018.01.16)  (0) 2018.01.19
9일차(2018.01.15)  (0) 2018.01.15
8일차(2018.01.12)  (0) 2018.01.12
7일차(2018.01.11)  (0) 2018.01.12