Dev.GA

[REST] RESTful 웹서비스 만들기 본문

Dev.Back-End/RESTful

[REST] RESTful 웹서비스 만들기

Dev.GA 2018. 5. 11. 16:44

[REST] RESTful 웹서비스 만들기



지난번 REST의 개념에 대해 알아본데 이어, 이번시간에는 RESTful 웹 프로젝트를 만들어보겠다.


RESTful 웹서비스는 Spring Boot를 사용해서 프로젝트를 만들것이며, 간단하게 REST에서 사용하는


HTTP에서 제공하는 4가지 메소드를 사용해 RESTful 웹서비스를 만들어보겠다.


Spring Boot 프로젝트가 생성되어 있다는 가정하에 포스팅을 시작할 것이며, 혹시 Spring Boot 프로젝트를 처음부터


생성해야한다면, 아래의 주소를 참고하길 바란다.


2018/04/24 - [Dev.Back-End/Spring Boot] - [SpringBoot] 스프링부트(SpringBoot) 프로젝트 생성하기(with gradle)


생성해야한다면, 아래의 주소를 참고하길 바란다.




1. 프로젝트 구조 확인


먼저 앞의 과정이 생략되어 있기에 프로젝트 구조먼저 확인하고 가자.





위와같이 "com.rest" 패키지 하위에 시작 main함수가 있는 RestApplication을 작성하였다.


간단히 선수정보를 이용해 Rest 웹서비스를 만들어 보기위해 Player(선수)의 패키지를 만들었다.


위와 같은 패키지 구조에서 어플리케이션을 실행시키면 제대로 동작하지 않는다. 이유는 시작 main함수가 있는 RestApplication.java가 동일한 패키지 상에 있는 컴포넌트들만 스캔하기 때문에 다른 패키지에 있는 클래스들을 스캔할 수 있도록 설정해야한다.


일반적인 Spring MVC 프로젝트 시, base-package를 설정하는 부분과 동일하게 생각하면 된다.


RestApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.rest.main;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
 
@SpringBootApplication
@ComponentScan(basePackages="com.rest")
public class RestApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(RestApplication.class, args);
    }
 
}
cs


8번째라인)처럼 @ComponentScan이라는 어노테이션을 이용해 basePackage를 지정해주면 된다.




2. 도메인 작성


기본적인 정보들로 Player(선수) 도메인을 작성한다.


Player.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.rest.player.service;
 
import java.util.Date;
 
public class Player {
 
    private long id;
    private String name;
    private String team;
    
    public Player() {
        
    }
    
    public Player(String name, String team) {
        this.id = (new Date()).getTime();
        this.name = name;
        this.team = team;
    }
 
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getTeam() {
        return team;
    }
 
    public void setTeam(String team) {
        this.team = team;
    }
    
}
 
cs



데이터베이스에서 데이터를 가져오는것이 아니라 먼저 Rest기능에 초점을 맞추고 있어,

직접 어플리케이션 상에서 데이터를 생성하도록 HashMap을 이용할 것이다.


다음과 같이 RestApplication.java에 HashMap을 생성해 데이터를 담아보자.


RestApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.rest.main;
 
import java.util.HashMap;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
 
import com.rest.player.service.Player;
 
@SpringBootApplication
@ComponentScan(basePackages="com.rest")
public class RestApplication {
    
    public static HashMap<Long, Player> PlayerHm;
 
    public static void main(String[] args) {
        PlayerHm = new HashMap<Long, Player>();
        
        Player player_one = new Player("Cristiano Ronaldo""Real Madrid");
        PlayerHm.put(new Long(player_one.getId()), player_one);
        
        SpringApplication.run(RestApplication.class, args);
        
        Player player_two = new Player("Lionel Messi""FC Barcelona");
        PlayerHm.put(new Long(player_two.getId()), player_two);
    }
 
}
cs




3. RestController 작성과 데이터 GET하기


RestApplication.java에 HashMap을 생성해 데이터를 담는 코드를 작성해 어플리케이션 실행시 자동으로 데이터가 생성되도록 하였다.


이제 RestController에서 REST의 HTTP메소드를 사용해보겠다.


