ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 학원 day 97. ajax, each함수
    기록 2023. 1. 19. 11:13

    jQuery의 ajax

    $.get(url, data, function(response) { ... }, dataType)

                  * GET 방식의 ajax 요청을 서버로 보낸다.

                  * dataType은 서버의 응답컨텐츠 타입을 지정한다.

                  * dataType은 생략가능하다. 유추해서 알아내기 때문에 생략해도 되지만 적어놓으면 빠르니까 적는게 좋다.

     

    $.post(url, data, function(response) { ... }, dataType)

                  * POST 방식의 ajax 요청을 서버로 보낸다.

                  * dataType은 서버의 응답컨텐츠 타입을 지정한다.

                  * dataType은 생략가능하다.

     

    $.getJSON(url, data, function(response) { ... })

                  * GET 방식의 ajax 요청을 서버로 보낸다.

                  * 서버의 응답데이터가 json형식일 때만 사용한다.

                  * dataType이 "json"인 경우다.

                  * json 형식의 데이터를 서버로 보낼 때는 사용할 수 없다. (json형식의 데이터는 무조건 메세지의 body에 붙어서 가야한다.)

     

    $.ajax({name:value, name:value, name:value, ... });    /// put, delete는 위에 없으니까 이걸로 사용, ajax를 쓸 때는 거의 대부분 이걸로 사용한다.

                          name                value                                                             desc

                         -------------------------------------------------------------------------------------------------------------

                          type                  "GET", "POST", "PUT", "DELETE"          요청방식을 지정한다.

                          url                     "요청URL"                                                ajax 요청을 처리하는 서버의 URL을 지정한다.

                          data                  {name:value, name:value}                       요청파라미터로 전달된다. @RequestParam

                                                   "name=value&name=value"                     요청파라미터로 전달된다. @RequestParam

                                                   '{"name:":value, "name":value}'                json형식의 데이터를 보낼 때 사용된다.                                                                                                                                    @RequestBody를 사용해서 값을 전달받아야 한다.

    data는 서버로 보내는 값,   {name:value, name:value}는 자바스크립트 객체 표현방법인데 전달될 때 "name=value&name=value" 이렇게 전달된다. 

     

                        contentType      "application/x-www-form-urlencoded"     기본값, 서버로 보내는 데이터의 컨텐츠 타입을 지정한다.     {name:value, name:value} ->  "name=value&name=value", "name=value&name=value"                                                                                                                                 

                                                   "application/json"                                     서버로 보내는 데이터의 타입을 json으로 지정한다.   '{"name" : value, "name" : value}'

                                                   "text/xml"                                                 서버로 보내는 데이터의 타입을 xml로 지정한다.

    +)    json형식인 '{"name:":value, "name":value}'  를 사용하고   "application/x-www-form-urlencoded" 이걸 사용할 수 없다. 

    contentType을 뭘로 지정했느냐에 따라서, 데이터와 type을 적절하게 설정해야 한다. 

    contentType을 안적었으면 기본값은 "application/x-www-form-urlencoded"이다.             

    +) type을 GET으로 하고  '{"name:":value, "name":value}' 로 작성할 수 없다. json형식의 데이터는 무조건 @RequestBody와 매핑할 수 있다. json 형식은 반드시 요청메시지의 바디부에 붙어서 전달되기 때문이다. 

                                                         

    데이터타입의 종류

    dataType에 지정가능한 값 : "xml", "html", "text", "script", "json", "jsonp" 

    ( 컨텐츠타입과 다르게 줄임말로 적는다.) 

    ( cors라는 정책때문에 origin이 다른 도메인에 데이터를 요청했을 때 데이터를 못받아올 때에도 jsonp를 사용하면 가져올 수 있다. )

     

    * contentType : 클라이언트가 서버로 보내는 요청데이터 타입을 정하는 것 (주로 데이터를 보내는 post, put일때 contentType을 쓴다. get, delete일 때는 생략해도 된다.)

    * dataType : 서버가 클라이언트로 내려보내는 응답데이터타입을 정하는 것 (contentType과는 상관이 없음) 

     

    beforeSend    function(xhr) { ... }                               ajax요청을 서버로 보내기 직전에 지정된 함수가 실행된다.

    success          function(response) { ... }                ajax요청에 대한 성공적인 응답이 왔을 때 지정된 함수가 실행된다.

                                                                                     함수의 response 매개변수에는 서버가 보낸 응답데이터가 전달된다.

    error               function(xhr, status, error) { ... }          ajax 요청에 대한 오류가 발생했을 때 지정된 함수가 실행된다.

    complete        function(xhr, status) { ... }                   ajax 요청이 완료되었을 때(실패/성공여부와 상관없이) 지정된 함수가 실행된다.

     

    $.ajax() 사용예시 - 사용자 목록 조회

                  * 요청방식 : GET

                  * 요청 URL : "/users",

                  * 요청 데이터 : 없음

                  * 응답 데이터 : json

                   $.ajax({

                                 type : "GET", 

                                 url : "/users",

                                 dataType : "json",

                                 success : function(response) {

                                 },

                                error: function() {

                                }

                     });

    게시글 검색

     

    data를 자바스크립트 객체형식으로 보내면 실제로는 쿼리스트링 형식으로 변환되어서 전달된다. 

    서버의 응답데이터 타입은 거의 대부분 json형식이다.

     

    json형식에서는 모든 name은 쌍따옴표여야 한다.

    json 형식으로 오는 건 매개변수에 @RequestBody를 붙여야 한다.  json이 그대로 userRegisterForm에 그대로 들어간다. 

    @PostMapping("/users")

    @ResponseBody

    public User saveUser(@RequestBody UserRegisterForm userRegisterForm) {

    }

    요청파라미터 형태로 전달되면 @RequestBody를 굳이 붙이지 않는다. 요청메세지의 바디에 포함되어 오더라도..

    @RequestBody를 안붙이면 userRegisterForm의 객체의 멤버변수를 조사해서 똑같은 이름의 값을 getParameter로 꺼내서 가져오는 것이다.

    @RequestBody를 붙이면 데이터바인더라는 놈이 json형식의 텍스트를 변환해준다.


    ajax로 사용자 목록 출력하기

    $(function() {
    	
    	let $usersTbody = $("#table-user-list tbody");
    	
    	// 웹 페이지가 로딩될 때 서버로 ajax 요청을 보내서 사용자 목록을 가져오고, 테이블에 출력한다.
    	$.ajax({
    		type: "GET",
    		url: "http://localhost/users",
    		dataType: "json",
    		success: function(users) {
    			// $.each(배열, function(index, value) { ... }), forEach와 다르게 index가 먼저 나옴
    			$.each(users, function(index, user) {
    				let row = `
    					<tr>
    						<td>${index + 1}</td>
    						<td>${user.id}</td>
    						<td>${user.name}</td>
    						<td>${user.createdDate}</td>
                            <td><button type="button" class="btn btn-outline-primary btn-sm" data-user-id="${user.id}">상세</button></td>
    					</tr>
    				`
    				// $usersTbody 안에 row를 계속 추가
    				$usersTbody.append(row);
    			})
    		}
    	});
    });

    함수를 호출하거나, 클릭을 해야지 함수가 실행되는 코드이다.

    하지만 ajax는 함수 안에 있는 코드가 아니기 때문에 페이지 로딩하면 바로 실행된다.

     

    이벤트 등록하기

    <div class="col-6">
        <p>사용자 상세정보를 확인하세요</p>
        <div class="card">
            <div class="card-header">사용자 상세정보</div>
            <div class="card-body">
                <table class="table" id="table-user-info">
                    <colgroup>
                        <col width="20%">
                        <col width="30%">
                        <col width="20%">
                        <col width="30%">
                    </colgroup>
                    <tbody>
                        <tr>
                            <th>아이디</th>
                            <td id="cell-user-id"></td>
                            <th>이름</th>
                            <td id="cell-user-name"></td>
                        </tr>
                        <tr>
                            <th>이메일</th>
                            <td id="cell-user-email"></td>
                            <th>전화번호</th>
                            <td id="cell-user-tel"></td>
                        </tr>
                        <tr>
                            <th>가입일</th>
                            <td id="cell-user-created-date"></td>
                            <th>최종수정일</th>
                            <td id="cell-user-updated-date"></td>
                        </tr>
                    </tbody>
                </table>
                    <div class="text-end">
                        <button class="btn btn-danger btn-sm disabled" id="btn-del-user">삭제</button>
                        <button class="btn btn-warning btn-sm disabled" id="btn-modify-user">수정</button>
                    </div>

     

    $(this)는 제이쿼리 객체가 얻어진다. .attr은 속성값을 가져온다.

     

    let userId = $(this).closest("tr").find("td:eq(1)").text(); 

    button에서 가장 가까운 부모 tr을 찾는다. find는 자식을 찾는데 2번째있는 td를 찾는 것이다. 

    그런데 위의 방식은 나중에 화면 디자인이 바뀌어서 순서가 달라질 수 있기 때문에 위험한 방식이다.

    id로 찾는 방식이 가장 명확하다.  

    // $("컨테이너선택자").on('이벤트명', '대상엘리먼트 선택자', function() { ... })
    // 컨테이너선택자는 계속 존재하고 있어야 하는 것이어야 한다.
    // tbody에 나중에 미래에 추가되는 .btn-outline-primary 버튼에 대한 클릭 이벤트 발생시 실행될 이벤트핸들러함수를 등록한다.
    $("#table-user-list tbody").on('click', '.btn-outline-primary', function() {
        // this <--- <button type="button" class="btn btn-outline-primary btn-sm" data-user-id="hong">상세</button>
    
        $(this).closest("tr").addClass("table-primary")	// 클릭한 버튼이 포함된 tr에는 table-primary 클래스를 추가한다.	
               .siblings().removeClass('table-primary');// 클릭한 버튼이 포함된 tr의 형제 tr들에서는 table-primary 클래스를 제거한다.
        let userId = $(this).attr("data-user-id");
    
        $.get(`http://localhost/users/${userId}`, function(user) {
    
            $("#cell-user-id").text(user.id);
            $("#cell-user-name").text(user.name);
            $("#cell-user-email").text(user.email);
            $("#cell-user-tel").text(user.tel);
            $("#cell-user-created-date").text(user.createdDate);
            $("#cell-user-updated-date").text(user.updatedDate);
    
            $("#btn-del-user, #btn-modify-user").removeClass("disabled");  // 2개를 적고 싶을 때는 ,로 한다.
    
        }, 'json')   // 'json'은 데이터타입을 적어놓은 것이다.
    })

    상세버튼 클릭시, 사용자 상세정보 가져와서 출력하기,

    삭제, 수정버튼 활성화시키기

    confirm이라는 메소드를 실행하면 확인창이 뜨고 확인 클릭하면true, 취소 클릭하면 false를 answer로 받는다.

    삭제가 된 것을 확인할 수 있으나, 순번은 변경되지 않기 때문에 문제가 있다.

    에러가 났을 때 개발자창 화면

    오류가 발생했을 때, 개발자창 열어서 breakpoint 걸고 확인하기! 

    실행하는 것과 관련된 수행문에 breakpoint를 걸고 한스텝씩 옮기면서 확인하기!

    userId에 값이 없음을 확인할 수 있다.


    * 삭제 후 순번 변경하기 

    $(function() {
    	
    	let $usersTbody = $("#table-user-list tbody");
    	
    	function generateRowNumbers() {
    		$usersTbody.find("td:first-child").each(function(index, td) {
    			$(td).text(index + 1);
    		});
    	}


    jQuery의 each( ) 함수

    // 배열의 값들을 반복처리한다.
    $.each(배열, function(index, item) { ... })
    * 배열에 저장된 값을 갯수만큼 지정된 함수를 반복수행한다.
    * 함수가 실행될 때 마다 배열의 0번째 값부터 순서대로 하나씩 전달된다.
    * 함수의 매개변수 
      index : 지금 처리중인 값의 인덱스가 전달된다. 0부터 시작되는 숫자
      item : 지금 처리중인 배열의 값이 전달된다.
          [10, 20, 30, 40] 
                함수가 첫번째 실행될 때 item에 10이 전달된다.
                함수가 두번째 실행될 때 item에 20이 전달된다.
          [{name:"홍길동", email:"hong@gmail.com"}, {name:"김유신", email:"kim@gmail.com"}]
                함수가 첫번째 실행될 때  item에 {name:"홍길동", email:"hong@gmail.com"}이 전달된다.
                함수가 두번째 실행될 때  item에 {name:"김유신", email:"kim@gmail.com"}이 전달된다.

    // 선택자로 선택된 엘리먼트들을 반복처리한다.
    $(선택자).each(function(index, element) {
           $(element).jQuery메소드( );
    });
    * 선택자표현식으로 선택된 엘리먼트들을 하나씩 반복처리할 때 사용한다.
    * 선택자표현식으로 선택된 엘리먼트의 갯수만큼 지정된 함수를 반복수행한다.
    * 함수가 실행될 때 마다 선택된 엘리먼트가 0번째 것부터 순서대로 하나씩 전달된다.
    * 함수의 매개변수
      index : 지금 처리중인 엘리먼트의 인덱스가 전달된다. 0부터 시작되는 숫자 
      element : 지금 처리중인 엘리먼트 객체가 전달된다.

    $(선택자).each(function( ) {
    // 이 함수내의 this에는 함수가 실행될 때 마다 전달되는 엘리먼트객체가 들어있다.
    $(this).jQuery메소드( );
    })


    폼 등록, 취소버튼 

    d-none은 등록버튼 누르기 전에는 화면에 안나오게 한다.

    조작을 해야 하는 대상에 id가 있어야 한다.

    id 명칭 정할 때 강사님의 방식 : 약칭 - 행동 - 대상 (예시 : btn-modify-user)

    form 자체를 submit 할게 아니라서 action과 method를 안적었다.

    ajax를 할 때, 입력된 것을 json으로 형식으로 보낼줄 때는 굳이 name이 없어도 된다.

    button에 아무것도 지정하지 않으면 submit되어버리기 때문에 type="button"을 적어준다.

    폼 취소

    tag하고 tag사이에 있는 값은 text로 지우거나 읽어오고

    입력필드 안에 있는 건 val로 읽어온다.

    JSON.stringify(user)는 자바스크립트 객체나 배열을 json문자열로 바꾸는 것이다. 

    JSON.parse(text)는 json형식을 자바스크립트 배열 또는 객체 형식으로 변경하는 것이다.

     

    json 형식으로 적는게 힘들기 때문에 처음에는 객체로 만들고, 이후에 JSON.stringify(user);로 json 형식으로 바꿔주면 편하다.

    서버로 보내줄 때는 json형식의 텍스트로 바뀐 것을 보내줘야 한다.

     

    폼입력값 등록하기

    $("#btn-submit-user").click(function() {
        // 입력폼의 값을 읽어서 자바스크립트 객체를 생성한다.
        let user = {
            id: $("#user-id").val(),
            password: $("#user-password").val(),
            name: $("#user-name").val(),
            email: $("#user-email").val(),
            tel: $("#user-tel").val()
        };
        // user 변수는 자바스크립트 객체를 저장하고 있다.
        // user -> {id:"hong", password:"zxcv1234", name:"홍길동", email:"hong@gmail.com", tel:"010-2365-8974"}
    
        // JSON.strigify(객체 혹은 배열)을 실행해서 json 형식의 텍스트로 변환한다.
        let jsonText = JSON.stringify(user);
        // jsonText 변수는 텍스트를 저장하고 있다.
        // jsonText -> '{"id":"hong", "password":"zxcv1234", "name":"홍길동", "email":"hong@gmail.com", "tel":"010-2365-8974"}'
    
        $.ajax({
            type: 'POST',
            url: "http://localhost/users",
            data: jsonText,                 // 서버로 보내는 데이터
            contentType: "application/json",// data 항목의 컨텐츠 타입을 지정한다. 요청메세지 바디부에 저장되어 서버로 전달되는 데이터의 타입을 지정한다.
            dataType: "json",				// 서버가 클라이언트로 보내는 응답데이터의 형식을 지정한다. 제이쿼리는 json을 자바스크립트 객체나 배열로 바꿔서 전달해준다.
            success: function(response) {
                let row = `
                    <tr>
                        <td></td>
                        <td>${response.id}</td>
                        <td>${response.name}</td>
                        <td>${response.createdDate}</td>
                        <td><button type="button" class="btn btn-outline-primary btn-sm" data-user-id="${response.id}">상세</button></td>
                    </tr>
                `;				
                $usersTbody.append(row);
    
                generateRowNumbers();
                clearForm();
            }
        });
    });

    id, password, name, email, tel은 UserRegisterForm의 변수명과 같아야 한다.


    jQuery ajax 요청 예시

     

    let obj = {id:"hong", password:"zxcv1234", name:"홍길동", email:"hong@gmail.com", tel:"010-2365-8974"};
    let jsonText = JSON.stringify(obj);

    $.ajax({
    type: "POST",
    data: obj,
    //contentType: 'application/x-www-form-urlencoded',
    dataType: "json",
    success: function(response) {

    }
    });

    요청메세지
    헤더부
    POST http://localhost/users
    contentType='application/x-www-form-urlencoded'
    바디부
    id=hong&password=zxcv1234&name=홍길동
    &email=hong@gmail.com&tel=010-2365-8974


    @PostMapping("/users")
    @ResponseBody
    public User saveUser(UserRegisterForm form) {   // 스프링이 UserRegisterForm객체 안의 변수명을 조사해서 getParameter로 변수명에 해당하는 값을 바디부에서 찾아 담는다. 
    }


    -------------------------------------------------------------------------------------------------------------------------------------------------------

     

    $.ajax({
    type: "POST",
    data: jsonText,
    contentType: 'application/json',
    dataType: "json",
    success: function(response) {

    }
    });

    요청메세지
    헤더부
    POST http://localhost/users
    contentType='application/json'
    바디부
    '{"id":"hong", "password":"zxcv1234", "name":"홍길동", "email":"hong@gmail.com", "tel":"010-2365-8974"}'

     

    // json형식으로 전해줬기 때문에 받는 방식이 달라진다.
    @PostMapping("/users")
    @ResponseBody
    public User saveUser(@RequestBody UserRegisterForm form) {   // Mapping dataBinder가 UserRegisterForm안에 바디부의 텍스트를 그대로 넣어준다.

    }

    반드시, 프런트엔드 어플리케이션과 Spring-Boot rest api를 따로 만들 필요없이 아래 그림처럼 작동시켜도 된다.

    하지만, react, vue.js 등의 별도의 기술을 사용한다면, 별도로 만드는게 좋다. 

    react, vue에서 자체적으로 내장되어 있는 웹서버를 제공하기 때문이다. 

     

    댓글

Designed by Tistory.