재밌고 어려운 IT를 이해해보자~!

JSP, Servlet Mapping 본문

코리아IT핀테크과정

JSP, Servlet Mapping

언제나즐거운IT 2024. 1. 10. 10:16

서블릿 매핑하는 이유
브라우저는 URL을 이용해 웹 프로젝트를 서버에게 요청한다. 이때 URL은 다음과 같은 구성으로 이루어져있다.

http:// IP주소:포트번호 / 프로젝트이름 / < 패키지이름 >.< 클래스이름 >

문제점

그런데 클래스 이름이 길어지면 입력하기도 불편하고, 클래스 이름이 노출되며 어떤 기능을 하는지 쉽게 파악할 수 있기 때문에 보안에도 취약하다. 그래서 이러한 문제점을 방지하기 위해 실제 서블릿 클래스 파일 이름을 대체할 수 있는 별명을 붙여주는 것이다.

http:// IP주소:포트번호 / 프로젝트이름 / 매핑한 이름 (별명)

 

서블릿 매핑하는 방법


서블릿 매핑하는 방법은 2개로 나뉜다.
1. web.xml에 직접 작성하기
2. 서블릿 어노테이션 이용하기

 

우리는 서블릿 어노테이션을 사용해서 맵핑을 한다!!!!

 

서블릿 클래스 위에 다음처럼 적으면 되는데 
이과정을 처음 servlet을 생성할 때부터 설정할 수 있는 방법이 있다.

@WebServlet("/서블릿매핑이름");

이 과정을 처음 servlet을 생성할 때부터 설정할 수 있는 방법이 있다.
1. class를 생성할 패키지에 우클릭 -> New -> Servlet

생성할 class name 적고 Next 클릭

매핑할 class를 선택하고 Edit 클릭

 mapping할 이름 적고 OK

우리는 *,do 로 한다!

 

또한 앞으로 모든 기능들은 모듈화시켜  Action 인터페이스를 implements받아 사용할 것이다.

이렇게 할 경우 한개의 기능이 고장나도 나머지는 잘 돌아가기 때문에 문제가 없다.

 

Action 인터페이스는 다음과 같다!

Action.java

package controller;

import java.io.IOException;

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

// FrontController 에서
// 기능 클래스를 호출할때에
// 메서드명을 일괄적으로 강제하고싶어서 인터페이스 사용
public interface Action {

	ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
	// execute() 수행결과로 반환할것들
	//  1. 어디로 가야할지 == 경로
	//  2. 어떻게 가야할지 == 리다이렉트 or 포워드
	// ☆ 반환이 2개이상이면, '자료형'을 새로 정의 => "클래스" 정의

}

 

Action 인터페이스는 ActionFoward를 반환타입으로 가지고 HttpServletRequest,와 HttpServletResponse를 인자로 받는 메서드를 뜻한다.

 

ActionForward 클래스는 멤버변수로 path와 redirect를 가지고있고
path는 어디로 이동할지, 
redirect는 어떤방식으로 이동할지 (Redirect or Forward)를 지정한다.

ActionForward.java

package controller;


public class ActionForward {

	private String path; // 어디로 가야하는지 == 경로
	private boolean redirect; // 어떻게 갈지 == 리다이렉트 or 포워드
	
	public ActionForward() {
		
	}

	@Override
	public String toString() {
		return "ActionForward [path=" + path + ", redirect=" + redirect + "]";
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public boolean isRedirect() {
		return redirect;
	}

	public void setRedirect(boolean redirect) {
		this.redirect = redirect;
	}

}

 

그리고 만들고싶은 기능 Action을 implement한 클래스에서 path와 redirect를 ActionForward 객체에 담아서 FrontController로 리턴해준다!

ActionForward.java

package controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("*.do")
public class FrontController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public FrontController() {
		super();
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doAction(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doAction(request, response);
	}

