2022.01.11 TIL

서승원·2022년 1월 11일
0

TIL

목록 보기
51/68

아키텍쳐

방명록을 jsp를 통해 프로그래밍 하는데 있어, 모델1, 모델2 아키텍쳐로 각각 구성해보고 그 차이를 알아봤다.

모델 1 아키텍쳐

모델 1아키텍쳐는 웹 브라우저가 jsp 파일에 요청을 보내고, jsp 가 그에 맞는 응답을 보내면 다시 브라우저에서 요청을 보내고, jsp를 통해서 DAO와 상호작용으로 페이지를 구성한다. 이 방법을 통하면 비교적 흐름이 단순하다. 하지만 분업을 한다고 가정했을 경우, jsp 는 디자이너의 영역으로 볼 수 있다. jsp가 DAO와 직접적으로 상호작용을 하면 그에 따른 jsp에 포함된 java 코드 내용이 점점 무거워 질 것이다.(특히 여러 기능이 추가될수록)

List<Bang06VO> ls = new ArrayList<Bang06VO>();
Exception err = null;
	
//	----------------------------------------------------------------------------

Bang06DAO dao = new Bang06DAO_MariaImpl();
try {
	ls = dao.findAll();
}
catch( Exception e ) {
	err = e; 
}

	
if( err != null ) {
	request.setAttribute("err", err );
	RequestDispatcher rd = request.getRequestDispatcher("test_511_error.jsp");
	rd.forward( request, response );
	return;
}

<%
for( Bang06VO t : ls ) {
%>

		<tr>
			<td>
				 <%=t.getNo()%>
			</td>
			<td>
				<span class="font"><%=t.getContent()%></span> 
				[<a href="test_513_del2.jsp?no=<%=t.getNo()%>">X</a>]
		 		&nbsp;<span class="font_sm"><%=t.getAuthor()%></span> 
		<% 
			if( t.getFsn() != null && t.getOfn() != null ) { 
				String ofn = t.getOfn();
		%>
			&nbsp;<a href="test_514_down.jsp?fsn="<%=t.getFsn()%>"&ofn="<%=ofn%>"><img src='down.svg'/></a>
		<%}%>
			</td>
		</tr>
	<%}%>

test_510_list.jsp 에 작성한 방명록의 게시, 삭제, 작성을 위한 java 부분이다.
기능이 추가될수록 더 많은 코드가 추가될 것이다.

모델 2 아키텍쳐

모델 2 아키텍쳐는 jsp를 거의 html 코드만 남겨 온전한 디자인을 위한 공간으로 남겨두는 것과 마찬가지다. DAO와의 상호작용은 Controller 라는 인터페이스를 사용해서 url-pattern별로 class 를 지정해 DAO와, Controller로부터 상속받은 Class 를 기능별로 나눠 응답,요청을 주고받을 수 있도록 한다.
<%

