데블 아니고 데블리

운동,햄버거, 개발 좋아요

🐷💻📝

프로그래밍/웹기술

API 방식에 따른 반환 클래스 구현

데블아니고데블리 2024. 3. 23. 17:49

[개요]

백엔드는 spring , 프론트엔드는 vue 를 사용하는 프로젝트를 시작하게 되었습니다.

기존 thymeleaf 로 개발하던 방식과는 다르게 Api를 사용하게 되었습니다.

 

그렇다면!

기존 thymeleaf 프로젝트와 Api 방식은 어떤 차이가 있을까요 ?

 

1. Thymeleaf 사용해 개발한다.

데이터를 컨트롤러에서 사용하는 model 에 담아 타임리프 html 파일을 반환합니다.

여기서 타임리프는 HTML 및 XML 기반의 뷰 템플릿 엔진으로 사용되는 기술이며, 타임리프는 서버 측에서 실행되며, 클라이언트에게 렌더링된 최종 HTML을 전송합니다.

 

즉 타임리프가 알아서 다 할게! (서버 사이드 랜더링) 방식입니다.

 

2. RESTful API로 개발한다.

프론트엔드 프레임워크와 소통하는 방법이라고 생각하면 됩니다.

사용자 -> 프론트 -> 서버 로 이루어진 구조라고 생각하면 됩니다.

사용자가 ui를 통해 프론트에 요청을 하면 -> 프론트에서 서버가 알아들을 수 있도록 REST API 로 요청합니다. 그럼 요청을 받은 서버가 REST API 방식으로 응답값을 내려줍니다. 서버 입장에서는 정보만 내려주면 되니 편해졌습니다. -> json 형식의 데이터 반환

 

저도 타임리프 방식이 익숙하고 바로바로 바인딩 할 수 있어서 개발하기에는 편하다는 생각이 들었었는데요.. 

 

하지만 제가 직접 느끼기에는

1. JSON과 같은 표준 데이터 포맷을 사용하니 시스템간의 호환성이 높아집니다.

2. HTTP 프로토콜(GET, POST, PUT, DELETE) 를 사용하여 보다 익숙하고 일관성 있게 코드를 짤 수 있습니다. 

 

그 외에 

3. 보안

4. 인터페이스로 분리가 된다는 장점이 있는데 이는 개발 하다보면서 와닿으면 근거에 대해 작성해 보도록 하겠습니다.

 

결론적으로 오늘 포스팅을 한 이유는... 만들었습니다! 공통코드

 

공통코드로 api 반환값을 만들어두면 개발할 때 똑같은 형식으로 떨어지니까 조금 더 친절한 백엔드가 될 수 있겠죠.. 프론트에서도 데이터 요청하는 

 

* 다음시간에는 swagger 에 대해 작성해 보도록 하겠습니다.

 

데이터를 병렬화 시키기 위해 jackson 라이브러리를 사용하였습니다. 모든 REST controller 에서 리턴할 때 이 메서드를 호출하여 데이터를 병렬화 시킵니다.(build.gradle에 넣는 방법도 있지만, spring boot가 플러그인을 제공해줍니다.)

 

@JsonInclude라는 어노테이션을 사용하면 자동으로 설치됩니다.

import com.fasterxml.jackson.annotation.JsonInclude;

 

제네릭 타입<T>를 사용하여 다양한 타입의 데이터를 응답 데이터로 표현할 수 있도록 했습니다. 또한 리턴값으로 Http response 값을 받아 에러 상황에 대해 프론트가 유연하게 대처할 수 있도록 하였습니다.

 

전체 코드입니다.

package com.example.fcm.common;


import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.Setter;
import org.springframework.http.HttpStatus;

@Getter
@Setter
public class ApiResponse<T> {

    private int code;
    private String message;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T data;


    public ApiResponse(int code, String message){
        this.code = code;
        this.message = message;
    }

    public ApiResponse(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> ApiResponse<T> ok() {
        return new ApiResponse<>(HttpStatus.OK.value(), "성공했습니다.");
    }

    public static <T> ApiResponse<T> ok(T data) {
        return new ApiResponse<>(HttpStatus.OK.value(), "성공했습니다", data);
    }

    public static <T> ApiResponse<T> ok(String message,T data) {
        return new ApiResponse<>(HttpStatus.OK.value(), message, data);
    }

    public static ApiResponse<String> error(String message) throws Exception {
        throw new Exception(message);
    }



}