๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๊ฐœ๋ฐœ/Java

[Spring] ์Šคํ”„๋ง AJAX ์—ฌ๋Ÿฌ์œ ํ˜• ์‚ฌ์šฉ ์˜ˆ์‹œ :: ๋งˆ์ด์ž๋ชฝ

by ๐ŸŒปโ™š 2018. 9. 6.

AJAX(Asynchronous JavaScript and XML)์€ ์—ฌ๋Ÿฌ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ๋˜๋Š”๋ฐ... ๋งค๋ฒˆ ์‚ฌ์šฉํ• ๋•Œ๋งˆ๋‹ค ์–ด๋–ป๊ฒŒํ•˜๋Š”์ง€ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์• ๋จน๋Š”๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

๊ทธ๋ž˜์„œ, ์ด ๊ธ€๋งŒ ๋ณด๊ณ  ์™„๋ฒฝํ•˜๊ฒŒ ๋‹ค์‹œ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋„๋ก ์ •๋ฆฌํ•ด๋ณผ๋ ค๊ณ  ํ•œ๋‹ค.

AJAX๋Š” ๋‹จ์ˆœํžˆ ํ…์ŠคํŠธ๊ฐ’๋งŒ ๋„˜๊ธธ์ˆ˜๋„ ์žˆ๊ณ , form์„ ๋„˜๊ธธ์ˆ˜๋„ ์žˆ๊ณ , ํŒŒ์ผ ์—…๋กœ๋“œ์™€ ๊ฐ™์ด ์›น๊ฐœ๋ฐœ์—์„œ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•ด์ฃผ๊ธฐ๋•Œ๋ฌธ์—....

AJAX๋งŒ ์ž˜ ์•Œ์•„๋„ ๊ฐœ๋ฐœํ•˜๋Š”๋ฐ ์‹œ๊ฐ„๋‹จ์ถ•์ด ๋œ๋‹ค.

 

AJAX๋Š” ๋น„๋™๊ธฐ์‹ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋Š” ๊ฑฐ๋ผ๊ณ ํ•œ๋‹ค.

์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด ๊ทธ๋ƒฅ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ƒˆ๋กœ๊ณ ์นจํ•˜์ง€ ์•Š๊ณ ๋„ ๋ฐ์ดํ„ฐ๊ฐ’์„ ๋ณ€๊ฒฝํ• ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

 

๋Œ€ํ‘œ์ ์œผ๋กœ AJAX๊ฐ€ ์‚ฌ์šฉ๋œ ์‚ฌ๋ก€๋Š” ๊ฐ์ข… ํฌํ„ธ์‚ฌ์ดํŠธ์˜ ์ธ๊ธฐ๊ฒ€์ƒ‰์–ด ํ˜น์€ ์—ฐ๊ด€๊ฒ€์ƒ‰์–ด์ด๋‹ค.

๊ทธ๋Ÿผ ์œ ํ˜•๋ณ„๋กœ ํ•˜๋‚˜์”ฉ ์จ๋ณด์ž.

 

AJAX๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ Jamong DTO ํด๋ž˜์Šค

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;
    }
    
}
 

 

 

1. ๊ธฐ๋ณธ 

AJAX์˜ ์ตœ์†Œํ™” ํ˜•ํƒœ์ด๋‹ค.

data๋ฅผ ์ „์†กํ•ด์„œ ํ•„์š”ํ•œ ๋กœ์ง๋“ค์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ฐ’์„ returnํ•œ๋‹ค.

 

์—ฌ๊ธฐ์„œ @ResponseBody์˜ ์—ญํ• ์„ ์•Œ์•„์•ผํ•˜๋Š”๋ฐ,

@RequestMapping์œผ๋กœ String type์„ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋ฉด, ViewResolver์—์„œ ์ •์˜ํ•œ prefix์™€ suffix๊ฐ€ return๊ฐ’์— ์ถ”๊ฐ€๋˜์–ด view๋กœ ์ด๋™์ด ๋œ๋‹ค.

@ResponseBody๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด view๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ, JSON ํ˜น์€ Object ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.

 

 

 

-Client

    $('#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");
            }
        });
    });
 

 

 

 

-Server

    @RequestMapping(value="/requestObject", method=RequestMethod.POST)
    @ResponseBody
    public String simpleWithObject(Jamong jamong) {
        //ํ•„์š”ํ•œ ๋กœ์ง ์ฒ˜๋ฆฌ
        return jamong.getName() + jamong.getAge();
    }
 

 

 

-View

<body>
    <button id="btn1">simpleAJAX</button>
    <div id="result"></div>
</body>
 

 

 

 

 

 

2. ํผ ํŒŒ๋ผ๋ฏธํ„ฐ ๋„˜๊ธฐ๊ธฐ

ํผ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„˜๊ธฐ๊ธฐ ์œ„ํ•ด serialize() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

ํ•„์š”ํ•œ ๋กœ์ง ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ  ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ @ResponseBody Annotation์„ ์‚ฌ์šฉํ•˜์—ฌ  Objectํ˜•ํƒœ๋กœ ๋„˜๊ธด๋‹ค.

 

 

 

-Client

    $('#btn2').on('click', function(){
        $.ajax({
            url: "serialize",
            type: "POST",
            data: $("#frm").serialize(),
            success: function(data){
                $('#result').text(data);
            },
            error: function(){
                alert("serialize err");
            }
        });
    });
 

 

 

 

-Server

    @RequestMapping(value="/serialize", method=RequestMethod.POST)
    @ResponseBody
    public String serialize(Jamong jamong) {
        //ํ•„์š”ํ•œ ๋กœ์ง ์ฒ˜๋ฆฌ   
        return jamong.getName() + jamong.getAge();
    }
 

 

 

 

