Custom Response 생성하기

박영준·2023년 2월 8일
0

Spring

목록 보기
11/58

1. response 데이터의 종류

api 요청 후, 그에 대한 응답으로 받는 데이터는 크게 세 가지다.

  1. 단일 데이터
  2. 리스트 데이터
  3. 에러

2. 문제점

1) 설계

BookController

// 책 단건 조회 → 단일 데이터
@GetMapping(value = /book/{bookId})
public Book getBookById(@PathVariable long bookId) {
	return bookService.getBookById(BookId);
}

// 책 목록 조회 → 리스트 데이터
@GetMapping(value = /books/{userId})
public List<Book> getBookList(@PathVariable long userId) {
	return bookService.getBooksByUser(userId);
}

BookService

// 책 단건 조회 → 단일 데이터
public Book getBookById(long bookId) {
	return bookJpaRepo.findById(bookId).get();
}

// 사용자별 책 목록 조회 → 리스트 데이터
public List<Book> getBookByUser(long userId) {
	User user = userJpaRepo.findById(userId).get();
    
    List<Book> bookList = bookJpaRepo.findBooksByUser(user)
    return bookList;
}

단건조회 → Book 반환

다중조회 → List< Book> 반환

2) 문제점

DB 에 존재하지 않는 책을 조회하려고 할 경우
서버상의 에러가 발생

즉, 가공하지 않고 Entity 를 그대로 반환하게 되면
Entity 가 외부에 그대로 노출되어서, 상황에 따른 에러들을 적절하게 처리할 수 없게 된다.

3. 해결법

따라서, 해당 아이디를 가진 책은 존재하지 않는다는 응답을 돌려주기 위해
서버단에서 직접 코드로 문제상황에 따른 에러를 내려주는 과정이 필요하다.

1) Custom Response 생성

(1) 설계

① 응답(response)에 포함될 속성

  1. 데이터 (엔티티 or 엔티티 리스트)
  2. 성공 여부
  3. status code
  4. 에러에 해당하는 경우 메세지 (에러 발생 요인)

② 패키지 생성

(2) CommonResponse

공통 속성

@Getter
class CommonResponse {
	boolean success;		// ① 응답(response)에 포함될 속성 中 2. 성공 여부
    int code;		// ① 응답(response)에 포함될 속성 中 3. status code
    String message;		// ① 응답(response)에 포함될 속성 中 4. 에러에 해당하는 경우 메세지 (에러 발생 요인)
}

(3) SingleResponse<T>

공통속성 + 엔티티 T 의 단일 데이터

@Getter
public class SingleResponse<T> extends CommondResponse {
	T data;		// ① 응답(response)에 포함될 속성 中 1. 데이터 (엔티티 or 엔티티 리스트)
}

(4) ListResponse<T>

공통속성 + 엔티티 T의 리스트 데이터

@Getter
public class ListResponse <T> extends CommondResponse {
	List<T> dataList;		// ① 응답(response)에 포함될 속성 中 1. 데이터 (엔티티 or 엔티티 리스트)
}

정리하자면,
CommonResponse 클래스에 공통 속성(success, code, message) 을 부여하고
++ 각각 CommonResponse 를 상속해서 데이터만 추가하면 된다.

2) ResponseService 생성

반환받은 데이터를 감싸서, Controller단에 넘겨줄 Service 클래스를 생성

@Service
public class ResponseService {
	// getSingleResponse : T를 받아 SingleResponse<T> 로 반환
	public<T> SingleResponse<T> getSingleResponse(T data) {
    
    	SingleResponse singleResponse = new SingleResponse();
        
        singleResponse.data = data;
        setSuccessResponse(singleResponse);
        
        return singleResponse;
    }
    
    // getListResponse : List<T> 를 받아 ListResponse<T> 로 반환
    public<T> ListResponse<T> getListResponse(List<T> dataList) {
    
    	ListResponse listResponse = new ListResponse();
        
        listResponse.dataList = dataList;
        setSuccessResponse(listResponse);
        
        return listResponse;
    }
    
    void setSuccessResponse(CommondResponse response) {
    	response.code = 0;
        response.success = true;
        response.message ="success";
    }
}

3) BookController 생성(수정)

@RestController
RequiredArgsConstructor
public class BookController {

	private final BookService bookService;
    private final ResponseService responseService;

	// 책 단건 조회 → 단일 데이터
    @GetMapping(value = /book/{bookId})
    public SingleResponse<Book> getBookById(@PathVariable long bookId) {
        return responseService.getSingleRespone(bookService.getBookById(BookId));
    }

    // 책 목록 조회 → 리스트 데이터
    @GetMapping(value = /books/{userId})
    public ListResponse<Book> getBookList(@PathVariable long userId) {
        return responseService.getListResponse(bookService.getBooksByUser(userId));
    }

}

수정 전 : public Book getBookById(@PathVariable long bookId)
수정 후 : public SingleResponse< Book> getBookById(@PathVariable long bookId)
→ Book 엔티티를 한 번 더 감쌌다.

수정 전 : return bookService.getBookById(BookId);
수정 후 : return responseService.getSingleRespone(bookService.getBookById(BookId));
→ bookService.getBookById(BookId) 를 한 번 더 감쌌다.

수정 전 : public List< Book> getBookList(@PathVariable long userId)
수정 후 : public ListResponse< Book> getBookList(@PathVariable long userId)

수정 전 : return bookService.getBooksByUser(userId);
수정 후 : return responseService.getListResponse(bookService.getBooksByUser(userId));
→ bookService.getBooksByUser(userId) 를 한 번 더 감쌌다.

4) 결과 확인

단건 조회

다중(List) 조회


참고: [스프링부트] Response를 객체에 담아 반환하기 (커스텀 Response 생성하기)

profile
개발자로 거듭나기!

0개의 댓글