Spring boot 빠르게 시작해보자

Spring boot를 이용하여 API 서버를 개발해보자!

start.spring.io 에서 설정해서 시작해도 된다.

maven을 이용하여 시작해보자.
일단 메이븐 프로젝트를 생성한다.
그럼 pom.xml 파일이 있을 것이다.
pom파일에 아래와 같이 추가한다.

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
        <relativePath/>
    </parent>

위의 아이는 버전관리 및 플러그인, 인코딩 자바 버전 등이 설정 되어있다.
참으로 좋은 녀석이다.
다음으론 아래와 같이 dependencies 들을 추가한다.


<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>

첫 번째 있는 spring-boot-starter 에는 스프링 부트의 핵심인?(필자기준 아닐수도 있음) autoconfigure가 포함되어 있다.
그리고 스프링 부트는 기본으로 logback을 사용하고 있다.
그런데 가만보면 이상한점이 있다. 버전을 정보가 없다. 그 이유는 parent에서 관리는 해주기 때문이다.
니가 뭔데 버전을 관리하냐 나는 내가 할거다 하는 사람은 버전을 명시적으로 써주면 된다.

흠. 설정이 끝났다.
메인 클래스 만들자.

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

메인 클래스 작성도 끝났다. 실행시켜보자. 아무 에러가 없다면 준비는 끝났다.
이 클래스에 중요한건 @SpringBootApplication 어노테이션이다.
저 안에는 @Configuration ,@EnableAutoConfiguration,@ComponentScan 애노테이션이 있다.
아주 쓸모있는 아이다.

이제 API를 서버를 만들자.
서버를 띄우기 위해선 아래와 같이 추가를 한다.

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

이놈도 무시무시한놈이다. 내장톰캣을 사용하고 웹에 필요한 라이브러리들을 추가해준다.
다음으론 메인 클래스를 조금 수정하자. 아니 추가하자.

@SpringBootApplication
@RestController
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @RequestMapping("hello")
    public String hello(){
        return "hello world";
    }
}

이제 모든 준비는 끝났다.
메인 클래스를 실행시키자!
서버가 시작되었면 http://localhost:8080/hello로 접속을 해보자
hello world가 웹페이지에 있다면 성공적으로 API서버를 만들었다.

참고 : Starter POMs

rest api 개념 및 설계

REST

  • REST는 웹의 창시자(HTTP) 중의 한 사람인 Roy Fielding의 2000년 논문에 의해서 소개되었다. 현재의 아키텍쳐가 웹의 본래 설계의 우수성을 많이 사용하지 못하고 있다고 판단했기 때문에, 웹의 장점을 최대한 활용할 수 있는 네트워크 기반의 아키텍쳐를 소개했는데 그것이 바로 Representational State transfer (REST)이다.

REST 의 기본

  • rest는 요소로는 크게 리소스, 메서드, 메세지 3가지 요소로 구성된다. 예를 들어 이름이 Wonwoo인 사용자를 생성한다. 라는 호출이 있을 때 사용자는 생성 되는 리소스, 생성한다라는 행위는 메서드 그리고 이름이 Wonwoo인 사용자는 메세지가 된다. 이를 표현해보면
HTTP POST, http://localhost/users/
{
   "users" :{
       "name" : "Wonwoo" 
   }
}

와 같이 표현되며 생성한다는 의미를 갖는 메서드는 POST, 생성하고자 하는 대상이 되는 사용자라는 리소스는 http://localhost/users/라는 형태의 URL로 표현되며, 생성하고자 하는 사용자의 내용은 JSON 문서를 이용한다.

HTTP 메서드

메서드 의미
POST Create
GET Select
PUT Update
DELETE Delete
PATCH Update
  • 각각의 Post, Get, Put, Delete는 각각의 CRUD 메서드와 대응 된다.
  • Patch 라는 메서드는 Put과 동일한 의미이지만 Put은 해당자원을 전체 Update하라는 의미를 지닌 대신 Patch는 일부만 변경하겠다는 의미를 갖고 있다. 최근에는 Put보다 더 의미적으로 적합하다고 평가받고 있다.

REST의 리소스

  • Rest는 리소스 지향 아키텍쳐 스타일이라는 정의 답게 ㅗ든 것을 리소스 즉 명사로 표현을 하며, 각 세부 리소스에는 id를 붙인다. 즉 사용자라는 리소스 타입을 http://localhost/users 라고 정의했다면 Wonwoo라는 id를 갖는 리소스는 http://localhost/users/Wonwoo 라는 형태로 정의한다.
  • 예제로 통해 알아보자
    1. 사용자 생성

    • 다음은 http://localhost/users 라는 리소스로 이름은 wonwoo, 주소는 seongnam 이라는 내용을 이용해서 생성하는 표현이다.
HTTP Post, http://localhost/users
{
  "name" : "wonwoo",
  "address" : "seongnam"
}

2. 사용자 조회
– 다음은 생성된 리소스 중에서 http://localhost/users 라는 사용자 리소스중에, id가 wonwoo인 사용자 정보를 조회해오는 표현이다.

HTTP Get, http://localhost/users

3. 사용자 업데이트
– 다음은 생성된 리소스 중에서 http://localhost/users 라는 사용자 리소스중에 id가 wonwoo인 사용자정보에 대해 주소를 seoul으로 수정하는 표현이다.

HTTP PUT, http://localhost/users/wonwoo
{
  "address":"seoul"
}

