:: Dev/Spring

[Sp-re-ing] 02 - JSON으로 반환하는 Hello, World!

jETA 2020. 1. 21. 10:00
반응형

오늘 만들 것

지난 글에서 이미 Hello, World!를 출력해보았습니다.

하지만 이번 글에서도 Hello, World!를 출력하려고 합니다.

 

다른 점이 있다면 이번엔 API의 형태로 데이터를 주고 받겠습니다.

GET http://localhost:8080/greeting와 같이 API를 요청하면,

{ “id”: 1, ”content”: ”Hello, World!” }의 형태로 반환해보겠습니다.

 

이번 글의 상당 부분은 Pivotal Software에서 제공하는 Spring 가이드(Getting Started · Building a RESTful Web Service) 를 번역하여 작성했습니다.

 

시작하기 전에: DAO? DTO? VO?

Spring에 대해 조사해 본 적이 있다면 DAO나 DTO, VO 등의 용어를 접해봤을 겁니다.

이 세 용어는 객체의 유형을 뜻합니다.

앞으로도 꾸준히 사용되는 용어이기 때문에 한 차례 정리합니다.

 

DTO: Data Transfer Object

DTO는 데이터 교환을 위한 객체입니다.

로그인 과정을 예로 들면 Client와 API Server 사이, API Server와 DB Server 사이에 회원 정보를 전달할 때 사용됩니다.

DTO는 보통 멤버 변수와 Getter, Setter로 이루어져 있습니다.

DTO를 사용함으로서 데이터 캡슐화가 가능하고, 각 계층에서 데이터를 안전하게 다룰 수 있습니다.

 

VO: Value Object

어떠한 값을 정의하기 위해 쓰입니다.

DTO에 읽기 전용 속성이 적용되었다고 이해하시면 됩니다.

읽기 전용이기 때문에 Getter 기능만 존재합니다.

 

DAO: Data Access Object

DB의 데이터에 접근할 때 사용하는 객체입니다.

DAO는 미리 DB와 Connection을 생성한 후 필요할 때 사용합니다.

때문에 내부에 DB와 데이터를 주고 받는 내용이 정의되어 있습니다.

 

예를 들어 회원가입을 한다면 아래와 같이 호출할 수 있습니다.

private final userDAO = new UserDAO(); // 사용자 DAO 생성 (DB연결)
private final newUser = new UserDTO(); // 새 사용자 생성

userDAO.insertUser(newUser);           // DAO에게 새 사용자 INSERT 요청

DTO, VO, DAO의 사용법은 앞으로 게시판 서버를 구현하며 파악할 수 있습니다.

지금은 ‘이런 것이 있구나’하고 넘어가도 됩니다.

 

프로젝트 생성

지난 글을 참고해서 프로젝트를 생성하시면 됩니다.

단, 이번 글에서는 API 서버를 생성할 예정이기 때문에 View 페이지가 필요하지 않습니다.

 

Thymeleaf는 빼고 아래 세 패키지에 대한 의존성만 추가합니다.

이렇게 세 개만 추가하시면 됩니다.

 

DTO 생성

서버에서 클라이언트로 데이터를 전달하기 위해 DTO를 정의합니다.

다음 경로에 아래 코드를 작성하여 저장합니다: /src/main/java/YOUR/DOMAIN/ARTIFACT/dto/GreetingDTO.java

package net.jetalab.spreinglab02.dto; // 자신의 프로젝트에 맞게 수정합니다.

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@AllArgsConstructor                   // this.var = var; 와 같은 생성자를 자동으로 생성한다.
@Getter                               // getId(), getContent() 등의 Getter를 자동으로 생성한다.
@Setter                               // setId(id), setContent(content) 등의 Setter를 자동으로 생성한다.
public class GreetingDTO {
    private long id;                  // 방문 ID
    private String content;           // 인삿말
}

 

이 클래스는 방문자의 ID와 방문자에게 전송할 인삿말을 정의합니다.

 

앞서 DTO에는 Getter와 Setter가 필요하다고 말씀드렸습니다.

