DI(Dependency Injection)란?

직역하면 "의존성 주입"이라는 표현을 할 수 있지만, 이는 개념을 이해하기에 좋지 못한 표현이다. Spring에서 사용하는 뜻에 맞게 의역하면 "의존성있는 객체는 외부에서 주입하는 것"이라고 표현할 수 있다.

 

public class FryPan{
	public void boil(){
    	System.out.println("불을 이용해 요리합니다.");
    }
}
public class Cook{
	FryPan fryPan;
    public void init(){
    	fryPan = new FryPane();
    }
    
    public static void main(String[]agrs){
    	fryPan.boid();
    }
}

예를 들어 위와 같은 코드보면, Cook클래스은 FryPan클래스의 의존하고 있는 상태이다. 

위와 같이 의존성이 강한 상태에서 fryPan의 인스턴스를 생성하기 위해서 new연산자를 이용할 수 밖에 없다.

이는 FryPan을 다른 클래스로 바꿔야한다는 상황이 올 때 직접 Cook코드를 열어 바꿔줘야한다.

-> 코드가 길어지고 복잡해지면 유지보수가 까다롭다.

public inteface Pan{
	public void boil();
}
public class FryPan implements Pan{
	@Override
    public void boil(){
    	System.out.println("불로 요리를 합니다");
    }
}
public class Cook{
	Pan pan;
	
    public void setPan(Pan pan){
    	this.pan = pan;
    }
    
    public static void main(String[]agrs){
    	fryPan.boid();
    }
}

위와 같이 인터페이스를 이용하여 코드의 결합도를 낮춰주고 좀더 유연하게 할 수 있다.

 

그리고 여기서 Spring은 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">

	<!-- 앞으로, 소스코드에서 new하지말고, 이 xml설정파일에서 사용할 객체를 명시하면 된다... 
		, 스프링의 ApplicationContext가 알아서 메모리에 인스턴스를 생성하고, 주입까지 해준다!!
		단, 주입받으려는 객체는 setter나 생성자가 명시되어 있어야  스프링이 주입을 할 수 있다.-->
	
	<!-- 프라이팬을 선언 -->
	<!-- 하나의 컴포넌트 = bean -->
	<bean id="friPan" class="food.FriPan"/>	
	<bean id="cook" class="food.Cook">
		<!-- cook내의 pan을 주입  
			cook내의 setter메서드 호출-->
		<property name="pan" ref="friPan"/>
	</bean>
</beans>
package food;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UseCook {
	public static void main(String[] args) {

		/*DI (Dependency Injection) 
		 : 직역 시, 의존성 주입..
		의역 시, 의존성있는 객체는 외부에서 주입받자!!!!
		 */		
			
		//스프링을 이용하지 않고 구현한 예
		//팬을 올리자
		/*
		 * FriPan pan = new FriPan(); Cook cook = new Cook();
		 * 
		 * cook.setPan(pan);//팬을 요리사에게 주입시키자!!
		 * 
		 * cook.makeFood();
		 */
		
		//스프링을 이용해서 객체를 주입시켜본다..
		//xml에 원하는 객체를 명시하면, 이 객체가 작성된 xml을 파악하여
		//객체들의 인스턴스를 생성관리해준다.. 이러한 역할을 수행하는 객체를 가리켜
		//Spring Context 객체라 한다!!!!! (외부파일을 통해 인스턴스 관리)
		ClassPathXmlApplicationContext context = null; //스프링xml 설정파일을 읽어서 작성된
		//객체의 인스터는스를 생성 및 관리해준다(주입도 해줌)
		//외부조립자(Assembler)
		context = new ClassPathXmlApplicationContext("spring/config/context.xml");
		
		//xml이 이미 읽혀진 상태이므로, 메모리에는 인스턴스들이 존재할 것이고, 그 중 어떤 인스턴스를 가져올지는
		//getBean메서드로 가져오면 된다..
		Cook cook = (Cook)context.getBean("cook");
		cook.makeFood();
	}
}

 

ClassPathXmlApplication객체를 이용하여 인스턴스를 생성할 xml을 지정하여 사용할 수 있다.

 

스프링을 사용하면 외부파일인 XML로 코드를 유지보수할 수 있고 코드의 결합도를 낮출 수 있다!

'프로그래밍 > Spring' 카테고리의 다른 글

Spring - ServletContext 쉽게 가져오기  (0) 2021.01.05
Spring | collection & association  (0) 2020.12.24
Spring | AOP  (0) 2020.12.23

MVC패턴이란?

  • 구현된 개발코드를 의미하는게 아니라, 어플리케이션 개발 시 디자인과 로직은 분리시켜 개발해야 추후 변경사항이 발생했을 때 많은 리소스(개발시간, 인력)를 소모하지 않고 유지보수할 수 있다는 IT의 전해 내려오는 개발방법이론(개발패턴)
  • 자바로 구현한 MVC패턴을 모델2방식이라 한다.
  • ms개발자, .net개발자도 사용 즉, 어떠한 개발에도 사용되는 방식

 

