[Checkmate] intellij spring boot 협업시 개발 환경 통일 하기 - rest API 구조 설계 - 2

Jifrozen·2022년 5월 20일
0

checkmate

목록 보기
2/4

REST API 설계하기

API 서버 개발을 본격적으로 진행해 보기 위해
현재 API 인터페이스 및 결과 데이터의 구조를 살펴보고
확장 가능한 형태로 설계할 것이다.

API는 제공 대상이 클라이언트 APP이나 WEB 개발자이다. (프론트앤드)
한 번 배포되고 공유한 API는 구조를 쉽게 바꿀 수 없기 때문에 처음부터 효율적이로 확장 가능한 형태로 모델을 설계하고 시작하는게 좋다.

그래서 다음과 같이 HttpMethod를 사용하고
Restful 한 API를 만들기 위해 몇 가지 규칙을 적용 할 것이다.

1. http method 구분해서 사용

post:쓰기
get:읽기
put:수정
delete:삭제

2. 매핑된 주소 체계를 정형화

Post /auth/login
Post /auth/signup
...

3. 데이터의 구조를 표준화하여 정의

// 기존 USER 정보
{
"msrl": 1,
"uid": "test@test.com",
"name": "test"
}
// 표준화한 USER 정보 결과 데이터 + API 요청 결과 데이터
{
"data": {
"msrl": 1,
"uid": "test@test.com",
"name": "test"
},
"success": true
"code": 0,
"message": "성공하였습니다."
}

API 요청 결과 데이터를 담는 공통 모델

API의 처리 상태 및 메시지를 내려주는 데이터로 구성된다.
success는 API의 성공, 실패 여부를 나타내고
code, msg는 해당 상황에서의 응답 코드와 응답 메시지를 나타낸다.

package com.checkmate.backend.common;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;

/**
 * @package : com.checkmate.backend.common
 * @name: CommonResult.java
 * @date : 2022/05/19 7:18 오후
 * @author : jifrozen
 * @version : 1.0.0
 * @description : REST API 결과 모델 생성
 * @modified :
 **/
@Getter
@Setter
public class CommonResult {

	@Schema(description = "응답 성공 여부 = true/false")
	private boolean success;

	@Schema(description = "응답 코드 번호")
	private int code;

	@Schema(description = "응답 메시지")
	private String msg;
}

단일건 api 결과 처리

Generic Interface에 를 지정하여
어떤 형태의 값도 넣을 수 있도록 구현한다.
또한, CommonResult를 상속받아 API 요청 결과도 같이 출력된다.

package com.checkmate.backend.common;

import lombok.Getter;
import lombok.Setter;

/**
 * @package : com.checkmate.backend.common
 * @name: SingleResult.java
 * @date : 2022/05/19 7:20 오후
 * @author : jifrozen
 * @version : 1.0.0
 * @description : 단일건 api 결과 처리
 * @modified :
 **/
@Getter
@Setter
public class SingleResult<T> extends CommonResult {
	private T data;
}

여러 건 API 결과 처리

API 결과가 다중 건인 경우에 대한 데이터 모델이다.
결과 필드를 List 형태로 선언하고
Generic Interface에 를 지정하여
어떤 형태의 List 값도 넣을 수 있도록 구현한다.

또한, CommonResult를 상속받아 API 요청 결과도 같이 출력한다.

package com.checkmate.backend.common;

import java.util.List;

import lombok.Getter;
import lombok.Setter;

/**
* @package : com.checkmate.backend.common
* @name: ListResult.java
* @date : 2022/05/19 7:20 오후
* @author : jifrozen
* @version : 1.0.0
* @description : 여러건 api 결과 처리
* @modified :
**/
@Getter
@Setter
public class ListResult<T> extends CommonResult {
	private List<T> list;
}

결과 모델을 처리할 Service

