๊ณตํต ์๋ต ํฌ๋งท ์ค๊ณ
01. ๋ฐฐ๊ฒฝ
ํ๋ก์ ํธ ์ด๊ธฐ ์ธํ ๋จ๊ณ์์ ๊ณตํต ์๋ต ํฌ๋งท์ ์ค๊ณํ๋ค. ์์ ์์ ๊ณตํต ์๋ต ํฌ๋งท์ ์ฌ์ฉํ๋ ๋ฐฉ์์ ์ ํ๊ณ , ์ง์ ์ ์ฉํด๋ณด๋ ์ผ๊ด์ฑ ์๋ API ์๋ต ๊ตฌ์กฐ๊ฐ ๊ฐ๋ฐ ์ ๋ฐ์ ๋์์ด ๋๋ค๊ณ ๋๊ปด์ ์ด ํ๋ก์ ํธ์๋ ๋์ผํ๊ฒ ์ ์ฉํ๋ค.
02. ๊ณตํต ์๋ต ํฌ๋งท์ ์ฌ์ฉํ๋ ์ด์
API ์๋ต ํ์์ด ์๋ํฌ์ธํธ๋ง๋ค ๋ค๋ฅด๋ฉด ์๋์ ๊ฐ์ ๋ฌธ์ ๊ฐ ์๊ธด๋ค.
// ์ด๋ค API๋ ์ด๋ ๊ฒ ๋ฐํํ๊ณ
{ "id": 1, "title": "ํด๋ฆฐ์ฝ๋" }
// ์ด๋ค API๋ ์ด๋ ๊ฒ ๋ฐํํ๊ณ
{ "result": "success", "post": { "id": 1 } }
// ์๋ฌ๋ ๋ ์ด๋ ๊ฒ ๋ฐํํ๋ค
{ "error": "Not Found" }
ํ๋ก ํธ์๋ ์ ์ฅ์์๋ API๋ง๋ค ์๋ต ๊ตฌ์กฐ๊ฐ ๋ฌ๋ผ์ ์ฒ๋ฆฌ ์ฝ๋๊ฐ ๋ณต์กํด์ง๊ณ , ๋ฐฑ์๋ ์ ์ฅ์์๋ ์๋ต ํ์์ด ํต์ผ๋์ง ์์ ์ ์ง๋ณด์๊ฐ ์ด๋ ค์์ง๋ค. ๊ณตํต ์๋ต ํฌ๋งท์ ์ฌ์ฉํ๋ฉด ์๋ ์ฅ์ ์ด ์๋ค.
- ํ๋ก ํธ์๋-๋ฐฑ์๋ ๊ฐ ํ์ ๋จ์ํ: ๋ชจ๋ API๊ฐ ๋์ผํ ๊ตฌ์กฐ๋ฅผ ๋ฐํํ๋๊น ํ๋ก ํธ์๋์์ ์๋ต ์ฒ๋ฆฌ ๋ก์ง์ ํ๋๋ก ํต์ผํ ์ ์๋ค.
- ์ฑ๊ณต/์คํจ ์ฌ๋ถ๋ฅผ HTTP ์ํ ์ฝ๋์๋ง ์์กดํ์ง ์์๋ ๋จ: success ํ๋๋ก ๋ช ์์ ์ผ๋ก ํํํ๋ฉด ํ๋ก ํธ์๋์์ ๋ ๋ช ํํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
- ์๋ฌ ๋ฉ์์ง ์ ๋ฌ ์ผ๊ดํ: message ํ๋๋ก ํต์ผํ๋ฉด ํ๋ก ํธ์๋๊ฐ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ด๋์ ๊บผ๋ด์ผ ํ ์ง ๋งค๋ฒ ํ์ธํด์ผ ํ๋ ํผ๋์ด ์์ด์ง๋ค.
- ํ์ฅ์ฑ: ๋์ค์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๊ณ ์ถ์ ๋ ApiResponse<T> ํ๋๋ง ์์ ํ๋ฉด ์ ์ฒด API์ ๋ฐ์๋๋ค.
03. ์ค๊ณ ๊ฒฐ์
1. ApiResponse<T> — ๊ณตํต ์๋ต ๋ํผ
๋ชจ๋ API ์๋ต์ ApiResponse<T>๋ก ๋ํํด์ ์ฑ๊ณต/์คํจ ์ฌ๋ถ์ ๋ฐ์ดํฐ๋ฅผ ์ผ๊ด๋ ๊ตฌ์กฐ๋ก ๋ฐํํ๋ค. record๋ฅผ ํ์ฉํด ๋ถ๋ณ ๊ฐ์ฒด๋ก ์ค๊ณํ๋ค.
/**
์๋น์ค ์ ์ญ์์ ์ฌ์ฉํ๋ ๊ณตํต API ์๋ต ๋ํผ.
๋ชจ๋ ์ปจํธ๋กค๋ฌ ์๋ต์ ์ด ํด๋์ค๋ก ๋ํ๋๋ค.
*/
public record ApiResponse<T>(boolean success, T data, String message) {
/** ๋ฐ์ดํฐ ์๋ ์ฑ๊ณต ์๋ต */
public static <T> ApiResponse<T> ok() {
return new ApiResponse<>(true, null, null);
}
/** ๋ฐ์ดํฐ ์๋ ์ฑ๊ณต ์๋ต */
public static <T> ApiResponse<T> ok(T data) {
return new ApiResponse<>(true, data, null);
}
/** ์คํจ ์๋ต */
public static <T> ApiResponse<T> fail(String message) {
return new ApiResponse<>(false, null, message);
}
}
2. record DTO — ๋ถ๋ณ ๋ฐ์ดํฐ ๊ฐ์ฒด
Java 16๋ถํฐ ๋์ ๋ record๋ฅผ DTO์ ์ ๊ทน ํ์ฉํ๋ค. ๊ธฐ์กด ํด๋์ค ๊ธฐ๋ฐ DTO ๋๋น ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋๋ฅผ ํฌ๊ฒ ์ค์ผ ์ ์๋ค. record๋ ์๋์ผ๋ก ์์ฑ์, getter, equals(), hashCode(), toString()์ ์์ฑํด์ฃผ๊ณ ๋ถ๋ณ ๊ฐ์ฒด๋ผ DTO๋ก ์ ํฉํ๋ค.
// record ๊ธฐ๋ฐ DTO
public record PostResponse(
Long id,
String title,
String author
) { }
3. from() ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋ — DTO ๋ณํ ์ฑ ์ ๋ถ๋ฆฌ
์ํฐํฐ๋ฅผ DTO๋ก ๋ณํํ๋ ์ฑ ์์ DTO ์์ ์ด ๊ฐ๋๋ก from() ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค. Service๋ ๋น์ฆ๋์ค ๋ก์ง์๋ง ์ง์คํ ์ ์๊ฒ ๋๋ค.
public record PostResponse(Long id, String title, String author, String genre) {
/** Post ์ํฐํฐ๋ฅผ ์๋ต DTO๋ก ๋ณํํ๋ค. */
public static PostResponse from(Post post) {
return new PostResponse(
post.getId(), post.getTitle(), post.getAuthor(), post.getGenre()
);
}
}
4. CustomException + ErrorCode — ์์ธ ์ฒ๋ฆฌ ์ผ๊ดํ
์์ธ ๋ฐ์ ์ CustomException๊ณผ ErrorCode๋ฅผ ํจ๊ป ๋์ ธ GlobalExceptionHandler์์ ์ผ๊ด ์ฒ๋ฆฌํ๋ค.
@ExceptionHandler(CustomException.class)
public ResponseEntity<ApiResponse<Void>> handleCustomException(CustomException e) {
return ResponseEntity
.status(e.getErrorCode().getStatus())
.body(ApiResponse.fail(e.getErrorCode().getMessage()));
}
04. ์ ๋ฆฌ
| ๊ฒฐ์ | ์ด์ |
|---|---|
| ApiResponse<T> ๋ํผ | ๋ชจ๋ API ์๋ต ํ์ ํต์ผ |
| record DTO | ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ ๊ฑฐ, ๋ถ๋ณ ๊ฐ์ฒด |
| from() ํฉํ ๋ฆฌ ๋ฉ์๋ | DTO ๋ณํ ์ฑ ์ ๋ถ๋ฆฌ, Service ๋จ์ํ |
| CustomException + ErrorCode | ์์ธ ์ฒ๋ฆฌ ์ผ๊ดํ, ์ ์ญ ํธ๋ค๋ง |