-View

<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>
 

 

 

 

 

 

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ํŒŒ์ผ์— ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.5</version>
        </dependency>
 

 

์ฝ”๋“œ๋ฅผ ๋ณด๊ธฐ ์ด์ „์— ์ด๋ฒˆ์—๋Š” @RequestBody์— ๋Œ€ํ•ด์„œ ์•Œ์•„์•ผํ•œ๋‹ค.

ํด๋ผ์ด์–ธํŠธ์ชฝ์—์„œ ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋ฅผ JSON์œผ๋กœ ๋ณด๋‚ด์ฃผ๋ฉด, ์„œ๋ฒ„์ชฝ์—์„œ๋„ JSON์œผ๋กœ ๋ฐ›์•„์ค˜์•ผํ•œ๋‹ค.

JSONํ˜•ํƒœ๋กœ ๋ฐ›๊ฒŒํ•ด์ฃผ๋Š” Annotation์ด @RequestBody์ด๋‹ค.

 

 

 

-Client

    $('#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");
            }
        });
    });
 

 

 

 

-Server

    @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;
    }
 

 

 

 

-View

<body>
    <button id="btn3">stringify</button>
    <div id="result"></div>
</body>
 

 

 

 

4. @RestController

๋‹ค์Œ์€ @Controller๊ฐ€ ์•„๋‹Œ @RestController์—์„œ JSONํƒ€์ž…์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„๊ฑฐ๋‹ค.

@RestController Annotation์„ ์‚ฌ์šฉํ•˜๋ฉด, @ResponseBody Annotation์„ ๋นผ๊ณ  ์‚ฌ์šฉํ•˜๋ฉด๋œ๋‹ค.

@RestController๊ฐ€ ์•Œ์•„์„œ JSONํ˜•ํƒœ๋กœ returnํ•ด์ค€๋‹ค.

 

-Client

    $('#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");
            }
        });
    });
 

 

 

 

-Server

@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;
    }
}
 

 

 

 

-View

<body>
    <button id="btn4">restController</button>
    <div id="result"></div>
</body>
 

 

 

 

 

5. ํŒŒ์ผ ์—…๋กœ๋“œ๊ฐ€ AJAX ์ฒ˜๋ฆฌ

 ์ง€๊ธˆ๊นŒ์ง€ AJAX์˜ ์ •๋ง ๊ธฐ๋ณธ์ ์ธ๊ฑด ๋‹ค ์„ค๋ช…ํ•œ๊ฒƒ๊ฐ™๋‹ค.

๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋งŒ ์ž˜ ๋งž์ถฐ์„œ ๋„˜๊ฒจ์ฃผ๊ณ , DB์™€ ์ ‘์†ํ•˜๋“ , API์—ฐ๋™์„ ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋“ , ์ฒ˜๋ฆฌ๋กœ์ง๋งŒ ์ž˜ ์ฒ˜๋ฆฌํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

์ด์ œ AJAX๋กœ ๋ญ๋“ ์ง€ ๋‹ค ํ•  ์ˆ˜ ์žˆ์„๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์ง€๋งŒ.... ํผ์— input type์ด file๋กœ ๋˜์–ด์žˆ๋Š” ํŒŒ์ผ๋“ค์€ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜์ง€?๋ผ๋Š” ์˜๋ฌธ์ด ์ƒ๊ธธ ๊ฒƒ์ด๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด ์ž˜ ๋”ฐ๋ผํ•˜๋ฉด ๋œ๋‹ค.

ํ•„์ž๋Š” ํŒŒ์ผ ์œ ํšจ์„ฑ๊ฒ€์‚ฌ๋‚˜ ์—…๋กœ๋“œํ•˜๋Š” ์ž‘์—…์€ ํ•˜์ง€์•Š์•˜๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ๋„˜์–ด๊ฐ€๊ณ  ๋ฐ›์•„์ ธ์˜ค๋Š” ๊ฒƒ๋งŒ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ํŒŒ์ผ ์ด๋ฆ„๋งŒ ์ถœ๋ ฅํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

 

 ํŒŒ์ผ์„ ๋ฐ›์•„์ค„ AjaxFile Dto ํด๋ž˜์Šค

public class AjaxFile {
    
    List<MultipartFile> images;
    
    public List<MultipartFile> getImages() {
        return images;
    }
    public void setImages(List<MultipartFile> images) {
        this.images = images;
    }
}
 

 

 

ํŒŒ์ผ ์—…๋กœ๋“œ๋ฅผ ์œ„ํ•ด maven ์ถ”๊ฐ€ pom.xml

        <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>
 

 

 

servlet-context.xml

    <!-- file Upload -->
    <beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- ํŒŒ์ผ ์ตœ๋Œ€ 50MB -->
        <beans:property name="maxUploadSize" value="52428800"/>
    </beans:bean>
 

 

 

-Client

    $('#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");
            }
        });
    });
 

 

 

 

-Server

    @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;
    }
 

 

 

 

 

-View

<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>
 

 

 

 

ํ•„์ž์˜ ์ƒ๊ฐ์œผ๋กœ ์ด์ •๋„๋งŒ ์•Œ๊ณ ์žˆ๋‹ค๋ฉด, Ajax์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ์—†์„๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

AJAX์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•์„ ์•Œ์•„๋ดค๊ณ ,  DB ํ˜น์€ API๋ฅผ ์—ฐ๋™ํ•˜์—ฌ AJAX ์‹ค์ „ํŽธ์„ ์˜ฌ๋ฆด ๊ณ„ํš์ด๋‹ค.

๋;

๋Œ“๊ธ€