하지만 위 코드에는 관련 메소드가 정의되지 않은 것처럼 보여집니다.

 

사실 7번째 줄부터 9번째 줄의 Annotation이 Getter 메소드와 Setter 메소드, 그리고 Constructor를 정의해줍니다.

우리가 프로젝트를 생성할 때 의존성으로 추가했던 Lombok이 선언을 대신 해준겁니다.

 

Lombok에 대한 자세한 내용은 아래 링크에서 확인할 수 있습니다.

Lombok을 이용해 Constructor/Getter/Setter/Builder에서 벗어나는법 :: 삐멜 소프트웨어 엔지니어

 

Controller 생성

사용자 요청을 처리하고 응답을 전송하는 컨트롤러를 정의합니다.

다음 경로에 아래 코드를 작성하여 저장합니다: /src/main/java/YOUR/DOMAIN/ARTIFACT/controller/GreetingController.java

package net.jetalab.spreinglab02.controller;     // 자신의 프로젝트에 맞게 수정합니다.

import net.jetalab.spreinglab02.dto.GreetingDTO; // 자신의 프로젝트에 맞게 수정합니다.

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.atomic.AtomicLong;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/greeting")
    public GreetingDTO greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
        return new GreetingDTO(counter.incrementAndGet(), String.format(template, name));
    }
}

꽤 간단해보이는 예제이지만 알찬 코드입니다.

차근차근 설명하겠습니다.

 

  • 11번째 줄
    @RestController Annotation을 사용하면 간단하게 RESTful 웹서비스를 위한 컨트롤러를 정의할 수 있습니다.
    Spring 4에서 추가된 @RestController Annotation은 기존의 @Controller@ResponseBody를 생략할 수 있게 해줍니다.
    RESTful 웹 서비스를 간편하게 구축할 수 있도록 해준다고 이해하면 될 것 같습니다.

  • 17번째 줄
    @RequestMapping Annotation을 사용해 /greeting로의 요청을 greeting() 메소드와 매핑합니다.
    위 예제에서는 HTTP 요청 메소드를 지정하지 않았기 때문에 모든 메소드에 대해 응답합니다.
    @RequestMapping(method=GET)과 같이 선언하면 지정한 메소드에 대해서만 응답하도록 할 수 있습니다.

  • 18번째 줄 ~ 20번째 줄: greeting()
    @RequestParam은 QueryString 파라미터를 정의합니다.
    위 예제에서는 QueryString 파라미터 name의 값을 String형 변수 name에 담습니다.
    만약 name 파라미터가 없다면 defaultValue에 지정된 "World"가 담깁니다.

    greeting() 메소드는 idcontent를 멤버 변수로 가지고 있는 새 GreetingDTO 객체를 만들어 반환합니다.
    이 때, HTTP 응답으로 GreetingDTO 객체의 데이터가 JSON 형태로 전달됩니다.

    Spring의 MappingJackson2HttpMessageConverter가 Jackson 2를 이용해 Greeting 인스턴스를 자동으로 JSON으로 변환해주기 때문에 직접 변환할 필요가 없습니다.

디렉토리 구조

두 파일을 생성한 후 아래 이미지와 같은 구조를 가지게 됩니다.

/src/main/java 이하를 보시면 됩니다.

 

테스트

IDE 우측 상단의 ▶ Run 버튼을 누르거나 키보드의 ^R(Control + R) 버튼을 눌러서 서버를 실행합니다.

정상적으로 실행되면 Postman이나 curl 등의 도구를 이용해 다음 API를 호출합니다: http://localhost:8080/greeting

아래와 같은 응답을 받을 수 있습니다.

새로운 Hello, World!

 

다음과 같이 QueryString 파라미터 name을 추가하면 이전과 다른 응답을 받을 수 있습니다: http://localhost:8080/greeting?name=jETA

 

예제 코드

본 포스트의 본 포스트의 예제 코드는 GitHub에 공개되어 있습니다.
https://github.com/jETA-Kor/sp-re-ing/tree/master/lab02

 

참고 문서

 

반응형