네트워킹 세팅 시 공통적으로 사용되는 베이스 리스폰스를 지정해주었습니다.
import Foundation
struct BaseResponse <T: Decodable>: Decodable {
let code: String
let message: String
let data: T?
}
하지만 일부 API에서 요청은 200으로 잘 되는데, 디코딩에러가 발생했습니다.
문제 상황은 다음과 같았습니다.
{
"code": "s2040",
"message": "요청이 성공했습니다."
}
PATCH api에서는 서버에서 설정한 리스폰스에 data가 오지 않았습니다.
베이스 리스폰스에는 data가 있는데, 리스폰스에는 data가 nil로 오는 것도 아니고 아예 오지 않았기 때문에 디코딩 에러가 발생했던 것입니다.
이런 경우 해결방법은 2가지가 있는데요.
- 서버에서 data를 nil로 내려달라고 한다.
- 클라이언트 측에서 분기처리를 해준다.
저는 2번의 방법으로 해결했습니다.
struct VoidType: Decodable {}
final class SubTaskPatchService {
let shared = BaseService.shared
func patchSubTask(id: Int, request: SubTaskPatchRequest) async throws -> VoidType {
do {
let response: VoidType = try await shared.request(
endPoint: .patchSubTasks(id),
body: request
)
return response
} catch {
throw error
}
}
}
리스폰스 data 타입을 빈 구조체인 VoidType으로 설정해줍니다. 베이스 리스폰스에서 data를 T라는 제네릭타입으로 지정해주었습니다. 그래서 이 data의 타입을 빈 구조체로 지정해주는 것입니다!
do {
print("type\(Response.self)")
let decoded = try JSONDecoder().decode(BaseResponse<Response>.self, from: data)
print("디코딩된 데이터는요: ", decoded)
if Response.self == VoidType.self {
let successCodes = ["s2000", "s2010", "s2040"]
guard successCodes.contains(decoded.code) else {
throw NetworkError.serverErrorMessage(decoded.message)
}
return (VoidType() as? Response) ?? {
fatalError("VoidType을 Response로 변환할 수 없습니다.")
}()
}
guard let data = decoded.data else {
throw NetworkError.noData
}
let successCodes = ["s2000", "s2010", "s2040"]
guard successCodes.contains(decoded.code) else {
throw NetworkError.serverErrorMessage(decoded.message)
}
return data
}
그리고 리스폰스를 디코딩해주는 함수에서 data가 Void Type인 경우를 미리 분기처리해줍니다.

그러면 성공적으로 디코딩에러가 해결되는 것을 확인할 수 있습니다.
이정도면 트슈도 운명아닐까요 저도 이런 일이 있었는데요 운명적