4. 사용자 삭제
– 다음은 생성된 리소스 중에서 http://localhost/users 라는 사용자 리소스중에 id가 wonwoo인 사용자 정보를 삭제 하는 표현이다.

HTTP DELETE, http://localhost/users/wonwoo
  • 간단하게 CURD 표현이 끝났다.

REST의 특성

  1. 유니폼 인터페이스(Uniform Interface)
    • REST는 HTTP 표준에만 따른 다면, 어떠한 기술이라던지 사용이 가능한 인터페이스 스타일이다. HTTP + JSON으로 정의를 했다면, 안드로이드건, IOS건, C 기타 다른 언어에 종속 받지 않고 사용할 수 있는 느슨한 결함 형태의 구조다.
  2. 무상태성/스테이트리스(Stateless)
    • REST는 Representational State Transfer의 약어로 상태를 유지하지 않는 특징 중 하나이다. 상태가 있다 없다의 의미는 사용자나 클라이언트의 컨택스트를 서버쪽에 유지 하지 않는다는 의미로 HTTP Session과 같은 상태 정보를 저장하지 않으며 각 API 서버는 들어오는 요청만 메시지로 처리하면 된다.
  3. 캐싱(Cacheable)
    • REST의 큰 특징 중 하나는 기존의 HTTP라는 웹 표준을 그대로 사용하기 때문에 웹에서 사용하는 기존의 인프라를 그대로 활용이 가능하다. HTTP 기반의 로드 밸런서나 SSL은 물론이고 캐싱기능을 적용할 수 있다. 일반적인 서버등의 캐싱하는 것은 용량이나 성능 면에서 많은 장점을 가지고 올 수 있다. 구현은 HTTP 프로토콜 표준에서 사용하는 Last-Modified 태그나 E-TAG를 이용하면 캐싱을 구현 할 수 있다. Client가 HTTP GET을 Last-Modified 값과 함께 보냈을 때, 컨텐츠가 변화가 없으면 Rest 컴포넌트는 304 Not modified를 리턴하면 Client는 자체 캐쉬에 저장된 값을 사용하면 된다.
  4. 자체 표현 구조(Self-descriptiveness)
    • REST API 자체가 매우 쉬워서 API 메시지 자체만 보고도 API를 이해할 수 있는 Self-descriptiveness 구조를 갖는다. 리소스와 메서드를 이용해서 어떤 메서드에 무슨 행위를 하는지를 알 수 있으며, 또한 메시지 포맷 역시 JSON을 이용해서 직관적으로 이해가 가능한 구조이다.
  5. 클라이언트 서버 구조(Client-Server 구조)
    • 근래에 들면서 재 정립되고 있는 특징 중의 하나는 REST가 클라이언트 서버 구조라는 것이다. REST 서버는 API를 제공하고 제공된 API를 이용해서 비즈니스 로직 처리 및 저장을 책임진다. 클라이언트 경우 사용자 인증이나 컨텍스트(세션, 로그인정보) 등을 직접 관리하고 책임지는 구조로 역할이 나뉘어 지고 있다. 이렇게 역할이 각각 확실하게 구분되면서, 개발관점에서 클라이언트와 서버에서 개발해야 할 내용들이 명확하게 되고 의존성도 줄어든다.
  6. 계층형 구조(Layered System)
    • 계층형 아키텍쳐 구조 역시 근래에 들어서 주목받기 시작하는 구조 인데 클라이언트 입장에서는 REST API만 호출 한다. 그러나 서버는 다중 계층으로 구성될 수 있다. 순수 비즈니스 로직을 수행하는 API 서버와 그 앞 단에 사용자인증(Authentication), 암호화(SSL), 로드밸런싱등을 하는 계층을 추가해서 구조상의 유연성을 둘 수 있는데 이는 근래에 들어서 마이크로 서비스 아키텍쳐의 api gate나 간단한 기능의 경우는 HAProxy나 Apache와 같은 Reverse Proxy를 이용해서 구현하는 경우도 있다.

REST 안티 패턴

1. GET/POST를 이용한 터널링
– http://localhost/users?method=update&id=wonwoo 이 경우가 전형적인 GET을 이용한 터널링이다. 메서드의 실제 동작은 리소스를 업데이트 하는 내용인데, HTTP PUT이나 PATCH를 사용하지 않고 쿼리파라미터로 method=update라고 넘겨서 수정 메서드임을 명시했다. 또 한 Insert성 오퍼레이션이 아닌데도 불구하고 JSON 바디에 오퍼레이션명을 넘기는 형태인데 예를 들어 특정 사용자 정보를 가지고 오는 API를 아래와 같이 POST를 이용해서 만든 경우이다.

HTTP POST, http://localhost/users
{
  "getuser": {
     "id" : "wonwoo"
  }
}

2. HTTP Response code를 사용하지 않음
– 다음으로 많이 하는 디자인 중 하나가 Http Response code를 충실하게 따르지 않고 성공은 200, 실패는 500과 같이 1~2개의 Http Response code만 사용하는 경우이다. 심한 경우에는 에러도 Http Response code 200으로 정의한후 별도의 에러 메시지를 200 Response code와 함께 보내는 경우이다.

출처: 조대협님 블로그(http://bcho.tistory.com/m/post/953)

Accept와 Content-type

Accept

  • 클라이언트가 서버에 어떤 형식(MediaType)으로 달라는 요청을 할 수 있는데 이게 Accpet 헤더를 뜻하는거다.

Content-Type

  • 클라이언트가 request에 실어 보내는 데이타(body)의 형식(MediaType)를 표현하는거다.