Model

  • 중립적 로직이라서 스윙, 웹 모두 사용할 수 있는 중립적 코드  일반클래스로 정의하면 된다.
  • DAO, DTO와 같은 클래스들이라고 말할 수 있다.

View

  • 디자인적인 요소를 담당하는 부분이다.
  • JSP와 같이 태그들이 들어가는 코드라고 말할 수 있다.

Controller

  •  로직인 Model과 디자인인 View를 분리시키기 위한 용도
  • 웹이건, 응용프로그램이건 모든 컨트롤러 5대역할 

                     1. 요청을 받는다. 
                     2. 요청을 분석한다.. 
                     3. 알맞는 로직 객체에게 일을 시킨다.(지가 직접안함) 
                     4. 일 시킨 후(3단계) 결과가 있다면 결과를 보관한다. 
                     5. 디자인에 그 결과를 반영한다.

  • Servlet과 같은 클래스이다.

 

게시판목록페이지의 코드로 예를 들어보자

 

아래의 코드는 게시판목록의 View담당하는 JSP코드이다. 

DAO와 같은 클래스를 가지고 있지 않다.

<%@page import="com.webapp1216.board.model.Notice"%>
<%@page import="com.webapp1216.common.board.Pager"%>
<%@page import="java.util.List"%>
<%@ page contentType="text/html;charset=utf-8"%>
<%
	List<Notice> list = (List<Notice>)session.getAttribute("noticeList");
	Pager pager = new Pager();
	pager.init(request, list); // 페이지 처리에 대한 계산!!
%>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
table {
	border-collapse: collapse;
	border-spacing: 0;
	width: 100%;
	border: 1px solid #ddd;
}

th, td {
	text-align: left;
	padding: 16px;
}

tr:nth-child(even) {
	background-color: #f2f2f2;
}

img{
	width:100px;
}
</style>
</head>
<body>

	<table>
		<tr>
			<th>No</th>
			<th>제목</th>
			<th>작성자</th>
			<th>작성일</th>
			<th>조회수</th>
		</tr>
		<%int num = pager.getNum(); %>
		<%int cusPos = pager.getCurPos(); %>
		<%for(int i=0;i<pager.getPageSize();i++){ %>
			<%if(num<1)break; %>
				<%Notice notice= list.get(cusPos++); %>
				<tr>
					<td><%=num-- %></td>
					<td><a href="/board/detail?notice_id=<%=notice.getNotice_id()%>"><%=notice.getTitle() %></a></td>
					<td><%=notice.getWriter() %></td>
					<td><%=notice.getRegdate() %></td>
					<td><%=notice.getHit() %></td>
				</tr>
		<%} %>
		  <tr>
			<td colspan="6" style="text-align: center">
			<%if(pager.getFirstPage()-1<=0){ %>
				<a href="javascript:alert('처음페이지입니다.')">◀</a>
			<%}else{ %>
			<a href="list.jsp?currentPage=<%=pager.getFirstPage()-1%>">◀</a>
			<%} %>
				<%for(int i=pager.getFirstPage();i<=pager.getLastPage();i++) {%>
					<%if(i<=pager.getTotalPage()){ %>
						<a href="list.jsp?currentPage=<%=i%>">[<%=i %>]</a>
					<%} %>
				<%} %>
				<%if(pager.getLastPage()>=pager.getTotalPage()){ %>
				<a href="javascript:alert('마지막페이지입니다.')">▶</a>
			<%}else{ %>
				<a href="list.jsp?currentPage=<%=pager.getLastPage()+1%>">▶</a>
			<%} %>
			</td>
		</tr>
		 -<tr>
			<td colspan="6">
				<button type="button" onClick="location.href='regist_form.jsp'">글등록</button>
			</td>
		</tr>
	</table>

</body>
</html>

 

아래의 코드는 M와 V를 연결해주는 역할의 Controller이다.

어떠한 디자인적인 요소가 들어가지 않았다.

/*
 * javaEE 개발패턴 중 mvc패턴을 적용한 개발방법을 가리켜 model2방식이라 일컫는다.
 * 특히 jsp가 디자인에 사용되고 있으며, 웹 상의 요청을 받고 응답이 가능한 서블릿이 컨트롤러로서 역할을 수행하게 된다.
*/
package com.webapp1216.board.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.webapp1216.board.model.Notice;
import com.webapp1216.board.model.NoticeDAO;

