[iOS/Swift] 디코딩 에러 / 서버에서 데이터를 내려주지 않을 때

2na·2025년 5월 26일

Swift 🍎

목록 보기
6/9

네트워킹 세팅 시 공통적으로 사용되는 베이스 리스폰스를 지정해주었습니다.

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가지가 있는데요.

  1. 서버에서 data를 nil로 내려달라고 한다.
  2. 클라이언트 측에서 분기처리를 해준다.

저는 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인 경우를 미리 분기처리해줍니다.

그러면 성공적으로 디코딩에러가 해결되는 것을 확인할 수 있습니다.

관련 PR 링크

profile
Studying Frontend 👩🏻‍💻

2개의 댓글

comment-user-thumbnail
2025년 5월 27일

이정도면 트슈도 운명아닐까요 저도 이런 일이 있었는데요 운명적

답글 달기
comment-user-thumbnail
2025년 5월 27일

저희는 그래서 서버쌤들한테 바디에 nil 넣어 주세요 😹😹😹😹😹 로 해결했네여

답글 달기