JSP/Servlet_09) Ajax를 사용한 비동기 방식
2025. 10. 16. 16:46

학습 목표

  • Ajax의 개념과 동작 원리 이해
  • jQuery를 활용한 Ajax 구현 방법
  • 서버와 클라이언트 간 비동기 통신 구현
  • 실제 프로젝트에서 Ajax 활용 사례 분석

<Ajax의 기본 개념>

Ajax란 무엇인가

Ajax(Asynchronous JavaScript and XML)는 웹페이지를 새로고침 없이 서버와 데이터를 요청하고 응답받는 기술이다.

기존 웹 개발 방식과 Ajax의 차이점:

기존 방식:

  • 버튼 클릭 시 페이지 전체가 서버에 전송
  • 응답을 받기 전까지 화면 전체가 흰 화면에서 대기
  • 서버에서 새로운 HTML을 만들어서 리턴
  • 매번 화면이 깜빡이는 현상 발생

Ajax 방식:

  • 페이지 새로고침 없이 필요한 데이터만 서버와 통신
  • 사용자 경험 향상
  • 빠른 응답 속도

Ajax의 핵심 특징

  • 비동기 처리: 서버 응답을 기다리지 않고 다른 작업 수행 가능
  • 부분 업데이트: 전체 페이지가 아닌 필요한 부분만 업데이트
  • JSON 데이터 형식: XML 대신 JSON을 주로 사용

<jQuery Ajax 구현 방법>

기본 Ajax 문법

$.ajax({
    url: "요청을 보낼 주소",
    type: "요청 방식", // GET, POST
    data: {}, // 전송할 데이터
    dataType: "json", // 응답 데이터 타입
    success: function(result) {
        // 성공 시 실행 코드
    },
    error: function(err) {
        // 실패 시 실행 코드
    }
});

XMLHttpRequest 객체를 이용한 순수 JavaScript Ajax

const xhr = new XMLHttpRequest();
xhr.open("GET", "idDuplicateCheck.me?checkId=" + encodeURIComponent(userId), true);

xhr.onreadystatechange = function() {
    if(xhr.readyState === 4) { // 요청이 완료되었을 때
        if(xhr.status === 200) { // 요청이 성공했을 때
            const result = xhr.responseText;
            // 결과 처리
        }
    }
};
xhr.send();

<실제 프로젝트 Ajax 구현 사례>

프로젝트 github : https://github.com/jinwoojaemeon/khWorkspace/tree/main/04_Servlet/jspProject

아이디 중복 확인 기능

클라이언트 측 구현 (enrollForm.jsp):

function idDuplicateCheck() {
    const idInput = document.querySelector("#enroll-form input[name=userId]").value;
    $.ajax({
        url: "idDuplicateCheck.me",
        type: "get",
        data: {checkId: idInput},
        success: function(result) {
            if(result === "NNNNN") {
                alert("이미 존재하는 아이디입니다.");
                idInput.focus();
            } else {
                alert("사용 가능한 아이디입니다. 사용하시겠습니까?");
                idInput.setAttribute("readonly", true);
            }
        },
        error: function(err) {
            console.log("아이디 체크 요청 실패");
        }
    });
}

서버 측 구현 (AjaxIdCheckController.java):

@WebServlet("/idDuplicateCheck.me")
public class AjaxIdCheckController extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String checkId = request.getParameter("checkId");

        int count = new MemberService().idCheck(checkId);
        if(count > 0) {
            response.getWriter().print("NNNNN"); // 중복됨
        } else {
            response.getWriter().print("NNNNY"); // 사용가능
        }
    }
}

실행 결과:


사용자가 아이디를 입력하고 중복확인 버튼 클릭

→ 서버에서 중복 여부 확인

→ "NNNNN" 또는 "NNNNY" 문자열로 응답

→ 클라이언트에서 결과에 따른 알림 표시

댓글 시스템 구현

댓글 목록 조회:

function getReplyList(bno, callback) {
    $.ajax({
        url: "rlist.bo",
        dataType: "json", // 응답 데이터 타입
        data: {
            boardNo: bno
        },
        success: function(res) {
            callback(res, bno);
        },
        error: function(err) {
            console.log("댓글 로드 ajax 실패");
        }
    });
}

