Java

Servlet이랑 jsp

chaebideas77 2026. 6. 24. 22:10

어제 수업을 안 들어서..

급하게 Tomcat을 다운 받고..

강의 자료 다운 받고..

오늘은 JSP랑 Servlet을 대략적으로 공부했는데.. 일단 이전에 jdbc로 만든 자바 파일을 서버로 옮기는 느낌이었다

 

톰캣(Tomcat)

강의실 가자마자 톰캣을 다운 받았다. 많이 들어봤는데 이게 뭐하는건지는 잘 몰랐는데 역시 직접 해보니까 

알겠다. 자바 서블릿 컨테이너(Servlet Container) 또는 WAS(Web Application Server)로  서블릿과 JSP가 실행될 수 있는 환경(서버)을 제공하고 관리한다. 

localhost:8080으로 접속해서 내가 만든 코드를 화면으로 띄워주는 역할!

 

서블릿(Servlet)

Java 코드로 웹을 처리한다고 간단하게 보면 된다.

클라이언트(사용자)의 요청(POST/GET)을 받아 DB를 조회하고 비즈니스 로직을 처리

기존에는 이 자바 코드에 html(프론트)영역까지 입력해서 코드가 매우 지저분했는데 그래서 나온게 JSP!

 

JSP(Java Server Page)

HTML 화면에 Java를 얹은.. 즉 프론트 영역 이건 코드로 보는게 빠를듯 싶다.

 

예를 들어 empinsert.jsp와 empinsertservlet.java 코드로 얘기해보겠다.

 

이게 대표적인 JSP 

emp.css를 이용해 html을 꾸민 내용은 제외하겠다.

 

form 폼형식에 action은 즉 insert.do 페이지에서 진행하겠다. post (전송)하겠다는 의미

<form action="insert.do" method="post">

이 폼에 입력한 데이터들을 insert.do라는 주소(URL)로 보내서 처리하겠다

 

<div>
     <label for="empid">직원번호</label>
     <input required type="number" id="empid" name="employee_id">
</div>

label for는 직원번호를 입력(input)란에 입력 시 커서가 깜빡이게 연결

type은 입력란에 숫자가 들어가야한다는 의미이며, required는 직원번호가 null 값이 될 수 없다는 의미

id는 추후에 html을 꾸밀 때 css, js에서 태그 입력 시 필요한 구분자라고 보면 된다.

name이 중요한데 서버(Back-end)로 데이터를 보낼 때, 자바가 데이터를 구별하기 위해 쓰는 이름 (Key).

사용자가 입력한 값은 Value가 되어 Key=Value 형태로 서버에 전송

id는 내 눈에 보이는 화면(Client)이 입력창을 찾기 위한 이름표고, 
name은 눈에 보이지 않는 서버(Server)가 데이터를 찾아가기 위한 이름표다!   제미나이가 정리해줌..

 

<div>
     <label>부서:</label>
     <select name="department_id">
     <option value="">부서없음</option>
     	<c:forEach var="dept" items="${deptlist}">
	    	<option value="${dept.department_id}">${dept.department_name}</option>
		</c:forEach>
     </select>
  </div>

name="department_id" 속성이 부여되어 있으므로, 사용자가 최종 선택한 값은 서버(Servlet)에서 request.getParameter("department_id")로 꺼낼 수 있음!

<option value=""> 부서없음 </option>

기본값으로 화면에 '부서없음'으로 뜨고

부서없음'을 선택하고 전송하면 value=""  빈 문자열(Empty String)이 서버로 전송

서버(Servlet) 측에서는 이 빈 값을 체크하여 DB에 null로 안전하게 집어넣는 로직이 필요