일반적인 GET부터 작성하여 정상적으로 프로젝트가 생성되었는지 확인해보자.


PlayerController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.rest.player.controller;
 
import java.util.HashMap;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import com.rest.main.RestApplication;
import com.rest.player.service.Player;
 
@RestController
@RequestMapping(value="/player")
public class PlayerController {
    
    @RequestMapping(value="/", method=RequestMethod.GET)
    public HashMap<Long, Player> getAllPlayers(){
        return RestApplication.PlayerHm;
    }
 
}
 
cs


상단에 @RestController 어노테이션으로 Rest서비스를 이용할 수 있게 하며, @RequestMapping을 이용해 이 컨트롤러에 접근할 수 있는 url을 지정해주었다.


이제 어플리케이션을 실행하여 데이터를 확인해보자.




크롬에서 제공하는 Rest API 테스트 툴을 사용했다.


어플리케이션을 실행하면서 생성한 2개의 데이터 조회를 성공적으로 수행하였다.



이제 나머지 PUT, DELETE, POST 메소드를 사용해보도록 하겠다.




4. POST, PUT, DELETE 작성


POST, PUT, DELETE 작성에 앞서 위의 GET요청은 모든 선수목록(AllPlayers)를 가져오는 방법이었기 때문에 

특정 id값으로 원하는 데이터만 GET하는 방법을 먼저 진행하겠다.


특정 id값으로 GET요청을 하게되면 나머지 POST, PUT, DELETE도 자연스럽게 완성할 수 있다.


1) GET(특정 id값으로)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    /**
     * GET use id
     */
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public Player getPlayers(@PathVariable("id"final String id) throws Exception{
        
        Player player;
        
        if(RestApplication.PlayerHm.containsKey(id)) {
            player = RestApplication.PlayerHm.get(id);
        } else {
            throw new Exception("Player " + id + "does not exists");
        }
        
        return player;
    }
cs


요청 url뒤로 원하는 데이터의 id값을 입력(ex. localhost:8080/player/id값) 하여 GET요청을 보내기때문에 


@PathVariable 어노테이션을 사용하여 위의 id값을 받는다.


저장한 HashMap에서 위의 id값으로 찾아 id값에 해당하는 데이터가 있는지 조회한 후 해당 데이터를 불러와 return시켜준다.


GET http://localhost:8080/player/1





2) POST


GET요청을 성공적으로 작성했기때문에 POST도 쉽게 진행할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    /**
     * POST
     */
    @RequestMapping(value="/", method=RequestMethod.POST)
    public void addPlayer(@RequestBody final Player player) throws Exception{
        
        if(player==null) {
            throw new Exception("You did not send data");
        } else {
            if(RestApplication.PlayerHm.containsKey(player.getId())) {
                throw new Exception("Player " + player.getId() + "does exists");
            } else {
                Player new_player = new Player(player.getId(), player.getName(), player.getTeam());
                RestApplication.PlayerHm.put(new String(new_player.getId()), new_player);                
            }
        }
        
    }
cs


POST는 Front-end단에서 데이터를 넘겨줄텐데 정상적인 데이터를 넘겨받을시 중복되는 데이터가 있는지 확인 후 데이터를 추가하면 된다.


POST http://localhost:8080/player/




JSON(application/json) 형태로 데이터를 POST요청하였다. 이런 형태로 Front-end측에서 데이터를 보내줄 것이기 때문이다.




다시 GET요청으로 확인해보면 추가한 데이터가 정상적으로 추가되었다.


위의 POST에서 예외처리 했던부분을 테스트해보자. 동일한 데이터를 다시 입력하고 POST요청을 해보겠다.



하단의 결과 message를 보면 예외처리대로 이미 존재한다고 메세지를 출력하고 있다.




3) PUT


PUT요청은 Update 행위임으로 특정 id값의 데이터를 udpate시켜 보겠다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    /**
     * PUT
     */
    @RequestMapping(value="/{id}", method=RequestMethod.PUT)
    public Player udpatePlayer(@PathVariable("id"final String id, @RequestBody final Player player) throws Exception{
        
        if(RestApplication.PlayerHm.containsKey(id)) {
            player.setTeam("Real Madrid");
            RestApplication.PlayerHm.put(new String(id), player);
        } else {
            throw new Exception("Player " + id +" does not exists");
        }
        
        return player;
    }
cs


특정 id값을 받아 해당 id의 team을 변경시켜 주었다.


PUT http://localhost:8080/player/3





4) DELETE