//클라이언트의 목록요청을 처리하는 서블릿 정의!!
public class ListServlet extends HttpServlet{
	NoticeDAO dao = new NoticeDAO();
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		List<Notice> list = dao.selectAll();
		//어떻게 list.jsp까지 살려서 보낼까???
		//세션? 클라이언트가 브라우저 프로세스를 닫지 않거나, 일정 시간내에 재접속했을 때 서버측의 메모리에
		//담겨진 정보를 사용할 수 있는 기술...(새로운 접속인 경우 세션 객체를 새로 생성되고, 세션아이디가 새롭게 발급됨..)
		//session을 어케 가져오지?
		//jsp에서의 session내장객체는 자료형이 HttpSession이다!!
		HttpSession session = request.getSession();//이 요청과 관련한 세션을 얻는다!
		session.setAttribute("noticeList", list);//세션 객체에 보관!
		
		
		//결과페이지 선택
		response.sendRedirect("/board/list.jsp");
	}
}

 

아래의 코드는 DAO를 담당하는 모델의 코드이다.

DB와의 연결을 통해 요청에 대한 응답하기위한 데이터를 처리하는 부분이다.

package com.webapp1216.board.model;

import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.webapp1216.mybatis.config.MybatisConfigManager;

public class NoticeDAO {
	MybatisConfigManager manager = MybatisConfigManager.getInstance();
	
	// CRUD

	public List<Notice> selectAll() {
		List<Notice> list =null;
		SqlSession sqlSession = manager.getSqlSession();
		list = sqlSession.selectList("Notice.selectAll");
		manager.close(sqlSession);
		return list;
	}
}

 

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | 서블릿(Servlet) 이해  (0) 2020.12.16
JSP | session  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 페이징 이해  (0) 2020.12.08

서블릿(Servlet)이란?

오직 웹서버에서만 해석 및 실행될 수 있는 JavaEE기반의 클래스이다.

 

서블릿의 생명주기

생명주기는 init(), service(), destory() 로 이해할 수 있다.

  • init() : 생성자 호출 후, 서블릿의 초기화 작업때문에 톰캣에 의해
    호출
  • service() : 동시에 많은 클라이언트의 요청을 처리하는 메서드이고, 
    동시에 호출되려면, 쓰레드에 의해 호출됨
  • destory() : 서블릿 소멸시점에 호출, 주로 서블릿이 보유하고 있는 자원들을
    반납하는 용도에 사용..

서블릿의 계보

자식                                        부모                                   할아버지

HttpServlet ( 웹용, 추상클래스) -> GenericServlet(추상클래스) -> Servlet(인터페이스)

 

쉽게 말하면 위와 같이 설명할 수 있다. 

Servlet인터페이스는 간단한 추상메서드들로만 구성되어있다.

GenericServlet은 Servlet보다 더 많은 메서드들로 구성되어있으며, Sun사에서 서블릿을 개발할 때 단순히 Http 즉 웹용으로만 개발하는 것이 아니라 더 방범위한 분야에서 사용할 수 있도록 GenericServlet과 같은 틀을 제공한다.

 

HttpServlet은 웹용의 서블릿을 개발할 때 사용되는 클래스이며, get, post.. 등 다양한 요청에 대해 대응할 수 있는 doGet, doPost.. doXXXX와 같은 메서드들을 지원해준다.

 

JSP는 서블릿이다.

JSP는 사실 서블릿이였다. 

JSP에는 지시영역, 선언부, 스크립틀릿, 표현식의 영역이 존재한다. 사실 서블릿의 영역들 중 한 부분인 것이였다.

<%@ page contentType="text/html;charset=utf-8"%>
<%!
	//멤버메서드, 멤버변수 .. 멤버란? 클래스에서 인스턴스가 갖는 변수, 메서드 작성하는 영역
	int x=5;
	public void test(){
	}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
<style></style>
<script></script>
</head>
<body>
난 jsp야!!
</body>
</html>

위와 같은 JSP파일이 사실은 

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/8.5.61
 * Generated at: 2020-12-15 02:23:06 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {


	//멤버메서드, 멤버변수 .. 멤버란? 클래스에서 인스턴스가 갖는 변수, 메서드 작성하는 영역
	int x=5;
	public void test(){
	}

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    final java.lang.String _jspx_method = request.getMethod();
    if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP들은 오직 GET, POST 또는 HEAD 메소드만을 허용합니다. Jasper는 OPTIONS 메소드 또한 허용합니다.");
      return;
    }

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=utf-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write('\r');
      out.write('\n');
      out.write("\r\n");
      out.write("<!DOCTYPE html>\r\n");
      out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("<meta charset=\"utf-8\">\r\n");
      out.write("<title>Insert title here</title>\r\n");
      out.write("<style></style>\r\n");
      out.write("<script></script>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
      out.write("난 jsp야!!\r\n");
      out.write("</body>\r\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

서블릿 클래스로 웹컨테이너가 변환시켜 실행하는 것이다!!! 놀라지 않을 수가 없다!!

 

단지 JSP는 디자인적인 코드를 편히 하기위해 만들어낸 기술일 뿐이다!!!

 

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | MVC패턴에 대한 이해  (0) 2020.12.16
JSP | session  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 페이징 이해  (0) 2020.12.08

+ Recent posts