티스토리 뷰

AJAX(Asynchronous JavaScript and XML)은 여러 상황에서 사용되는데... 매번 사용할때마다 어떻게하는지 검색하고 애먹는경우가 많다.

그래서, 이 글만 보고 완벽하게 다시 사용할수 있도록 정리해볼려고 한다.

AJAX는 단순히 텍스트값만 넘길수도 있고, form을 넘길수도 있고, 파일 업로드와 같이 웹개발에서 중요한 역할을 해주기때문에....

AJAX만 잘 알아도 개발하는데 시간단축이 된다.

 

AJAX는 비동기식 방법으로 데이터에 접근하는 거라고한다.

쉽게 말하면 그냥 브라우저에서 새로고침하지 않고도 데이터값을 변경할수 있는 것이다.

 

대표적으로 AJAX가 사용된 사례는 각종 포털사이트의 인기검색어 혹은 연관검색어이다.

그럼 유형별로 하나씩 써보자.

 

AJAX데이터를 담을 Jamong DTO 클래스

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public class Jamong {

    String name;

    int age;

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    

}

cs

 

 

1. 기본 

AJAX의 최소화 형태이다.

data를 전송해서 필요한 로직들을 처리하고 값을 return한다.

 

여기서 @ResponseBody의 역할을 알아야하는데,

@RequestMapping으로 String type을 반환해주면, ViewResolver에서 정의한 prefix와 suffix가 return값에 추가되어 view로 이동이 된다.

@ResponseBody를 사용해주면 view를 생성해주는것이 아니라, JSON 혹은 Object 형태로 데이터를 넘겨준다.

 

 

 

-Client

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

    $('#btn1').on('click'function(){

        var form = {

                name"jamong",

                age: 23

        }

        $.ajax({

            url: "requestObject",

            type: "POST",

            data: form,

            success: function(data){

                $('#result').text(data);

            },

            error: function(){

                alert("simpleWithObject err");

            }

        });

    });

cs

 

 

 

-Server

1

2

3

4

5

6

    @RequestMapping(value="/requestObject", method=RequestMethod.POST)

    @ResponseBody

    public String simpleWithObject(Jamong jamong) {

        //필요한 로직 처리

        return jamong.getName() + jamong.getAge();

    }

cs

 

 

-View

1

2

3

4

<body>

    <button id="btn1">simpleAJAX</button>

    <div id="result"></div>

</body>

cs

 

 

 

 

2. 폼 파라미터 넘기기

폼의 파라미터를 넘기기 위해 serialize() 함수를 사용한다.

필요한 로직 처리를 하고 마찬가지로 @ResponseBody Annotation을 사용하여  Object형태로 넘긴다.

 

 

 

-Client

1

2

3

4

5

6

7

8

9

10

11

12

13

    $('#btn2').on('click'function(){

        $.ajax({

            url: "serialize",

            type: "POST",

            data: $("#frm").serialize(),

            success: function(data){

                $('#result').text(data);

            },

            error: function(){

                alert("serialize err");

            }

        });

    });

cs

 

 

 

-Server

1

2

3

4

5

6

    @RequestMapping(value="/serialize", method=RequestMethod.POST)

    @ResponseBody

    public String serialize(Jamong jamong) {

        //필요한 로직 처리   

        return jamong.getName() + jamong.getAge();

    }

cs

 

 

 

-View

1

2

3

4

5

6

7

8

<body>

<form id="frm">

    name : <input type="text" name="name" id="name"><br>

    age : <input type="text" name="age" id="age">

</form>

    <button id="btn2">serialize</button>

    <div id="result"></div>

</body>

cs

 

 

 

 

 

3. JSON.stringify()

AJAX에는 dataType이라는 옵션이 있다. 설정을 안해주면 MIME타입에 의해 자동으로 설정이된다.

그런데 나는 JSON형태로 보내고싶다.

AJAX를 사용하는 예시를 보면 JSON.stringify() 함수를 많이 사용한다.

이 함수는 JSON타입을 String 객체로 변환시켜주는 역할을 한다.

서버쪽으로 데이터를 넘길때,  String객체로 변환시켜주기 않으면 URL의 get 파라미터 형식(?a=1&b=2)처럼 넘겨버린다.

 

자... 근데... stringify함수를 그냥 사용하게되면 415에러가뜬다.

이부분에서 필자는 굉장히 삽질을 했는데.... jackson 라이브러리를 추가해줘야한다.

서버쪽으로 데이터를 넘기면서 무슨 변환작업을 해주는것 같은데, 추가안해주면 415에러가 뜬다.

 pom.xml파일에 추가해준다.

1

2

3

4

5

        <dependency>

            <groupId>com.fasterxml.jackson.core</groupId>

            <artifactId>jackson-databind</artifactId>

            <version>2.9.5</version>

        </dependency>

cs

 

코드를 보기 이전에 이번에는 @RequestBody에 대해서 알아야한다.

클라이언트쪽에서 데이터 형태를 JSON으로 보내주면, 서버쪽에서도 JSON으로 받아줘야한다.

JSON형태로 받게해주는 Annotation이 @RequestBody이다.

 

 

 

-Client

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

    $('#btn3').on('click'function(){

        var form = {

                name"jamong",

                age: 23

        }

        $.ajax({

            url: " stringify",

            type: "POST",

            data: JSON.stringify(form),

            contentType: "application/json; charset=utf-8;",

            dataType: "json",

            success: function(data){

                var txt = data.name + data.age;

                $('#result').text(txt);

            },

            error: function(){

                alert("stringify err");

            }

        });

    });

