Search
๐Ÿ“š

EP12. API Response Format

์ƒ์„ฑ์ผ
2024/06/06 03:14
๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ
2024/06/12

EP12. API Response Format

API Response Format์„ ์„ค๊ณ„ํ•˜๊ณ  ๊ทธ ์ด์œ ๋ฅผ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

1. ํƒ€ ์„œ๋น„์Šค API Response ํ›‘์–ด๋ณด๊ธฐ

์œ ๋ช… ์„œ๋น„์Šค๋“ค์˜ API Response๋ฅผ ์‚ดํŽด๋ณด๋ฉฐ ์™œ ๊ทธ๋ ‡๊ฒŒ ๊ตฌํ˜„ํ–ˆ์„์ง€ ๊ณ ๋ฏผํ•ด๋ด…์‹œ๋‹ค.
1.
๋„ค์ด๋ฒ„ ์›นํˆฐ
{ "code": 20002, "message": "์„ฑ๊ณต", "result": { "appVersion": "2.19.0", "titleId": "793887" } }
JSON
๋ณต์‚ฌ
2.
์ฟ ํŒก
{ "rCode": "RET0000", "rMessage": "SUCCESS", "rData": true }
JSON
๋ณต์‚ฌ
3.
ํŽ˜์ด์ฝ”
{ "code": 0, "message": "success", "result": { "popupList": [], "floatingPopup": null } }
JSON
๋ณต์‚ฌ
4.
๋ฐฐ๋‹ฌ์˜๋ฏผ์กฑ
{ "status": "SUCCESS", "message": "์„ฑ๊ณต", "serverDatetime": "2024-06-18 22:44:12", "data": {} }
JSON
๋ณต์‚ฌ
๋‹ค๋ฅธ ์„œ๋น„์Šค ์•ฑ์ธ๋ฐ Response Format์ด ๋น„์Šทํ•œ ์ด์œ ์— ๋Œ€ํ•ด์„œ ๊ณ ๋ฏผํ•ด๋ด…์‹œ๋‹ค.

2. ๊ณตํ†ต Response Format ๊ตฌํ˜„

