[TIL-260310] Servlet & JSP 입문: 서블릿의 응답 처리, DB 연동

2026. 3. 10. 17:58·Java

Servlet 기초

서블릿의 응답 처리

  1. doGet()이나 doPost() 메서드 안에서 처리
  2. javax.servlet.http.HttpServletResponse 객체 이용
  3. setContentType()을 이용해 클라이언트에게 전송할 데이터 종류(MIME_TYPE)를 지정
  4. 브라우저(클라이언트)와 서블릿의 통신은 자바 IO 스트림을 이용
package ex01;

import java.io.IOException;
import java.io.PrintWriter;

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

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    public void init() {
        System.out.println("init 메소드 호출");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8"); // 웹브라우저에서 전송된 데이터의 인코딩 설정
        response.setContentType("text/html;charset=utf-8"); // 응답할 데이터 종류를 html로 설정
        PrintWriter out = response.getWriter(); // 출력 스트림 객체 받아옴

        String user_id = request.getParameter("user_id");
        String user_pw = request.getParameter("user_pw");

        String data = "<html>";
        data += "<body>";
        data += "아이디 : " + user_id;
        data += "<br>";
        data += "비밀번호 : " + user_pw;
        data += "</body>";
        data += "</html>";
        out.print(data); // PrintWriter의 print()를 이용해 HTML 태그 문자열을 웹브라우저로 출력
    }

    public void destory() {
        System.out.println("destroy 메소드 호출");
    }
}

위의 코드에서는 GET 방식으로 데이터를 처리했다.

 

GET과 POST 비교

GET 방식과 POST 방식을 비교해보자.

  GET 방식 POST 방식
서블릿에 데이터를 전송 시 데이터가 URL 뒤에 name=value 형태로 전송됨.
여러 개의 데이터 전송 시 &로 구분해서 전송
TCP/IP 프로토콜 데이터의 HEAD 영역에 숨겨진 채 전송됨
보안 보안에 취약 보안에 유리
전송 데이터 용량 데이터의 최대길이는 255자 무제한
속도 POST 방식보다 빠름 전송 시 서블릿에서는 또 다시 가져오는 작업을 해야하므로 처리 속도가 GET 방식보다 느림
데이터 처리 서블릿에서 doGet()으로 전송된 데이터 처리 서블릿에서 doPost()를 이용해 데이터 처리

 

POST 방식으로 변경

package ex01;

import java.io.IOException;
import java.io.PrintWriter;

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

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    public void init() {
        System.out.println("init 메소드 호출");
    }

    // doGet 메서드를 doPost 메서드로 변경
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8"); // 웹브라우저에서 전송된 데이터의 인코딩 설정
        response.setContentType("text/html;charset=utf-8"); // 응답할 데이터 종류를 html로 설정
        PrintWriter out = response.getWriter(); // 출력 스트림 객체 받아옴

        String user_id = request.getParameter("user_id");
        String user_pw = request.getParameter("user_pw");

        String data = "<html>";
        data += "<body>";
        data += "아이디 : " + user_id;
        data += "<br>";
        data += "비밀번호 : " + user_pw;
        data += "</body>";
        data += "</html>";
        out.print(data); // PrintWriter의 print()를 이용해 HTML 태그 문자열을 웹브라우저로 출력
    }

    public void destory() {
        System.out.println("destroy 메소드 호출");
    }
}

 

login.html도 form 태그의 method를 post로 바꾼다.

이번엔 자바스크립트를 이용해 서블릿을 요청해봤다.