cs

 

 

 

-Server

1

2

3

4

5

6

7

8

    @RequestMapping(value="/stringify", method=RequestMethod.POST)

    @ResponseBody

    public Object stringify(@RequestBody Jamong jamong) {

        HashMap<String, Object> map = new HashMap<String, Object>();

        map.put("name", jamong.getName());

        map.put("age", jamong.getAge());

        return map;

    }

cs

 

 

 

-View

1

2

3

4

<body>

    <button id="btn3">stringify</button>

    <div id="result"></div>

</body>

cs

 

 

 

4. @RestController

다음은 @Controller가 아닌 @RestController에서 JSON타입으로 데이터를 주고받을거다.

@RestController Annotation을 사용하면, @ResponseBody Annotation을 빼고 사용하면된다.

@RestController가 알아서 JSON형태로 return해준다.

 

-Client

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

    $('#btn4').on('click'function(){

        var form = {

                name"jamong",

                age: 23

        }

        $.ajax({

            url: " restController",

            type: "POST",

            data: JSON.stringify(form),

            contentType: "application/json; charset=utf-8;",

            dataType: "json",

            success: function(data){

                for(var i=0; i<data.length; i++){

                    $('#result').append(data[i] + "<br>");

                }

            },

            error: function(){

                alert("restController err");

            }

        });

    });

cs

 

 

 

-Server

1

2

3

4

5

6

7

8

9

10

11

@RestController

public class AjaxRestController {

    @PostMapping("/restController")

    public Object restController(@RequestBody Jamong jamong) {

        ArrayList<String> arrList = new ArrayList<String>();

        for(int i=0; i<5; i++) {

            arrList.add(jamong.getName() + i);

        }

        return arrList;

    }

}

cs

 

 

 

-View

1

2

3

4

<body>

    <button id="btn4">restController</button>

    <div id="result"></div>

</body>

cs

 

 

 

 

5. 파일 업로드가 AJAX 처리

 지금까지 AJAX의 정말 기본적인건 다 설명한것같다.

데이터 형태만 잘 맞춰서 넘겨주고, DB와 접속하든, API연동을 하여 데이터를 받아오든, 처리로직만 잘 처리해주면 된다.

이제 AJAX로 뭐든지 다 할 수 있을것 같다는 생각이 들지만.... 폼에 input type이 file로 되어있는 파일들은 어떻게 처리하지?라는 의문이 생길 것이다.

아래와 같이 잘 따라하면 된다.

필자는 파일 유효성검사나 업로드하는 작업은 하지않았다. 데이터가 넘어가고 받아져오는 것만 확인하기 위해 파일 이름만 출력하도록 코드를 작성했다.

 

 파일을 받아줄 AjaxFile Dto 클래스

1

2

3

4

5

6

7

8

9

10

11

public class AjaxFile {

    

    List<MultipartFile> images;

    

    public List<MultipartFile> getImages() {

        return images;

    }

    public void setImages(List<MultipartFile> images) {

        this.images = images;

    }

}

cs

 

 

파일 업로드를 위해 maven 추가 pom.xml

1

2

3

4

5

6

7

8

9

10

11

        <dependency>

            <groupId>commons-fileupload</groupId>

            <artifactId>commons-fileupload</artifactId>

            <version>1.3.2</version>

        </dependency>

 

        <dependency>

            <groupId>commons-io</groupId>

            <artifactId>commons-io</artifactId>

            <version>2.5</version>

        </dependency>

cs

 

 

servlet-context.xml

1

2

3

4

5

    <!-- file Upload -->

    <beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

        <!-- 파일 최대 50MB -->

        <beans:property name="maxUploadSize" value="52428800"/>

    </beans:bean>

cs

 

 

-Client

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

    $('#btn5').on('click'function(){

        var form = new FormData($('#frm')[0]);

        $.ajax({

            url: "file",

            type: "POST",

            data: form,

            contentType: false,

            processData: false,

            success: function(data){

                for(var i=0; i<data.length; i++){

                    $('#result').append(data[i] + '<br>')

                }

            },

            error: function(){

                alert("file err");

            }

        });

    });

cs

 

 

 

-Server

1

2

3

4

5

6

7

8

9

10

    @RequestMapping(value="/file", method=RequestMethod.POST)

    @ResponseBody

    public Object file(AjaxFile file) {

        List<MultipartFile> list = file.getImages();

        ArrayList<String> fileNameList = new ArrayList<String>();

        for(MultipartFile mf : list) {

            fileNameList.add(mf.getOriginalFilename());

        }

        return fileNameList;

    }

cs

 

 

 

 

-View

1

2

3

4

5

6

7

<body>

<form id="frm" enctype="multipart/form-data">

    <input multiple="multiple" type="file" id="images" name="images">

</form>

    <button id="btn5">file</button>

    <div id="result"></div>

</body>

cs

 

 

 

json으로 받아온 데이터는

JSON.stringify() 으로 확인할 수 있다.

 

console.log( "json : " + JSON.stringify(data)  );

alert( JSON.stringify(data) );

 

받아온 json을 사용하실 때는

data[0]["name"]; //첫번째 배열(로우)에 key(컬럼) 이름이 name인 경우

data[1]["name"]; //두번째 배열(로우)에 key(컬럼) 이름이 name인 경우

 

이런식으로 하나씩 가져올 수 있다.