웹개발을 시작하기 전부터 질리도록 들었던 단어가 있다. 바로 MVC 패턴으로, 이는 웹개발 관련 블로그나 커뮤니티에서 하루도 빠짐없이 언급 될 정도로 웹 개발 하면 필수적으로 알아야 할 디자인 패턴이다. MVC패턴에 대해 설명하기 전에 모델 1 구조와 모델 2 구조를 먼저 설명하고자 한다.

JSP로 구성할 수 있는 웹 어플리케이션의 아키텍쳐는 크게 모델 1, 모델 2로 나뉜다. 이 두 모델의 큰 차이점은 JSP가 결과의 출력 뿐만 아니라 요청에 대한 모든 로직들을 처리하냐, JSP는 결과의 출력만 담당하냐의 차이이다.


1. 모델 1 구조


모델 1은 뷰와 로직을 모두 JSP 페이지 하나에서 처리하는 구조를 말하며, 위 사진과 같은 구성을 띈다. 모델 1을 구성하는 요소는 크게 나누면 다음과 같다.

1. JSP

2. 자바빈 혹은 서비스 클래스

 JSP 페이지 내에 로직 처리르 위한 자바 코드가 출력을 위한 코드와 함께 섞여 삽입된다. 브라우져에서 요청이 들어오면 JSP 페이지는 자신이 직접 자바빈이나 따로 작성한 서비스 클래스를 이용하여 작업을 처리하고, 그 처리한 정보를 클라이언트에 출력한다. 과거에 가장 많이 사용되었던 아키텍쳐로, 간단한 페이지를 구성하거나 여러 책의 초반 예제로 많이 사용되기때문에 익숙한 방식이다. 모델 1은 다음과 같은 장점과 단점을 가지고있다.


 장점

 단점

- 구조가 단순하여 익히기가 쉽다.

- 위와 같은 이유로 숙련된 개발자가 아니더라도 구현이 용이하다.

- 출력을 위한 뷰 코드와 로직 처리를 위한 자바 코드가 함께 섞이기 때문에 JSP 코드 자체가 복잡해진다.

- JSP 코드에서 백엔드와 프론트엔드가 혼재되기 때문에 분업이 용이하지 않다.

- 코드가 복잡해져 유지보수가 어렵다.



2. 모델 2 구조



모델 2는 모든 처리를 JSP 페이지 하나가 담당하는것과는 달리 JSP페이지와 서블릿, 그리고 로직을 위한 클래스가 나뉘어 브라우저 요청을 처리한다. 모델 2를 구성하는 요소는 다음과 같다.

1. 서블릿

2. JSP

3. 자바빈 혹은 서비스 클래스

  요청이 들어오면 요청에 대한 로직 처리는 이를 처리할 모델(Model)인 서비스클래스 혹은 자바빈이 담당하고, 요청 결과는 유저에게 결과를 보여줄 뷰(View)단인 JSP에 출력되며,  이를 위한 모든 흐름 제어는 컨트롤러(Controller)서블릿에서 담당한다.



3. MVC 패턴과 모델2

즉 모델 2 구조란 MVC(Model-View-Controller) 패턴을 웹 개발에 도입한 구조이며. 모델 2와 MVC 패턴의 형태는 완전히 같은 형태를 가진다.

MVC 패턴

모델 2

 

Model

서비스 클래스 or 자바빈 

 비즈니스 로직을 처리하는 모든것들이 모델에 속한다. 컨트롤러로부터  특정 로직에 대한 처리 요청(ex: 게시판 글쓰기, 회원가입, 로그인 등)이 들어오면 이를 수행하고 수행 결과를 컨트롤러에 반환한다. 필요한 정보는 request 객체나 session 객체에 저장하기도 한다.

View 

JSP 페이지 

 클라이언트에 출력되는 화면을 말한다. 모델1과 달리 로직 처리를 위한 코드가 내포되어 있지 않다. 요쳥 결과의 출력 뿐만 아니라 컨트롤러에 요청을 보내는 용도로도 사용된다. request 객체나 session 객체에 저장된 정보를 토대로 화면을 출력한다.

Controller 

서블릿 

 MVC 패턴(모델 2)모든 흐름 제어를 맡는다. 브라우져로부터 요청이 들어오면, 어떤 요청인지를 분석하여 이 요청을 처리하기 위한 모델을 사용하여 처리한다. 사용한 모델로부터 처리 결과를 받으면 추가로 처리하거나 가공해야할 정보가 있다면 처리 후 request 객체나 session객체에 저장하고, 뷰(JSP 페이지)를 선택하여 foward나 redirect 하여 클라이언트에 출력한다.