forEach문은 자바의 향상된 for문

 

  • 화면 표시 (${dept.department_name}): 태그 사이에 위치하여 사용자의 눈에 보이는 부서명(예: 인사부, 개발부)
  • 실제 전송 데이터 (value="${dept.department_id}"): 사용자가 부서명을 선택하더라도, 실제 서버로 전송되는 값은 value 속성에 담긴 고유한 식별자인 '부서 아이디(숫자)'
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 1. 서비스 객체 생성 및 DB 데이터 조회
    DeptService deptService = new DeptService();
    
    // 2. 가방(request)에 조회한 부서 리스트 담기
    request.setAttribute("deptlist", deptService.selectAll());
    
    // 3. 데이터를 넘겨줄 목적지(JSP) 지정 및 화면 위임(Forward)
    RequestDispatcher rd = request.getRequestDispatcher("empinsert.jsp");
    rd.forward(request, response);
}

 

이제 서블릿을 보면 doGet 함수가 있다.

DeptService.java에 부서리스트 전체를 조회하는 함수를 작성했다.

setAttribute에 deptService.selectAll()을 이용해서 deptlist에 담고

dispatcher를 이용해 jsp 파일을 forward

 

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("EmpInsert...Post방식(요청문서의 Body로 들어온다.)");
    
    // 1. 한글 깨짐 방지 설정
    request.setCharacterEncoding("UTF-8");
    
    // 2. 입력 데이터 추출 및 DTO 객체 생성 (포장)
    EmpDTO emp = makeEmp(request);
    
    // 3. 비즈니스 로직(Service)을 통한 DB Insert 실행
    EmpService empService = new EmpService();
    int result = empService.insertService(emp);
    System.out.println(result + "건 입력");
    
    // 4. 중복 제출 방지를 위한 페이지 이동 (Redirect)
    response.sendRedirect("list.do");
}

이번에는 입력한 데이터를 전송하는 함수다.

EmpDTO.java에 필요한 필드 값을 다 적어놓았다.

EmpService.java에는 insert 로직을 작성해놓았고

몇 건이 입력되었는지 알기 위해 result 변수에 담았다.

데이터를 DB에 새로 넣거나 수정/삭제할 때는 새로고침 중복 방지를 위해 끝나고

무조건 Redirect로 페이지를 튕겨준다

 

만약 forward를 쓴다면?

화면은 목록 페이지가 보일지 몰라도 주소창에는 여전히 insert.do(저장 요청)가 남아있게 된다.

이 상태에서 사용자가 새로고침(F5)을 누르면 방금 입력한 직원 정보가 DB에 또 인서트되는 중복 등록 에러가 발생

 

private EmpDTO makeEmp(HttpServletRequest request) { ... }

request.getParameter() → 낱개 문자열 수집

JSP 폼의 각 <input name="속성명"> 태그에 지정된 name 값을 Key로 삼아 사용자가 입력한 알맹이를 꺼낸다.

String s_empid = request.getParameter("employee_id");

웹 브라우저를 통해 서버로 들어오는 모든 데이터는 숫자가든 날짜든 일단 무조건 문자열(String) 타입으로 들어온다.

 

Integer deptid = (s_deptid != null && !s_deptid.isEmpty()) ? Integer.parseInt(s_deptid) : null;

부서명이 null 값이 아니고 비어있지 않다면? String 변수로 받았기 때문에 Integer.parseInt로 형변환을

해준 후 deptid에 넣어준다.

 

EmpDTO emp = EmpDTO.builder().employee_id(empid)...build();

빌더 패턴을 사용하는 이유 : 사원 테이블처럼 채워야 할 필드(데이터)가 10개가 넘어갈 때, 일반적인 생성자(new EmpDTO(empid, first_name, ...))를 쓰면 값의 순서가 조금만 뒤바뀌어도 엉뚱한 컬럼에 데이터가 들어가는 대참사 발생

빌더 패턴을 사용하면 .employee_id(empid), .salary(salary) 처럼 어떤 필드에 어떤 변수를 넣는지 눈으로 명확하게 매칭하면서 객체를 생성할 수 있다.

'Java' 카테고리의 다른 글

자바 jdbc로 미니 프로젝트  (0) 2026.06.16
스레드  (0) 2026.06.01
제네릭  (0) 2026.06.01
이것이 자바다 연습문제 Chap12  (0) 2026.06.01
참조형 변수  (1) 2026.05.19