로그인 버튼을 클릭했을 때 fn_validate() 함수가 실행되어 아이디, 비밀번호의 유효값을 검증하고 submit()을 호출해 /login 경로로 데이터를 보낸다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 창</title>
<script>
function fn_validate(){
    var f = document.frmLogin;
    var user_id = f.user_id.value;
    var user_pw = f.user_pw.value;

    if((user_id.length == 0 || user_id == "") || (user_pw.length == 0 || user_pw == "")){
        alert("아이디와 비밀번호는 필수입니다");
    } else {
        f.method = "post";
        f.action = "login";
        f.submit();
    }
}
</script>
</head>
<body>
    <form name="frmLogin" method="post" action="login" encType="UTF-8">
        <input type="hidden" name="address" value="서울시 성동구">
        아이디 : <input type="text" name="user_id"><br>
        비밀번호 : <input type="password" name="user_pw"><br>
        <input type="checkbox" name="subject" value="java" checked> 자바 
        <input type="checkbox" name="subject" value="python" > 파이썬
        <input type="checkbox" name="subject" value="JSP" > JSP
        <input type="checkbox" name="subject" value="kotlin" > 코틀린<br>
        <input type="button" onclick="fn_validate();" value="로그인"><input type="reset" value="reset">
    </form>
</body>
</html>

 

GET 방식, POST 방식 동시 처리

전송된 방식에 따라 doGet()이나 doPost()로 처리한 후 다시 doHandle()을 호출해서 모든 기능을 구현할 수도 있다.

 


데이터베이스 연동

오라클에서 SQL Developer를 다운로드한 후 압축 풀고 exe 파일을 실행한다.

그리고 +버튼을 눌러 DB서버 접속을 만든다.

테스트 버튼 눌러서 성공하면 접속한다.

 

1. 테이블 생성 및 오라클 드라이버 추가

오라클 SQL Developer에서 쿼리문을 다음과 같이 작성한다.

CREATE TABLE t_member (
    id varchar2(10) PRIMARY KEY,
    pwd varchar2(10),
    name varchar2(50),
    email varchar2(50),
    joinDate date DEFAULT SYSDATE
)

INSERT INTO t_member
VALUES('mok', '1212', '황시목', 'mok@gmail.com', sysdate);
INSERT INTO t_member
VALUES('yeojin', '1111', '한여진', 'jin@gmail.com', sysdate);
INSERT INTO t_member
VALUES('dongjae', '1234', '서동재', 'seo@gmail.com', sysdate);

commit;

오라클은 자동 커밋이 아니기 때문에 반드시 commit을 해줘야 한다.

 

그리고 ojdbc6.jar를 다운로드 받아 WEB-INF/lib 안에 복사한다.

ojdbc6.jar: 자바(Java) 애플리케이션이 오라클 데이터베이스와 연동(연결 및 SQL 실행)할 수 있도록 도와주는 자바 라이브러리 파일(JDBC 드라이버)

 

2. 예제 코드 작성

웹 브라우저에서 /member URL로 회원 정보를 요청하면 브라우저에 회원 정보를 테이블로 만들어서 출력하는 예제를 실습한다.

 

  1. 웹 브라우저가 서블릿에게 회원 정보를 요청
  2. MemberServlet은 요청을 받은 후 MemberDAO 객체를 생성하여 listMembers() 메서드를 호출
  3. listMembers()에서 다시 connDB() 메서드를 호출하여 DB와 연결한 후 SQL문을 실행해 회원 정보를 조회
  4. 조회된 회원 정보를 MemberVO 속성에 설정한 후 다시 ArrayList에 저장
  5. ArrayList를 다시 메서드를 호출한 MemberServlet으로 반환한 후 ArrayList의 MemberVO를 차례대로 가져와 회원 정보를 HTML 태그의 문자열로 만듦
  6. 만들어진 HTML 태그를 웹 브라우저로 전송해서 회원 정보를 출력

 

MemberVO.java

package ex02;

import java.sql.Date;

// Member Value Object의 줄임말
public class MemberVO {
    private String id;
    private String pwd;
    private String name;
    private String email;
    private Date joinDate;

