[내일배움캠프 Spring 4기] 24일차 TIL - 서버의 주 업무 | JSON 데이터 반환하는 방법 | RestController | Jackson | DTO | Create, Read, Upgrade, Delete

서예진·2024년 1월 22일
0

오늘의 학습 키워드

▸ 코드 카타
▸ 서버의 주 업무
▸ JSON 데이터 반환하는 방법
▸ RestController
▸ Jackson
▸ DTO
▸ Create, Read, Upgrade, Delete


▸ 코드 카타

2024년 1월 22일 - [프로그래머스] 10: 시저암호 | 숫자 문자열과 영단어 | 문자열 내 마음대로 정렬하기


▸ 서버의 주 업무

  • MySQL과 같은 데이터 서버에서 받아온 데이터를 Client(브라우저)에 반환을 해주면 이 Client에서 해당 데이터를 가지고 브라우저를 통해서 사용자에게 어떠한 결과 값을 보여주는 식
  • 서버가 직접 HTML을 반환하기보다는 이 요청에 맞는 특정한 정보만 반환하는 것을 조금 더 선호
  • AJAX -> 비동기적으로 서버에 요청
    Response -> 그 요청에 맞게 JSON 형태의 데이터로 반환

▸ JSON 데이터 반환하는 방법

  • JSON형태는 서버에서 읽을 수 없음 -> JSON형태는 JAVA라는 언어에 존재하지 않음, 자바스크립트에서 존재
  • JSON형태로 Client에 반환
@Controller
@RequestMapping("/response")
public class ResponseController {
    @GetMapping("/json/string")
    @ResponseBody
    public String helloStringJson() {
        return "{\"name\":\"yejin\",\"age\":26}";
    }

    @GetMapping("/json/class")
    @ResponseBody
    public Star helloClassJson(){
        return new Star("yejin", 26);
    }
}
  • @Controller : 컨트롤러 역할 명시
  • @RequestMapping : /response로 오는 요청들은 모두 여기서 처리한다는 것을 명시
  • @ResponseBody : HTML 반환이 아니라 그냥 데이터 반환임을 명시
  • return "{\"name\":\"yejin\",\"age\":26}" : JSON형태로 생겼는데 String타입인 형태로 반환
    -> content-type = text/html => html에서는 이 text로 인식
[Star]
package com.sparta.springmvc.response;

import lombok.Getter;

@Getter
public class Star {
    String name;
    int age;

    public Star(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Star() {}
}
  • return new Star("yejin", 26); -> content-type = application/json => 자바 객체를 그대로 반환하게 되면 자바스크립트에서 인식 불가 / Spring에서 자동으로 이 자바 객체를 JSON형태로 반환
    • JSON 형태인 것을 알 수 있음

▸ RestController

@RestController
@RequestMapping("/response/rest")
public class ResponseRestController {
    // [Response header]
    //   Content-Type: text/html
    // [Response body]
    //   {"name":"yejin","age":26}
    @GetMapping("/json/string")
    public String helloStringJson() {
        return "{\"name\":\"yejin\",\"age\":26}";
    }

    // [Response header]
    //   Content-Type: application/json
    // [Response body]
    //   {"name":"yejin","age":26}
    @GetMapping("/json/class")
    public Star helloClassJson() {
        return new Star("yejin", 26);
    }
}
  • @RestCotroller = @Controller + @ResponseBody
  • 이 클래스 내에 전체 메서드가 모두 데이터를 반환하는 경우 사용

📍@Controller / @RestController

  • 해당 클래스 내에서 view를 반환하는 메서드가 있으면 해당 클래스는 @Controller, 데이터를 반환하는 메서드에만 @ResponseBody
  • 해당 클래스 내에서 데이터를 반환하는 메서드만 있으면 @RestController

▸ Jackson

  • Jackson: JSON 데이터 구조를 처리해주는 라이브러리
    • Object(자바 객체)를 JSON 타입의 String으로 변환 가능
    • JSON 타입의 String을 Object로 변환 가능

📍Object -> JASON