서버 측 댓글 목록 조회 (AjaxReplyListController.java):

@WebServlet("/rlist.bo")
public class AjaxReplyListController extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        int boardNo = Integer.parseInt(request.getParameter("boardNo"));

        ArrayList<Reply> list = new BoardService().selectReplyByBoardNo(boardNo);

        response.setContentType("application/json; charset=UTF-8");
        new Gson().toJson(list, response.getWriter()); // JSON으로 변환하여 응답
    }
}

댓글 작성:

function insertReply(bno) {
    const contentInput = document.querySelector("#reply-content");

    $.ajax({
        url: "rinsert.bo",
        type: "post",
        data: {
            boardNo: bno,
            content: contentInput.value
        },
        success: function(res) {
            if(res === "1") {
                contentInput.value = ""; // 입력창 초기화
                getReplyList(bno, drawReplyList); // 댓글 목록 새로고침
            }
        },
        error: function(err) {
            console.log("댓글 작성 ajax 실패");
        }
    });
}

서버 측 댓글 작성 (AjaxReplyInsertController.java):

@WebServlet("/rinsert.bo")
public class AjaxReplyInsertController extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        int boardNo = Integer.parseInt(request.getParameter("boardNo"));
        String replyContent = request.getParameter("content");
        int memberNo = ((Member)(request.getSession().getAttribute("loginMember"))).getMemberNo();

        Reply r = new Reply();
        r.setRefBoardNo(boardNo);
        r.setReplyContent(replyContent);
        r.setReplyWriter(memberNo);

        int result = new BoardService().insertReply(r);
        response.getWriter().print(result); // 성공 시 1, 실패 시 0
    }
}

댓글 삭제:

function deleteReply(replyNo, callback) {
    $.ajax({
        url: "rdelete.bo",
        data: {
            replyNo: replyNo
        },
        success: function(res) {
            if(res === "1") {
                callback(); // 삭제 성공 시 콜백 함수 실행
            }
        },
        error: function(err) {
            console.log("댓글 삭제 ajax 실패");
        }
    });
}

<Ajax 응답 데이터 처리>

JSON 데이터 활용

Gson 라이브러리를 이용한 JSON 변환:

// 서버에서 객체를 JSON으로 변환
response.setContentType("application/json; charset=UTF-8");
new Gson().toJson(list, response.getWriter());

클라이언트에서 JSON 데이터 처리:

// dataType: "json"으로 설정하면 자동으로 JSON 파싱
success: function(replyList) {
    for(let r of replyList) {
        // r.replyNo, r.replyContent 등으로 접근 가능
    }
}

응답 데이터 타입별 처리

  • text: 일반 문자열 응답
  • json: JSON 객체로 자동 파싱
  • html: HTML 태그가 포함된 문자열
  • xml: XML 형식 데이터

<Ajax 에러 처리>

클라이언트 측 에러 처리

$.ajax({
    url: "rlist.bo",
    dataType: "json",
    success: function(res) {
        // 성공 시 처리
    },
    error: function(xhr, status, error) {
        console.log("요청 실패:", status, error);
        // 에러 발생 시 사용자에게 알림
    }
});

서버 측 응답 코드

// 성공/실패를 숫자로 구분
int result = new BoardService().insertReply(r);
response.getWriter().print(result); // 1: 성공, 0: 실패

정리 및 요약

Ajax의 핵심 장점:

  1. 사용자 경험 향상: 페이지 새로고침 없이 동적 콘텐츠 업데이트
  2. 성능 최적화: 필요한 데이터만 전송하여 네트워크 트래픽 감소
  3. 반응성: 비동기 처리로 빠른 응답 속도

실제 구현 시 주의사항:

  1. 에러 처리: success와 error 콜백을 모두 구현
  2. 데이터 타입: JSON 형식으로 통일하여 데이터 처리 간소화
  3. 보안: 클라이언트 측 검증과 서버 측 검증 모두 필요

프로젝트에서 활용한 Ajax 기능:

  • 아이디 중복 확인
  • 댓글 CRUD (생성, 조회, 삭제)
  • 실시간 데이터 업데이트