[Spring] REST API

3 minute read

REST

REST(Representational State Transfer)란 자원(URI)과 행위(Http Method)를 기반으로 데이터를 주고 받는 방법을 말한다. REST 원리를 따르는 시스템은 RESTful이란 용어로 지칭된다.

CRUD Operation

행위(Http Method) 설명
POST Create
GET Read
PUT Update
DELETE Delete
HEAD Header 정보조회

장점

  • HTTP 프로토콜 인프라를 그대로 사용 가능
  • HTTP 프로토콜이 사용가능한 모든 플랫폼에서 사용이 가능 - 다양한 브라우저와 모바일 디바이스에서 통신

단점

  • 명확한 표준이 존재하지 않는다.
  • 사용할 수 있는 메서드가 4가지 밖에 없다.
  • 구현 브라우저는 PUT, DELETE를 사용할 수 없다.

Spring REST API

@RestController

JSP와 같은 view를 반환하는 것이 아니고 JSON, XML같은 데이터를 브라우저로 전송하는 컨트롤러

@RestController
@RequestMapping("/test/*")
public Class TestController{
    // 문자열 전달
    @RequestMapping("/hello")
    public String hello(){
        return "hello REST!";
    }
    // VO객체를 JSON으로 전달
    @RequestMappring("/member")
    public MemberVO member(){
        MemberVO vo = new MemberVO();
        vo.setID("SYKIM");
        vo.setPwd("1234");
        return vo;
    }
    ...
}

VO 객체는 물론 Collection(Map, List 등) 객체도 JSON으로 전달된다.

@PathVariable

브라우저에서 요청 URI로 전달된 매개변수를 가져올 수 있다.

@RequestMapping(value = "/notice/{num}", method = RequestMethod.GET)
public int notice(@PathVariable("num") int num) throws Exception{
    return num;
}

브라우저에서 요청 시, {num}부분의 값이 @PathVariable로 지정된다.

@RequestBody

REST는 Ajax와 연동해서 자주 사용되는데, 브라우저에서 JSON 데이터를 컨트롤러로 전송 시, @RequestBody를 사용하면 컨트롤러에서 전송받은 JSON을 객체로 변환하는 기능을 구현한다.

@RequestMapping(value= "/info", method= RequestMethod.POST )
public void modify(@RequestBody MemberVO vo){
    // JSON으로 전송된 데이터를 MemberVO 객체의 속성에 자동 설정
    logger.info(vo.toString());
}
$(function(){
    $('#checkJson').click(function(){
        var member = { id: 'hong', name: '홍길동', pwd: '1234'};
        $.ajax({
            type: 'post',
            url: '${contextPath}/test/info',
            contentType: 'application/json',
            data: JSON.stringfy(member),    // 회원정보 객체를 JSON 문자열로 변환
            ...
        });
    });
});

@ResponseBody

RestController로 지정하지 않았어도 ResponseBody가 적용된 메서드는 JSP가 아닌 JSON으로 결과를 전송한다.

@Controller
public class Controller{
    @RequestMapping("/res1");
    @ResponseBody
    public Map<String, Object> res1(){
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id","hong");
        map.put("name","홍길동");
        // Map 데이터를 브라우저로 전송
        return map;
    }
}

@ResponseEntity

예외에 대한 세밀한 제어가 필요한 경우 ResponseEntity 클래스를 사용하여 HTTP 상태코드를 설정하여 전송하도록 한다.

...
    public ResponseEntity<List<MemberVO>> listMembers(){
        List<MemberVO> list = new ArrayList<MemberVO>();
        ...
        return new ResponseEntity(list, HttpStatus.INTERNAL_SERVER_ERROR);  // 오류코드 500 응답
    }
  • ResponseEntity에서 설정할 수 있는 HTTP 상태코드 (일부)
코드 상수
200 OK
201 CREATED
400 BAD_REQUEST
403 FORBIDDEN
404 NOT_FOUND
500 INTERAL_SERVER_ERROR

HttpHeaders 클래스를 이용하여 ResponseEntity 전송

...
    public ResponseEntity res3(){
        HttpHeaders responseHeaders = new HttpHeaders();
        // 전송할 데이터의 종류와 인코딩 설정
        responseHeaders.add("Content-Type","text/html;charset=utf-8");
        String message = "<script>";
        message += "alert('새 회원을 등록합니다.')";
        message += "location.href='/...'; ";
        message += "</script>";
        // ResponseEntity를 이용해 HTML 형식으로 전송
        return new ResponseEntity(message, responseHeaders, HttpStatus.CREATED);
    }

위 메서드가 매핑된 주소로 접속하면, message에 입력한 자바스크립트 경고메시지가 표시된다.

ResponseEntity를 사용하면, JSON 뿐만 아니라 HTML 또는 자바스크립트를 브라우저로 전송할 수 있어 결과메시지 또는 오류메시지를 전송할 때 편리하다.

REST방식으로 URI 표현하기

REST방식에서는 조회 뿐만 아니라 추가, 수정, 삭제 (CRUD) 기능을 수행할 때 포스팅 상위에 작성한 것처럼 HTTP 메서드를 이용하여 처리해야한다.

REST 요청 URI의 예

/작업명/기본키 + 메서드 + 데이터

  • 작업명 : 요청 작업의 종류 /boards
  • 기본키 : 작업 대상의 기본 키 /133
  • 메서드 : 수행 기능
  • 데이터 : 기능 수행 시 필요한 JSON 데이터
메서드 URI 설명
POST /boards+데이터 새 글 등록
GET /boards/133 133번 글 조회
PUT /boards/133+데이터 133번 글 수정
DELETE /boards/133 133번 글 삭제

예제 코드

@RestController
@RequestMapping("/boards")
public class BoardController{
    ...
    // articleNO에 해당하는 글 조회 - GET
    @RequestMapping(value = "/{articleNO}", method = RequestMethod.GET)
    public ResponseEntity<ArticleVO> findArticle(@PathVarialbe("articleNO") Integer articleNO){
        ...
        return new ResponseEntity<ArticleVO>(vo, HttpStatus.OK);
    }
    
    // JSON으로 전달된 객체를 새 글로 추가 - POST
    @RequestMapping(value = "", method = RequestMethod.POST)
    public ResponseEntity<String> addArticle(@RequestBody ArticleVO articleVO){
        ResponseEntity<String> resEntity = null;
        try{
            resEntity = new ResponseEntity("ADD_SUCCEDED",HttpStatus.OK);
        }catch(Exception e){
            resEntity = new ResponseEntity(e.getMessage(),HttpStatus.BAD_REQUEST);
        }
        return resEntity;
    }

    // articleNo에 해당하는 글을 JSON으로 전달된 객체로 수정 - PUT
     @RequestMapping(value = "/{articleNO}", method = RequestMethod.PUT)
     public ResponseEntity<String> modArticle(@PathVarialbe("articleNO") Integer articleNO, @RequestBody ArticleVO articleVO){
         ...
     }

    // articleNo에 해당하는 글을 삭제 - DELETE
     @RequestMapping(value = "/{articleNO}", method = RequestMethod.DELETE)
     public ResponseEntity<String> removeArticle(@PathVarialbe("articleNO") Integer articleNO){
         ...
     }
}
<script>
...
    $.ajax({
        // 등록 시 - POST방식, /board+데이터
        type: 'POST',
        url: '${contextPath}/boards'
        contentType: 'application/json',
        data: JSON.stringfy(article),
        ...
    });
</script>

수정과 삭제 등은 type와 url를 바꾸면 된다 😀

Tags:

Categories:

Updated:

Comments