  • Getter, 즉 get 메서드가 필요
@Test
@DisplayName("Object To JSON : get Method 필요")
void test1() throws JsonProcessingException {
        Star star = new Star("yejin", 26);

        ObjectMapper objectMapper = new ObjectMapper(); // Jackson 라이브러리의 ObjectMapper
        String json = objectMapper.writeValueAsString(star);

        System.out.println("json = " + json);
    }
  • objectMapper.writeValueAsString(변환하고싶은 object 객체)
json = {"name":"yejin","age":26}
  • String이 찍힌건데 형태는 JSON
  • 기준은 name, age -> 필드의 값을 보고서 바꾸어줌
  • 변환할 때 ObjectMapper가 Getter 사용

📍JSON -> Object

  • 기본생성자와 get(or set) 메서드가 필요
  • JSON 타입의 String에서 변환하고자하는 객체의 필드와 같아야함
  • 예를들어, name이 아니라 nam이라고 하면 오류 발생
  • 오류: nam이라는 field를 인식할 수 없음
@Test
@DisplayName("JSON To Object : 기본 생성자 & (get OR set) Method 필요")
void test2() throws JsonProcessingException {
        String json = "{\"name\":\"yejin\",\"age\":26}"; // JSON 타입의 String

        ObjectMapper objectMapper = new ObjectMapper(); // Jackson 라이브러리의 ObjectMapper

        Star star = objectMapper.readValue(json, Star.class);
        System.out.println("star.getName() = " + star.getName());
    }
  • obejctMapper.readValue(JSON타입의 String 변수, 변환하고싶은 객체)

▸ DTO

📍DTO란 무엇일까?

  • DTO: 데이터 전송 및 이동을 위해 생성되는 객체
  • DB와의 소통을 담당하는 Java 클래스를 그대로 Client에 반환하는 것이 아니라 DTO로 한번 변환한 후 반환할 때도 사용됨.

📍RequestDto, ResponseDto

  • Request의 데이터를 처리할 때 사용되는 객체는 RequestDto
  • Response를 할 때 사용되는 객체는 RequestDto 명명하여 DTO 클래스를 생성
    => 절대적인 규칙은 아니다.

▸ Create, Read, Upgrade, Delete

  • Create: 메모 생성 -> PostMethod
  • Read: 메모 조회 -> GetMethod
  • Update: 메모 변경 -> PutMethod
  • Delete: 메모 삭제 -> DeleteMethod
[Controller package]
package com.sparta.memo.controller;

import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api")
public class MemoController  {

    private final Map<Long, Memo> memoList = new HashMap<>();

    @PostMapping("/memos")
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto){
        //requestDto를 저장해야하기 때문에 entity로
        Memo memo = new Memo(requestDto);

        //id
        Long maxId = memoList.size() > 0 ? Collections.max(memoList.keySet()) + 1 : 1;
        memo.setId(maxId);

        //데이터베이스에 저장
        memoList.put(memo.getId(), memo);

        //entity -> ResponseDto
        MemoResponseDto memoResponseDto = new MemoResponseDto(memo);

        return memoResponseDto;
    }
    @GetMapping("/memos")
    public List<MemoResponseDto> getMemos(){
        List<MemoResponseDto> responseList = memoList.values().stream()
                .map(MemoResponseDto::new).toList();
        return responseList;
    }
    @PutMapping("/memos/{id}")
    public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto){
        //해당 메모가 DB에 존재하는지 확인
        if(memoList.containsKey(id)){
            //해당 메모 가져오기
            Memo memo = memoList.get(id);

            //memo 수정
            memo.update(requestDto);
            return memo.getId();
        } else{
            throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
        }
    }
    @DeleteMapping("/memos/{id}")
    public Long deleteMemo(@PathVariable Long id){
        //해당 메모가 DB에 존재하는지 확인
        if(memoList.containsKey((id))){
            //해당 메모 삭제
            memoList.remove(id);
            return id;
        } else {
            throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
        }
    }

}
profile
안녕하세요

0개의 댓글