모델 2(MVC 패턴)은 모델1의 단점에 의해 탄생했기 때문에, 모델1이 가지고있는 모든 단점들을 해소하였지만 반대로 다루기 어렵다는 단점이 있다.


 장점

 단점

- 출력을 위한 뷰 코드와 로직 처리를 위한 자바 코드를 분리하기 때문에 JSP 모델1에 비해 코드가 복잡하지 않다.

- 뷰, 로직처리에 대한 분업이 용이하다.

- 기능에 따라 분리되어있기 때문에 유지보수가 용이하다.

- 구조가 복잡하여 습득이 어렵고 작업량이 많다.

- JAVA에 대한 깊은 이해가 필요하다.


모델 1 VS 모델 2

모델 2가 뒤늦게 나왔다고 무조건 장점만 가지고 있는 것은 아니다. 모델 2는 규모가 큰 프로젝트나 업데이트가 빈번한 프로젝트엔 용이할지는 모른다. 하지만 규모가 많이 크지 않고 업데이트가 적은 프로젝트일 경우엔 쓸대없이 복잡한 형태로 작업량이 늘어날 뿐이다. 이 경우에는 간단한 모델 1으로 개발하는게 더 나을수도 있다. 모델 1과 모델 2은 완전히 다른 장점과 단점을 가지고 있으므로 하나만 무조건적으로 사용한다기보단 상황에따라 적절한 선택이 필요할 것 같다. 


'JAVA > JSP,Servlet' 카테고리의 다른 글

커넥션풀(Connection Pool) - DBCP 예제  (0) 2016.02.08


커넥션 풀이란 db와 연결하는 커넥션을 미리 생성해두고 풀에 저장해두었다 필요할때 꺼내쓰고, 사용후에는 다시 풀에 반환하는 기법을 말한다.
(멀티쓰레드의 쓰레드풀과 유사하다.)
커넥션을 미리 생성해두기 때문에 커넥션을 사용자가 db를 사용할때마다 매번 생성을 하는것보다 더 빠른 속도를 보장한다.
또한 커넥션의 최대 생성 갯수도 제어해주기 때문에 많은 사용자가 몰려도 과부화를 방지할 수 있다.



커넥션 풀의 오픈소스에는 대표적으로 DBCP와 C3P0이 있는데 여기선 DBCP를 사용하였다. DBCP는 아파치 사이트에서 받을수 있는데, 그 외에 DBCP에서 사용한 Pool인 Commons Pool이 필요하고, 부가적으로 로그 기록에 사용되는 Commons Logging도 필요하다.
각각의 API는 아래 링크에서 받을 수 있다.



1. DBCPInit.java
package jdbc;