    public MemberVO() {
        System.out.println("MemberVO 생성자 호출");
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getJoinDate() {
        return joinDate;
    }

    public void setJoinDate(Date joinDate) {
        this.joinDate = joinDate;
    }

}

 

MemberDAO.java

package ex02;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

//Member Data Access Object의 줄임말
public class MemberDAO {
    private static final String driver = "oracle.jdbc.driver.OracleDriver";
    private static final String url = "오라클 서버 url";
    private static final String user = "사용자 이름";
    private static final String pwd = "비밀번호";
    private Connection con;
    private Statement stmt;


    public List<MemberVO> listMembers(){
        List<MemberVO> list = new ArrayList<MemberVO>();
        try {
            connDB(); // 네 가지 정보로 DB를 연결
            String query = "select * from t_member";
            System.out.println(query);
            ResultSet rs = stmt.executeQuery(query);
            while (rs.next()) {
                String id = rs.getString("id");
                String pwd = rs.getString("pwd");
                String name = rs.getString("name");
                String email = rs.getString("email");
                Date joinDate = rs.getDate("joinDate");

                MemberVO vo = new MemberVO();
                vo.setId(id);
                vo.setPwd(pwd);
                vo.setName(name);
                vo.setEmail(email);
                vo.setJoinDate(joinDate);
                list.add(vo);
            }
            rs.close();
            stmt.close();
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list; // 조회한 레코드의 개수만큼 ArrayList를 반환
    }


    private void connDB() {
        try {
            Class.forName(driver);
            System.out.println("Oracle 드라이버 로딩 성공");
            con = DriverManager.getConnection(url, user, pwd);
            System.out.println("Connection 생성 성공");
            stmt = con.createStatement();
            System.out.println("Statement 생성 성공");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

MemberServlet.java

package ex02;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Date;
import java.util.List;

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("/member") // '/member' 경로로 들어오면 이 서블릿이 동작됨
public class MemberServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        MemberDAO dao = new MemberDAO();
        List<MemberVO> list = dao.listMembers();

        out.print("<html><body>");
        out.print("<table border=1><tr align='center' bgcolor='lightgreen'>");
    out.print("<td>아이디</td><td>비밀번호</td><td>이름</td><td>이메일</td><td>가입일</td><td>삭제</td></tr>");

    // 조회한 회원 정보를 리스트로 출력
    for(int i = 0; i < list.size(); i++) {
        MemberVO memberVO = (MemberVO)list.get(i);
        String id = memberVO.getId();
        String pwd = memberVO.getPwd();
        String name = memberVO.getName();
        String email = memberVO.getEmail();
        Date joinDate = memberVO.getJoinDate();
        out.print("<tr><td>" + id + "</td><td>"
                + pwd + "</td><td>" 
                + name + "</td><td>" 
                + email + "</td><td>" 
                + joinDate + "</td><td><a href='/ServletEx/member?command=delMember&id="+id+"'>삭제</a></td></tr>");
        }
        out.print("</table></body></html>");
    }
}

 

3. 결과 확인

 

PreparedStatement

위의 코드에서는 Statement 인터페이스를 이용해 DB와 연동했다. 이 경우 매번 SQL문을 컴파일해야 하므로 속도가 느리다.

 

PreparedStatement 인터페이스를 사용하면 SQL문을 미리 컴파일해서 재사용하므로 Statement 인터페이스보다 빠르게 DB작업 수행이 가능하다.

 

Statement로 3번 조회하는 경우

Statement stmt = con.createStatement();

for(int i = 1; i <= 3; i++) {
    String query = "SELECT * FROM member WHERE id=" + i;

    ResultSet rs = stmt.executeQuery(query);

    while(rs.next()) {
        System.out.println(rs.getString("name"));
    }
}

 

DB 내부 흐름

Java
 ↓
SELECT * FROM member WHERE id=1
 ↓
DB
 ↓
1. SQL 파싱(해석)
2. SQL 컴파일
3. 실행
4. 결과 반환

Java
 ↓
SELECT * FROM member WHERE id=2
 ↓
DB
 ↓
1. SQL 파싱(해석)
2. SQL 컴파일
3. 실행
4. 결과 반환

Java
 ↓
SELECT * FROM member WHERE id=3
 ↓
DB
 ↓
1. SQL 파싱(해석)
2. SQL 컴파일
3. 실행
4. 결과 반환

이렇게 매번 SQL문을 해석하고 컴파일 한다.

 

PreparedStatement로 3번 조회하는 경우

String query = "SELECT * FROM member WHERE id = ?";

PreparedStatement pstmt = con.prepareStatement(query);

for (int i = 1; i <= 3; i++) {
    pstmt.setInt(1, i);
    ResultSet rs = pstmt.executeQuery();

    while(rs.next()) {
        System.out.println(rs.getString("name"));
    }
}

 

DB 내부 흐름

// 처음 준비할 때
Java
 ↓
SELECT * FROM member WHERE id = ?
 ↓
DB
 ↓
1. SQL 파싱
2. SQL 컴파일
3. 실행 계획 저장

// 1~3번째 실행
값 전달
? = 1
 ↓
이미 컴파일된 SQL 실행
 ↓
결과 반환

값 전달
? = 2
 ↓
이미 컴파일된 SQL 실행
 ↓
결과 반환

값 전달
? = 3
 ↓
이미 컴파일된 SQL 실행
 ↓
결과 반환

총 1번 컴파일 한다.

 

정리하면,

Statement → SQL 자체가 매번 새로 생성
PreparedStatement → SQL 구조는 고정, 값만 변경

따라서, DB연동 시 또는 빠른 반복 처리가 필요할 때 PreparedStatement 인터페이스를 사용해야 한다.

 


❕느낀점

너무 어렵지만 재밌기도 하다. 데이터베이스 연동이라는게 엄청 어려울 줄 알았는데 생각보다는 간단해서 좋았다.

jdbc를 잘 익혀서 팀 과제에 사용할 수 있게 해야겠다.

'Java' 카테고리의 다른 글

[TIL-260312] Servlet & JSP 입문: JSP 내장 객체, 액션 태그, 모델2  (0) 2026.03.13
[TIL-260311] Servlet & JSP 입문: 커넥션 풀, JSP 정의, JSP 스크립트  (1) 2026.03.12
[TIL-260309] Servlet & JSP 입문: JSP 실습, Servlet 기초  (0) 2026.03.10
[TIL-260306] Servlet & JSP 입문: 자바와 웹, 웹 애플리케이션, HTTP  (0) 2026.03.08
[TIL-260212] 자바 기초: 내부 클래스, 스레드, 람다, 스트림  (0) 2026.02.17
'Java' 카테고리의 다른 글
  • [TIL-260312] Servlet & JSP 입문: JSP 내장 객체, 액션 태그, 모델2
  • [TIL-260311] Servlet & JSP 입문: 커넥션 풀, JSP 정의, JSP 스크립트
  • [TIL-260309] Servlet & JSP 입문: JSP 실습, Servlet 기초
  • [TIL-260306] Servlet & JSP 입문: 자바와 웹, 웹 애플리케이션, HTTP
hee-on
hee-on
작은 기록을 모아 꾸준히 성장해 나가는 개발 기록 공간입니다💻
  • hee-on
    희온의 dev log
    hee-on
  • 전체
    오늘
    어제
    • 전체 글 (46)
      • About (2)
      • Java (15)
      • Spring (4)
      • Spring Boot (2)
      • Front-end (6)
      • 알고리즘 (6)
        • Do it 알고리즘 코딩테스트 (자바편) (4)
      • DB (7)
      • Git (1)
      • 개발 지식 (2)
      • 일상 || 잡담 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    JSP
    백준
    react
    Java
    Spring
    til
    SQL
    Servlet
    안티그래비티
    깃허브 코파일럿
    취준
    백엔드
    MVC
    소개
    코테
    개발자
    JavaScript
    알고리즘
    SpringBoot
    db
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
hee-on
[TIL-260310] Servlet & JSP 입문: 서블릿의 응답 처리, DB 연동
상단으로

티스토리툴바