List <Bang06VO> rl = (List<Bang06VO>)request.getAttribute("rList");
%>
모델 2 아키텍쳐로 작성한 test_517_list.jsp이다. 자바코드는 위와 같이 한 줄만 jsp 에 남게된다.
이 구조를 더 살펴보면,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
String uri = request.getRequestURI();
        String cp = request.getContextPath();
        
        String uri2 = uri.substring( cp.length() );
        
        Controller ctrl = null;
        if( uri2.equals("/list.do") ) {
            ctrl = new CtrlList();
        }
        else if( uri2.equals"/add2.do" ) )  {
            ctrl = new CtrlAdd2();
        }
        else if( uri2.equals"/del2.do" ) ) {
            ctrl = new CtrlDel2();
        }
        if( ctrl == null ) {
            System.out.println( uri2 + "에 해당하는 컨트롤러가 없네요");
        }
        else {
            try {
                ModelAndView mnv = ctrl.handleRequest(request, response);
                if( mnv != null ) {
                    String viewName = mnv.getViewName();
                    if( viewName.startsWith("redirect:") ) {
                        response.sendRedirect( viewName.substring(9) );
                    }
                    else {
                        mnv.plant(request);
                        RequestDispatcher rd = request.getRequestDispatcher( viewName + ".jsp");
                        rd.forward( request , response );
                    }
                }
            }
            catch( Exception e ) {
                e.printStackTrace();
cs
메인이 되는 서블릿인 Test519.java 파일이다. null인 Controller ctrl 을 생성하고, jsp에서 action으로 보낸 uri로부터 uri2 : 실행할 기능을 uri2 에 대입해서 그에 맞는 기능을 실행하도록 ctrl에 Controller로 상속받은 각 class에 맞게 대입한다. 해당 내용은 ModelAndView mnv에 handleRequest 함수 호출을 통해 대입하고, 해당 mnv를 통해 forward/sendRedirect가 이뤄진다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class ModelAndView {
    private String viewName = null;
 
    public String getViewName() {
        return viewName;
    }
 
    public void setViewName(String viewName) {
        this.viewName = viewName;
    }
    private Map<String,Object> objMap = null;
    public void addObject( String key, Object val ) {
        if( objMap == null ) {
            objMap = new Hashtable<String,Object>();
        }
        objMap.put( key , val );
        
    }
    
    public void plant( HttpServletRequest request ) {
        if( objMap != null ) {
            Set<String> ks = objMap.keySet();
            forString key : ks ) {
                Object val = objMap.get(key);            
                request.setAttribute( key, val );
            }
        }
    }
}
cs
ModelAndView.java의 코드다. Map을 가지고 있다. Getter와 Setter를 이용해서 Map이 가진 key와 val에 forward/sendRedirect에 대한 정보를 담아내고, plant라는 함수를 통해서 해당 정보들을 request에 SetAttribute 해준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class CtrlList implements Controller {
 
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception 
    {
        Bang06DAO dao = new Bang06DAO_MariaImpl();
        List<Bang06VO> rl = dao.findAll();
        System.out.println( rl );
        
        ModelAndView mnv = new ModelAndView();
        mnv.setViewName("test_517_list");        
        mnv.addObject("rList", rl );
        
        return mnv;
    }
 
}
cs
CtrlList.java , List를 게시하기 위한 class 로 이전에 작성한 List 와 동일하지만 다른 점은 RequestDispatcher를 통해 다른 페이지와 응답을 주고받지 않고 mnv를 이용한다는 점이다. rl 리스트에 findAll을 통한 SELECT 결과를 대입하고 , 다시 "rList",rl 의 key,val 의 형태로 mnv 의 Map에 추가된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class CtrlAdd2 implements Controller {
 
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception 
    {
        Bang06DAO dao = new Bang06DAO_MariaImpl();
 
        MultipartRequest mpr = new MultipartRequest( request , Util.uploadDir(), 
                1024*1024*16 , "utf-8"null );
 
        ModelAndView mnv = new ModelAndView();
        
        
        String content = mpr.getParameter("content");
        if( content == null || content.equals("") ) {
            mnv.setViewName("redirect:list.do?ecode=invalid_content");
            return mnv;
        }
        String author = mpr.getParameter("author");
        if( author == null || author.equals("") ) {
            mnv.setViewName("redirect:list.do?ecode=invalid_author");
            return mnv;
        }
        
        Bang06VO po = new Bang06VO();
        po.setContent( content );
        po.setAuthor( author );
            
        String ofn = mpr.getOriginalFileName("apple");
        File file = mpr.getFile("apple");
            
        String fsn = UUID.randomUUID().toString();
        file.renameTo( new File( Util.uploadDir() + fsn ) );
 
        po.setOfn( ofn );
        po.setFsn( fsn );
        dao.add( po );        
                
        mnv.setViewName("redirect:list.do");
        return mnv;
    }
 
}
cs
CtrlAdd2.java 다. 역시 기존 방명록 작성 코드와 동일한 흐름이지만, mnv에 담아내는데 ViewName에 Redirect: 를 포함시켜 , Test519.java가 forward/sendRedirect를 구분하여 사용하게 한다. 이는 Spirng Framework에서 사용하는 방식으로 미리 사용해봐서 프레임워크를 만드는 방법, 그 구조를 이해하는데 도움이 많이 됐다.
profile
2년차 백엔드 개발자, crimy

0개의 댓글