API 서버를 개발할 때
클라이언트와 원활한 소통을 위해
일관된 응답 구조 방식을 채택할 수 있다
API 엔드포인트에서
성공 여부와 에러를 전달할 때
일정한 포멧으로 응답을 주고 받으면
클라이언트에서 예측 가능한 처리가 가능하다
유틸 클래스의 필요성
API의 갯수가 많아질수록 동일한 형태의
성공 / 실패 응답을 자주 사용하게 될 가능성이 높다
이는 자연스래 중복된 코드로 이어지고
유지보수 또한 까다로워진다
동일한 엔드포인트에서
성공 / 실패 여부에 따른 응답을
위와 같이 설정할 수 있다
성공 시 응답 데이터
{
"result": true,
"errNum": null,
"data": {
"message": "Registration Success"
}
}
실패 시 응답 데이터
{
"result": false,
"errNum": 1001,
"data": {
"message": "Invalid Credentials"
}
}
이러한 응답 구조를 관리하기 위해
공통된 형태의 응답을 반환하는
유틸 클래스를 설계할 수 있다
BuzzTalkResult 유틸클래스
/*
* 성공 시 success 메소드
* 실패 시 resultError 메소드 에러 상태 코드(errNum)와 에러 메시지를 errorMsg 객체에 매핑
* 예기치 못한 오류 발생시 handleError 메소드 호출
*/
export class BuzzTalkResult {
private errorMessages: { [key: number]: string } = { // 에러 메시지를 상태 코드와 매핑
1000: 'Internal Server Error',
1001: 'Invalid Credentials',
1002: 'Player Not Found',
1003: 'Password Incorrect', // etc ......
};
response: { [key: string]: any } = {};
resultError(errNum: number): { [key: string]: any } {
// 에러 메시지가 없으면 'Unknown Error' 반환
const message = this.errorMessages[errNum] || 'Unknown Error';
return this.result(false, errNum, { message });
}
success(data: any): { [key: string]: any } {
return this.result(true, null, data);
}
result(chk: boolean, errNum: number | null, data: any): { [key: string]: any } {
const map: { [key: string]: any } = {};
map['result'] = chk;
map['errNum'] = errNum; // 오직 에러 메세지 기반 응답 처리 방지
map['data'] = data;
return map;
}
handleError(e: any): { [key: string]: any } {
console.error('Error occurred:', e);
return this.resultError(20); // 기본적으로 1000번 코드로 처리 (Internal Server Error)
}
}
유틸클래스를 위와 같이 설계하였을 경우
API에서는 아래와 같이 활용 가능하다
회원가입 API
@Controller('/player')
export class PlayerController {
constructor(
private readonly playerService: PlayerService,
private readonly buzzTalkResult: BuzzTalkResult
) {}
@Post('/register')
async register(@Body() body): Promise<any> {
try {
const playerId = body.playerId;
const password = body.password;
const statusCode = await this.playerService.register(playerId, password);
if (statusCode === 0) {
return this.buzzTalkResult.success({ message: 'Registration Success' });
}
return this.buzzTalkResult.resultError(statusCode); // 실패 응답 처리
} catch (e) {
return this.buzzTalkResult.handleError(e); // 예외 발생 시 처리
}
}
}
유틸 클래스의 단점
유연성 부족
모든 API가 동일한 응답으로
처리하도록 설계되어있기 때문에
특정 API에서 더 복잡하거나
특정 응답 구조가 필요할 경우 제한적이다
클래스 비대화
다양한 타입의 응답 처리가 필요할 경우
(ex: 파일 다운로드 링크)
클래스가 계속 확장하며 관리가 어려워질 수 있다
728x90
반응형
'Web Technologies 🖥️ > etc' 카테고리의 다른 글
API 명세서 자동화 - swagger (feat. express.js) (0) | 2024.10.10 |
---|