	private void doAction(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// controller.jsp 의 코드를 옮겨올예정!

		String uri = request.getRequestURI();
		String cp = request.getContextPath();
		String action = uri.substring(cp.length());

		ActionForward forward = null;
		if (action.equals("/main.do")) { // ◀ if(action.equals("main")){
			forward = new MainAction().execute(request, response);
		} else if (action.equals("/join.do")) {
			forward = new JoinAction().execute(request, response);
		} else if (action.equals("/joinPage.do")) {
			forward = new ActionForward();
			forward.setPath("join.jsp");
			forward.setRedirect(true);
			// response.sendRedirect("join.jsp");
		} else if (action.equals("/logout.do")) {
			forward = new LogoutAction().execute(request, response);
		} else if (action.equals("/testPage.do")) {

		} else if (action.equals("/myPage.do")) {
			System.out.println("로그2?");
			// forward = new JoinAction().execute(request, response);
//			forward = new ActionForward();
//			forward.setPath("myPage.jsp");
//			forward.setRedirect(true);
			forward = new MypageAction().execute(request, response);
		} else if (action.equals("/loginPage.do")) {
			forward = new ActionForward();
			forward.setPath("login.jsp");
			forward.setRedirect(true);
		} else if (action.equals("/login.do")) {
			forward = new LoginAction().execute(request, response);
		} else if (action.equals("/replySelectOne.do")) {
			forward = new ReplySelectOneAction().execute(request, response);
		} else if (action.equals("/replyInsert.do")) {
			forward = new ReplyInsertAction().execute(request, response);
		} else if (action.equals("/replyUpdate.do")) {
			forward = new ReplyUpdateAction().execute(request, response);
		} else if (action.equals("/replyDelete.do")) {
			forward = new ReplyDeleteAction().execute(request, response);
		} else if (action.equals("/changeName.do")) {
			forward = new ChangeNameAction().execute(request, response);
		} else if (action.equals("/memberDelete.do")) {
			forward = new MemberDeleteAction().execute(request, response);
		} else {

		}

		if (forward == null) {
			// 에러 상황
		}

		if (forward.isRedirect()) {
			response.sendRedirect(forward.getPath());
		} else {
			RequestDispatcher dispatcher = request.getRequestDispatcher(forward.getPath());
			dispatcher.forward(request, response);
			// pageContext.forward(forward.getPath());
		}
	}
}

여기서드는 의문!

FrontController는 HttpServlet을 상속받은 클래스이며, doGet, doPost, doAction을 메서드로 가지고있다.

또한 각 기능에서 return받은 forward의 path와 redirect를 확인해서 원하는곳으로 페이지를 이동시켜준다.

이때 doGet, doPost, doAction 는 static이 아니라서 호출하려면 객체를 만든 후에 호출이 되어야하는데, 
객체생성된곳도 없고 호출된곳도 없다 어떻게 된일일까?!?!?!?!

 

★ ★ ★ ★ ★ ★ ★ 바로바로 new FrontController()는 톰캣이 해준다!!!!!!!!!! 댑악
그리고 FrontController 객체가 .doGet(); .doPost() 하고있는것이다!!!!!!!!
★ ★ ★ ★ ★ ★ ★
.doActuon() 메서드가 static이 아님 즉, 객체가 실행중임 근데? 객체화를 한적이 없음 ...ㅎㄷㄷㄷㄷㄷ 뭥미 누가해줌 ..?!?!?! new FrontController() 를 누가할까 ..?!?!?!
정담 : 톰캣 (웹 서버, "서블릿 컨테이너")

 

여기서 서블릿 컨테이너의 뜻은

서블릿 == .java, 서블릿  파일, not POJO

컨테이너 == 객체화를 해주는 주체, 객체를 생성하는 주체, new 를 수행하는 주체

서블릿 컨테이너는 신호를(설정을) 받으면 해당 서블릿을 new  해주리고 약속되어있는데, 이신호(설정)이 @webServelt("*.do") 이다 !!!

 

어노테이션 @ 으로 (==컨테이너를 활용해서) new 를 수행하면 사이인이유!!!!!!댕사기 
★ "싱글톤 패턴"을 유지시켜줌 
       == 전체 프로그램에 해당 객체가 단 1개 존재한다. 댑악 
메인 회원가입 메인 회원가입 이렇게하면 new로 객체를 계속생성 ㅡ_ㅡ  심지어 안에 DAO DTO는 개많이생성됨!! 나중엔 메모리부족

컨테이너를 활용하면, 기존에 해당 객체가 있다면 더이상 new를 안한다. 따라서 스프링을 쓰는것이다!!!
스프링의 다른말이 스프링컨테이너~ !!!

WAS(Web Application Server)

WAS란 DB 조회 혹은 다양한 로직 처리를 요구하는 동적 컨텐츠를 제공하기 위해 만들어진 Application 서버이다. HTTP 프로토콜을 기반으로 사용자 컴퓨터나 장치에 애플리케이션을 수행해주는 미들웨어로서, 주로 데이터베이스 서버와 같이 수행된다.

 

WAS는 JSP, Servlet 구동환경을 제공해주기 때문에 서블릿 컨테이너 혹은 웹 컨테이너로 불린다.

 

이러한 WAS는 웹 서버의 기능들을 구조적으로 분리하여 처리하고자 하는 목적으로 제시되었다. 분산 트랜잭션, 보안, 메시징, 쓰레드 처리 등의 기능을 처리하는 분산 환경에서 사용된다. WAS는 프로그램 실행 환경과 DB 접속 기능을 제공하고, 여러 개의 트랜잭션을 관리 가능하다. 또한 비즈니스 로직을 수행할 수 있다.

 

이러한 WAS에는 Tomcat, JBoss, WebSphere 등이 있다. 

 

WAS는 Web Server와 Web Container의 역할을 모두 할 수 있다. 여기서 컨테이너는 JSP, Servlet을 실행시킬 수 있는 소프트웨어를 말한다. 현재 WAS의 웹 서버도 정적인 컨텐츠를 처리하는 데 성능상 큰 차이가 없다.

 

그렇다면 WAS가 웹 서버의 기능까지 모두 수행하면 되는 것일까? 

 

웹 서버와 WAS를 분리해야 한다. 그 이유는 다음과 같다.

 

1. 서버 부하 방지

WAS와 웹 서버는 분리하여 서버의 부하를 방지해야 한다. WAS는 DB 조회나 다양한 로직을 처리하고, 단순한 정적 컨텐츠는 웹 서버에서 처리해줘야 한다. 만약 정적 컨텐츠까지 WAS가 처리한다면 부하가 커지게 되고, 수행 속도가 느려질 것이다. 

 

2. 보안 강화

SSL에 대한 암호화, 복호화 처리에 웹 서버를 사용 가능

 

3. 여러 대의 WAS 연결 가능

로드 밸런싱을 위해 웹 서버를 사용할 수 있다. 여러 개의 서버를 사용하는 대용량 웹 어플리케이션의 경우 웹 서버와 WAS를 분리하여 무중단 운영을 위한 장애 극복에 쉽게 대응할 수 있다. 

 

4. 여러 웹 어플리케이션 서비스 가능

하나의 서버에서 PHP, JAVA 애플리케이션을 함께 사용할 수 있다. 

 

이러한 이유로 웹 서버를 WAS 앞에 두고 필요한 WAS들을 웹 서버에 플러그인 형태로 설정하면 효율적인 분산 처리가 가

웹 서비스는 아래와 같이 다양한 구조를 가질 수 있다.

 

1. Client -> 웹 서버 - > DB

2. Client -> WAS -> DB

3. Client -> 웹 서버 -> WAS -> DB (상위그림)

 

 

*참조

https://code-lab1.tistory.com/199

 

'코리아IT핀테크과정' 카테고리의 다른 글

Image Upload [TEAM PROJECT]  (0) 2024.01.13
MVC pattern2에서 alert 구현하기  (1) 2024.01.11
JSP 3  (0) 2024.01.08
JSP practice  (0) 2024.01.06
JSP2  (0) 2024.01.05
Comments