[ASP.NET Core] SPA NetCore - API 결과 리턴 공통화 1.0
전편에서 했던 "API 결과 리턴 공통화"는 좀 급하게 만들다 보니 빠진 것이 있는데......
가장 중요하다고 할 수 있는 '결과 처리 클래스'가 공통화가 덜돼서 최종 결과를 출력하는 'ApiResultReady.ToResult()'를 호출할 때 출력할 객체를 따로 지정해야 했습니다.
이번엔 이 불편함을 고쳐봅시다.
1. 'ApiResultBaseModel' 수정
'ApiResultBaseModel'으로 옮여야 합니다.
성공 문자를 저장해두고 이것과 비교하는 함수를 추가합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | /// <summary> /// API 결과 공통 베이스. /// </summary> public class ApiResultBaseModel { /// <summary> /// 실패시 전달한 코드 /// 0 : 성공. /// 다른 값은 모두 실패 /// </summary> public string InfoCode { get; set; } /// <summary> /// 전달할 메시지 /// </summary> public string Message { get; set; } /// <summary> /// 성공했을때 문자 /// </summary> private string SuccessString; /// <summary> /// 기본 생성. /// InfoCode가 "0"로 초기화됨 /// </summary> public ApiResultBaseModel() { this.SuccessString = ApiResultType.None.GetHashCode().ToString(); this.Reset(); } /// <summary> /// 인포코드와 메시지를 넣고 생성 /// </summary> /// <param name="sInfoCode"></param> /// <param name="sMessage"></param> public ApiResultBaseModel(string sInfoCode, string sMessage) { this.SuccessString = ApiResultType.None.GetHashCode().ToString(); this.InfoCode = sInfoCode; this.Message = sMessage; } /// <summary> /// 성공으로 초기화한다. /// </summary> public void Reset() { this.InfoCode = this.SuccessString; this.Message = string.Empty; } /// <summary> /// 타입 세팅 /// </summary> /// <param name="typeApiResult"></param> public void TypeSet(ApiResultType typeApiResult) { this.InfoCode = typeApiResult.GetHashCode().ToString(); } /// <summary> /// InfoCode값이 성공값인지 여부 /// </summary> /// <returns></returns> public bool IsSuccess() { bool bReturn = false; if(this.InfoCode == this.SuccessString) {//성공문자열이다. bReturn = true; } return bReturn; } } | cs |
20번 라인 : 생성자에서 여기다 성공했을 때 사용할 문자열을 초기화해줍니다.
49번 라인 : 초기 상태로 초기화해줍니다.
68번 라인 : 'InfoCode'값이 성공 문자열과 같은지 여부를 리턴합니다.
이 함수를 통해 지금 가지고 있는 'ApiResultBaseModel'의 내용을 판단합니다.
2. 'ApiResultReady' 수정
전편에서 만든 'ApiResultReady'를 좀 수정해야 합니다.
2-1. 스테이터스 코드 제거
전 버전에서는 '스테이터스 코드'를 사용했는데....
써보니까 이게 많이 불편합니다 ㅎㅎㅎ
어차피 서버에서 예상할 수 없는 오류는 결국 '500' 뿐이고
그렇다면 결국 값을 가지고 있는 건 의미가 없습니다.
결국 성공과 실패를 전달해주면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 | /// <summary> /// 스테이터스 코드 /// </summary> 제거 -> public int StatusCode { get; set; } /// <summary> /// 성공 여부. /// 알수 없는 에러가 났을때 처리하기위한 용도. /// 알수 있는 에러는 이값을을 true로 해둔다. /// </summary> public bool Success { get; set; } | cs |
이 값은 에러 났는지 여부만 가지고 있으면 됩니다.
이 값이 참(True)이고 'InfoCode'값이 "0"이면 성공한 것으로 취급하게 됩니다.
2-1-1. 'InfoCode'를 판단하는 함수
'ApiResultBaseModel'의 'IsSuccess'함수를 호출하는 함수를 만들어 줍니다.
1 2 3 4 5 6 7 8 | /// <summary> /// InfoCode값이 성공값인지 여부 /// </summary> /// <returns></returns> public bool IsSuccess() { return this.ResultObject.IsSuccess(); } | cs |
2-2. 인스턴스 저장용 변수
전 버전은 사용할 오브젝트를 마지막에 받아서 사용했습니다.
그러다 보니 'ApiResultReady'가 가지고 있는 변수와 혼동될 때가 있었습니다.
그래서 'ApiResultBaseModel'를 상속받는 인스턴스를 저장해둘 변수가 필요해졌습니다.
1 2 3 4 | /// <summary> /// 전달받은 결과 오브젝트 /// </summary> public ApiResultBaseModel ResultObject { get; set; } | cs |
이제 'ApiResultBaseModel'를 상속받은 인스턴스를 만들었으면 바로 이 변수에 할당하면 됩니다.
예를 들면 아래와 같이 사용합니다.
1 2 3 4 5 | //리턴 보조 ApiResultReady rrResult = new ApiResultReady(this); //리턴용 모델 TestModel01 armResult = new TestModel01(); rrResult.ResultObject = armResult; | cs |
생성자에서 'ResultObject'를 'ApiResultBaseModel'로 초기화해주므로 (요 다음에 코드 있음)
'ResultObject'를 초기화하지 않으면 'ApiResultBaseModel'를 사용하게 됩니다.
이렇게 되면 'armResult'는 형 변환 없이 사용 가능하고
'ApiResultBaseModel'의 변수인 'InfoCode'와 'Message'는
'rrResult'와 'armResult'에서 공유하게 됩니다.
2-3. 'InfoCode', 'Message' 변경
'InfoCode'를 속성으로 바꾸고 get/set을 아래와 같이 작성합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /// <summary> /// 실패시 전달한 코드 /// 0 : 성공. /// 다른 값은 모두 실패 /// </summary> 제거 -> public string InfoCode { get; set; } /// <summary> /// 실패시 전달한 코드 /// 0 : 성공. /// 다른 값은 모두 실패 /// </summary> public string InfoCode { get { return this.ResultObject.InfoCode; } set { this.ResultObject.InfoCode = value; } } | cs |
'Message'를 속성으로 바꾸고 get/set를 비슷하게 작성합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /// <summary> /// 전달할 메시지 /// </summary> public string Message { get { return this.ResultObject.Message; } set { this.ResultObject.Message = value; } } | cs |
2-4. 'ToResult' 수정
기존 'ToResult'는 'ResultObject'를 이용하도록 수정합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | /// <summary> /// API끝에서 호출한다. /// ApiResult를 생성하여 리턴해 준다. /// </summary> /// <returns></returns> public ObjectResult ToResult() { return this.ToResult(this.ResultObject); } /// <summary> /// API끝에서 호출하여 'ObjectResult'를 생성하여 리턴해 준다. /// 만들어지는 결과의 ApiResultBaseModel데이터는 this 기준이다. /// </summary> /// <param name="objResultData">전달할 모델</param> /// <returns></returns> public ObjectResult ToResult(object objResultData) { ObjectResult orReturn = null; if (null == objResultData) {//오브젝트가 없다. //없으면 가지고 있는 오브젝트를 자동으로 사용한다. objResultData = this.ResultObject; } if (this.Success == true) {//성공 //성공은 전달받은 오브젝트를 준다, orReturn = this.ThisCB.StatusCode(StatusCodes.Status200OK, objResultData); } else {//실패 //실패는 500 에러를 기본으로 전달해야 한다. ApiResultFailModel afm = new ApiResultFailModel( ((ApiResultBaseModel)objResultData).InfoCode , ((ApiResultBaseModel)objResultData).Message); //여기에 들어왔다는건 예측 가능한 오류가 났다는 의미다. //예측가능한 오류는 200으로 바꿔준다. orReturn = this.ThisCB.StatusCode(StatusCodes.Status200OK, afm); //여기서 예측가능한 오류를 200으로 바꾸지 않으려면 이 코드를 사용한다. //orReturn = this.ThisCB.StatusCode(this.StatusCode, afm); } return orReturn; } | cs |
3. 사용하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | [HttpGet] public ActionResult<TestModel01> Test01(int nData, string sData) { //리턴 보조 ApiResultReady rrResult = new ApiResultReady(this); //리턴용 모델 TestModel01 armResult = new TestModel01(); rrResult.ResultObject = armResult; if (0 <= nData) {//양수다. armResult.nTest = nData; armResult.sTest = sData; } if (false == rrResult.IsSuccess()) { rrResult.InfoCode = "1"; rrResult.Message = "'nData'에 음수가 입력되었습니다."; } return rrResult.ToResult(armResult); } | cs |
5번 라인 : 위에서 수정한 'ApiResultReady'의 인스턴스를 생성합니다.
7번 라인 : 이 API에서 사용할 모델의 인스턴스를 생성합니다.
'ApiResultReady'에 바로 생성해서 넣을 수 있긴 합니다.
문제는 그렇게 되면 매번 형 변환을 해서 사용해야 한다는 것이죠.
8번 라인 : 'ApiResultReady'에 7번 라인에서 생성한 모델을 전달합니다.
이제 'rrResult.IsSuccess()'를 호출하여 리턴용 모델이 성공상태인지 확인합니다.
'ApiResultBaseModel'속성에 접근할 때는
'rrResult'나 'TestModel01'중 어느 쪽에 접근하여도 같은 개체를 사용하게 됩니다.
22번 라인 : 결과를 API 결과 모델로 변환하여 전달하고 있습니다.
에 생성한 'armResult'를 전달합니다.
'ToResult'를 호출할 때 인스턴스를 전달하지 않으면 가지고 있는 인스턴스를 리턴합니다.
인스턴스를 전달하면 전달받은 인스턴스를 기준으로 작업하여 리턴합니다.