DELETE는 PUT요청과 비슷하게 진행하면 된다. 해당 id값을 받아와 해당 데이터를 HashMap에서 제거해주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
    /**
     * DELETE
     */
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public HashMap<String, Player> deletePlayer(@PathVariable("id"final String id, @RequestBody final Player player) throws Exception{
        
        if(RestApplication.PlayerHm.containsKey(id)) {            
            RestApplication.PlayerHm.remove(new String(id));
        } else {
            throw new Exception("Player " + player.getId()+" does not exists");
        }
        
        return RestApplication.PlayerHm;
    }
cs



DELETE http://localhost:8080/player/2


결과를 확인하자.



2번 id값을 삭제하여 1,3번만 남은것을 볼 수 있다.



5. 완성코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.rest.player.controller;
 
import java.util.HashMap;
 
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import com.rest.main.RestApplication;
import com.rest.player.service.Player;
 
@RestController
@RequestMapping(value="/player")
public class PlayerController {
    
    /**
     * GET ALL
     * @return
     */
    @RequestMapping(value="/", method=RequestMethod.GET)
    public HashMap<String, Player> getAllPlayers(){
        return RestApplication.PlayerHm;
    }
    
    /**
     * GET use id
     */
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public Player getPlayers(@PathVariable("id"final String id) throws Exception{
        
        Player player;
        
        if(RestApplication.PlayerHm.containsKey(id)) {
            player = RestApplication.PlayerHm.get(id);
        } else {
            throw new Exception("Player " + id + "does not exists");
        }
        
        return player;
    }    
    
    /**
     * POST
     */
    @RequestMapping(value="/", method=RequestMethod.POST)
    public HashMap<String, Player> addPlayer(@RequestBody final Player player) throws Exception{
        
        if(player==null) {
            throw new Exception("You did not send data");
        } else {
            if(RestApplication.PlayerHm.containsKey(player.getId())) {
                throw new Exception("Player " + player.getId() + "does exists");
            } else {
                Player new_player = new Player(player.getId(), player.getName(), player.getTeam());
                RestApplication.PlayerHm.put(new String(new_player.getId()), new_player);                
            }
        }
        
        return RestApplication.PlayerHm;
    }
    
    /**
     * PUT
     */
    @RequestMapping(value="/{id}", method=RequestMethod.PUT)
    public Player udpatePlayer(@PathVariable("id"final String id, @RequestBody final Player player) throws Exception{
        
        if(RestApplication.PlayerHm.containsKey(id)) {
            player.setTeam("Real Madrid");
            RestApplication.PlayerHm.put(new String(id), player);
        } else {
            throw new Exception("Player " + player.getId()+" does not exists");
        }
        
        return player;
    }
    
    /**
     * DELETE
     */
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public HashMap<String, Player> deletePlayer(@PathVariable("id"final String id, @RequestBody final Player player) throws Exception{
        
        if(RestApplication.PlayerHm.containsKey(id)) {            
            RestApplication.PlayerHm.remove(new String(id));
        } else {
            throw new Exception("Player " + player.getId()+" does not exists");
        }
        
        return RestApplication.PlayerHm;
    }
 
}
 
cs



이렇게 RESTful 웹서비스를 만들어 보았다.


최근에는 Front-end 기술을 사용해 Back단에서는 Java로 RESTful 서비스만 제공하고 따로 view단은 만들지 않는 방식을 많이 쓴다고 한다.


RESTful 서비스를 활용해 ReactJS 등과 같은 자바스크립트로 view단을 만들어 프로젝트를 진행하도록 할 것이다.

'Dev.Back-End > RESTful' 카테고리의 다른 글

[REST] RESTful 파헤치기  (0) 2018.04.13
[REST] REST란 무엇인가? REST맛보기  (0) 2018.04.04
Comments