functions/api ๋””๋ ‰ํ† ๋ฆฌ ํ•˜์œ„์— lib/response ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
functions/api/lib/response/responseCode.ts
export enum ResponseCode { SUCCESS = 10000, INVALID_ARGUMENTS = 40000, SERVER_ERROR = 50000, // ์„œ๋น„์Šค์— ํ•„์š”ํ•œ ์˜ค๋ฅ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. }
TypeScript
๋ณต์‚ฌ
โ€ข
์„œ๋น„์Šค์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ฅ˜๋ฅผ ์„ธ๋ถ„ํ™”ํ•˜์—ฌ Code๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.
functions/api/lib/response/responseFormat.ts
import { ResponseCode } from "./responseCode.ts"; // ResponseFormat ์ธํ„ฐํŽ˜์ด์Šค๋Š” API ์‘๋‹ต์˜ ํ˜•์‹์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. // ์ œ๋„ค๋ฆญ ํƒ€์ž… T๋Š” JSON ๊ฐ์ฒด ๋˜๋Š” null์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. // deno-lint-ignore no-explicit-any๋Š” Record<string, any> ์‚ฌ์šฉ ์‹œ lint ์˜ค๋ฅ˜๋ฅผ ๋ฌด์‹œํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. // deno-lint-ignore no-explicit-any export interface ResponseFormat<T extends Record<string, any> | null> { // ์‘๋‹ต ์ฝ”๋“œ code: ResponseCode; // ์‘๋‹ต ๋ฉ”์‹œ์ง€ message: string; // ์‘๋‹ต ๊ฒฐ๊ณผ, JSON ๊ฐ์ฒด ๋˜๋Š” null result: T; } // createResponse ํ•จ์ˆ˜๋Š” ResponseFormat ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. // ์ œ๋„ค๋ฆญ ํƒ€์ž… T๋Š” JSON ๊ฐ์ฒด ๋˜๋Š” null์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. // deno-lint-ignore no-explicit-any๋Š” Record<string, any> ์‚ฌ์šฉ ์‹œ lint ์˜ค๋ฅ˜๋ฅผ ๋ฌด์‹œํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. // deno-lint-ignore no-explicit-any export function createResponse<T extends Record<string, any> | null>( // ์‘๋‹ต ์ฝ”๋“œ code: ResponseCode, // ์‘๋‹ต ๋ฉ”์‹œ์ง€ message: string, // ์‘๋‹ต ๊ฒฐ๊ณผ, JSON ๊ฐ์ฒด ๋˜๋Š” null result: T, ): ResponseFormat<T> { // ResponseFormat ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ return { code, message, result }; }
TypeScript
๋ณต์‚ฌ
โ€ข
code: ์š”์ฒญ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ Code๊ฐ’
โ€ข
message: ์š”์ฒญ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€
โ€ข
result: ์š”์ฒญ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ๊ฐ’

3. ๊ณตํ†ต Response Format ์ ์šฉ

supabase/functions/api/controllers/userController.ts
+import { ResponseCode } from "./../lib/response/responseCode.ts"; import { Context } from "https://deno.land/x/hono/mod.ts"; import { UserService } from "../services/userService.ts"; +import { createResponse } from "../lib/response/responseFormat.ts"; // UserController ํด๋ž˜์Šค๋Š” FCM ํ† ํฐ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ปจํŠธ๋กค๋Ÿฌ์ž…๋‹ˆ๋‹ค. export class UserController { @@ -17,7 +19,13 @@ export class UserController { // fcmToken์ด ์—†๋Š” ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. if (!fcmToken) { - return c.json("Missing userID or fcmToken"); + return c.json( + createResponse( + ResponseCode.INVALID_ARGUMENTS, + "Missing userID or fcmToken", + null, + ), + ); } // UserService๋ฅผ ํ†ตํ•ด FCM ํ† ํฐ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. @@ -25,7 +33,17 @@ export class UserController { // ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. return c.json( - result ? "FCM token added successfully" : "Failed to add FCM token", + result + ? createResponse( + ResponseCode.SUCCESS, + "FCM token added successfully", + null, + ) + : createResponse( + ResponseCode.SERVER_ERROR, + "Failed to add FCM token", + null, + ), ); } @@ -35,7 +53,9 @@ export class UserController { const tokens = await this.userService.getFCMTokensByUserID("mock_user_id"); // ํ† ํฐ ๋ชฉ๋ก์„ JSON ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. - return c.json(tokens); + return c.json( + createResponse(ResponseCode.SUCCESS, "Success", { fcmTokens: tokens }), + ); } // deleteFCMTokenV1 ๋ฉ”์„œ๋“œ๋Š” FCM ํ† ํฐ์„ ์‚ญ์ œํ•˜๋Š” API ์—”๋“œํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค. @@ -45,7 +65,13 @@ export class UserController { // fcmToken์ด ์—†๋Š” ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. if (!fcmToken) { - return c.json("Missing userID or fcmToken"); + return c.json( + createResponse( + ResponseCode.INVALID_ARGUMENTS, + "Missing userID or fcmToken", + null, + ), + ); } // UserService๋ฅผ ํ†ตํ•ด FCM ํ† ํฐ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. @@ -56,7 +82,17 @@ export class UserController { // ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. return c.json( - result ? "FCM token deleted successfully" : "Failed to delete FCM token", + result + ? createResponse( + ResponseCode.SUCCESS, + "FCM token deleted successfully", + null, + ) + : createResponse( + ResponseCode.SERVER_ERROR, + "Failed to delete FCM token", + null, + ), ); } }
Diff
๋ณต์‚ฌ
โ€ข
API Response๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„์—์„œ createResponseํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๊ณตํ†ต ํฌ๋งท์œผ๋กœ ๋ณ€๊ฒฝ

4. ๋ณ€๊ฒฝ๋œ API Response ํ™•์ธ

Postman์„ ํ™œ์šฉํ•ด ๋ณ€๊ฒฝ๋œ API Response๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

5. Public ๋ฐฐํฌ

bash deploy.sh
TypeScript
๋ณต์‚ฌ
public ๋ฐฐํฌ ํ›„ public API endpoint ํ…Œ์ŠคํŠธ๋„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ•์˜ ์ฝ”๋“œ

4
pull