결과 모델에 데이터를 넣어주는 역할을 하는 Service를 정의한다. Controller에서 항상 ResponseService를 호출하여 결과 모델로 반환해준다.

package com.checkmate.backend.service;

import java.util.List;

import org.springframework.stereotype.Service;

import com.checkmate.backend.common.CommonResult;
import com.checkmate.backend.common.ListResult;
import com.checkmate.backend.common.SingleResult;

/**
* @package : com.checkmate.backend.service
* @name: ResponseService.java
* @date : 2022/05/19 7:50 오후
* @author : jifrozen
* @version : 1.0.0
* @description : 결과 모델을 처리할 서비스
* @modified :
**/
@Service
public class ResponseService {
	// 단일건 결과 처리
	public <T> SingleResult<T> getSingleResult(T data) {
		SingleResult<T> result = new SingleResult<>();
		result.setData(data);
		setSuccessResult(result);
		return result;
	}

	// 다중건 결과 처리
	public <T> ListResult<T> getListResult(List<T> list) {
		ListResult<T> result = new ListResult<>();
		result.setList(list);
		setSuccessResult(result);
		return result;
	}

	// 성공 결과만 처리
	public CommonResult getSuccessResult() {
		CommonResult result = new CommonResult();
		setSuccessResult(result);
		return result;
	}

	// 성공하면 api 성공 데이터 세팅
	private void setSuccessResult(CommonResult result) {
		result.setSuccess(true);
		result.setCode(CommonResponse.SUCCESS.getCode());
		result.setMsg(CommonResponse.SUCCESS.getMsg());
	}

	// 실패 결과만 처리
	public CommonResult getFailResult(int code, String msg) {
		CommonResult result = new CommonResult();
		result.setSuccess(false);
		result.setCode(code);
		result.setMsg(msg);
		return result;
	}

	public enum CommonResponse {
		SUCCESS(0, "성공"),
		FAIL(-1, "실패");

		int code;
		String msg;

		CommonResponse(int code, String msg) {
			this.code = code;
			this.msg = msg;
		}

		public int getCode() {
			return code;
		}

		public String getMsg() {
			return msg;
		}
	}

}

HttpMethod와 정형화된 주소체계로 Controller 적용

다중건 처리는 ListResult()

	@ApiOperation(value = "업체 메뉴 조회", notes = "업체 메뉴를 조회한다.")
	@GetMapping(value = "/{storeId}/menus")
	public ListResult<Menu> menus(
		@ApiParam(value = "업체 Id", required = true) @PathVariable long storeId
	) {
		return responseService.getListResult(menuService.getMenus(storeId));
	}
### 단일건 처리는 SingleResult()
	@ApiImplicitParams({
		@ApiImplicitParam(name = "X-AUTH-TOKEN", value = "로그인 성공 후 access_token", required = true, dataType = "String", paramType = "header")
	})
	@ApiOperation(value = "회원 정보 조회", notes = "회원 마이페이지 조회")
	@GetMapping(value = "/customer")
	public SingleResult<Customer> getCustomer() throws Throwable {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		String email = authentication.getName();

		return responseService.getSingleResult(userService.getCustomer(email));
	}

API 처리 성공 결과만 필요한 경우 getSuccessResult()


	@ApiOperation(value = "비밀번호 확인")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "X-AUTH-TOKEN", value = "로그인 성공 후 access_token", required = true, dataType = "String", paramType = "header")
	})
	@PostMapping(value = "/password/verification")
	public CommonResult verifyPassword(
		@ApiParam(value = "비밀번호 확인", required = true) @RequestParam String password) throws
		Throwable {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		String email = authentication.getName();

		if (!userService.isValidPassword(email, password)) {
			throw new PasswordNotMatchedException();

		}
		return responseService.getSuccessResult();
	}

출처 - https://velog.io/@jifrozen/Dining-together-REST-API-구조-설계하기
https://pepega.tistory.com/26

0개의 댓글