import java.sql.DriverManager;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class DBCPInit extends HttpServlet {

    @Override
    public void init() throws ServletException {
            loadJDBCDriver();
            initConnectionPool();
    }
    private void loadJDBCDriver() {
        try {
            //커넥션 풀에서 사용할 jdbc 드라이버를 로딩
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException("fail to load JDBC Driver", ex);
        }
    }
    private void initConnectionPool() {
        try {
            String jdbcUrl = "jdbc:mysql://localhost:3306/chap14?" + "useUnicode=true&characterEncoding=utf8";
            String username = "phs1116";
            String pw = "1234";
            
            //커넥션팩토리 생성. 커넥션 팩토리는 새로운 커넥션을 생성할때 사용한다.
            ConnectionFactory connFactory = new DriverManagerConnectionFactory(jdbcUrl, username, pw);
            
            //DBCP가 커넥션 풀에 커넥션을 보관할때 사용하는 PoolableConnectionFactory 생성
            //실제로 내부적으로 커넥션을 담고있고 커넥션을 관리하는데 기능을 제공한다. ex)커넥션을 close하면 종료하지 않고 커넥션 풀에 반환
            PoolableConnectionFactory poolableConnFactory = new PoolableConnectionFactory(connFactory, null);
            //커넥션이 유효한지 확인할때 사용하는 쿼리를 설정한다.
            poolableConnFactory.setValidationQuery("select 1");
            
            
            //커넥션 풀의 설정 정보를 생성한다.
            GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
            //유휴 커넥션 검사 주기
            poolConfig.setTimeBetweenEvictionRunsMillis(1000L * 60L * 1L);
            //풀에 있는 커넥션이 유효한지 검사 유무 설정
            poolConfig.setTestWhileIdle(true);
            //커넥션 최소갯수 설정
            poolConfig.setMinIdle(4);
            //커넥션 최대 갯수 설정
            poolConfig.setMaxTotal(50);

            //커넥션 풀 생성. 인자로는 위에서 생성한  PoolabeConnectionFactory와 GenericObjectPoolConfig를 사용한다.
            GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnFactory,
                    poolConfig);
            
            //PoolabeConnectionFactory에도 커넥션 풀을 연결
            poolableConnFactory.setPool(connectionPool);
            
            //커넥션 풀을 제공하는 jdbc 드라이버를 등록.
            Class.forName("org.apache.commons.dbcp2.PoolingDriver");
            
 
            PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
            //위에서 커넥션 풀 드라이버에 생성한 커넥션 풀을 등룍한다. 이름은 cp이다.
            driver.registerPool("cp", connectionPool);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}


2. web.xml에 서블릿 실행 설정
    <servlet>
        <servlet-name>DBCPInit</servlet-name>
        <servlet-class>jdbc.DBCPInit</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>


3. 커넥션 사

String jdbcDriver = "jdbc:apache:commons:dbcp:cp";
...
conn = DriverManager.getConnection(jdbcDriver);

커넥션을 사용할땐 기존 db 주소가 아닌 커넥션 풀의 주소를 사용한다.


'JAVA > JSP,Servlet' 카테고리의 다른 글

JSP 모델1과 모델2, 그리고 MVC 패턴  (2) 2016.02.15


//적용 방법 1

JLayeredPane layered1 = new

JLayeredPane(); jframe.add(layered1);

//적용 방법 2

JLayeredPane layered2 = this.getLayeredPane(); //컴퍼넌트 추가방법중 하나 layered.add(Compnent comp, int index);

 


JLayeredPane는 JFC나 Swing의 컨테이너에 깊이(depth)를 적용하여 컨테이너들을 겹쳐서 사용할 수 있도록 하는 컨테이너 객체이다.


add 메서드의 매개변수중 index의 크기에 따라서 깊이가 달라지는데, 크기가 클수록 더욱 상위에 위치한다.


JLayeredPane 클래스에는 이를 위해 몇가지 static final integer값이 선언되어있다.



 

 DEFAULT_LAYER

 new Integer(0)

 PALETTE_LAYER 

 new Integer(100)

 MODAL_LAYER

 new Integer(200)

 POPUP_LAYER

 new Integer(300)

 DRAG_LAYER

 new Integer(400)


자세한 깊이 정도는 위의 그림 참조.




http://docs.oracle.com/javase/8/docs/api/javax/swing/JLayeredPane.html



Method NameDescription
showConfirmDialogAsks a confirming question, like yes/no/cancel.
showInputDialogPrompt for some input.
showMessageDialogTell the user about something that has happened.
showOptionDialogThe Grand Unification of the above three.

//메세지 다이얼로그

JOptionPane.showMessageDialog(parentComponent, message);

JOptionPane.showMessageDialog(parentComponent, message, title, messageType);

JOptionPane.showMessageDialog(parentComponent, message, title, messageType, icon);


 

JDialog를 이용해서 다이얼로그를 생성할 수 있지만


JOptionPane를 이용하면 제한적인 기능을 가진 다이얼로그를 간단하게 생성 할 수 있다.



JOptionPane.showMessageDialog(null, "ID,비밀번호를  모두 입력해주세요.");





http://docs.oracle.com/javase/6/docs/api/javax/swing/JOptionPane.html




loginButton = new JButton(new ImageIcon("img/btLogin_hud.png")); // 버튼 배경 이미지 설정

loginButton.setBorderPainted(false); // 버튼 테두리 설정

loginButton.setContentAreaFilled(false); // 버튼 영역 배경 표시 설정

loginButton.setFocusPainted(false); // 포커스 표시 설정


loginField.setBorder(javax.swing.BorderFactory.createEmptyBorder());//테두리 없애는 방법 1

 

passwordField = new JPasswordField(15){ //테두리 없애는 방법 2

public void setBorder(Border border){ } };



setBorder 메서드에 비어있는 border객체를 생성해 전달해주거나


setBorder 메서드를 비어둔 상태로 오버라이딩 해주면 된다.


+ Recent posts