Haram 개발회고 Cache-Control

이건준·2023년 11월 1일
0

문제설명

  • 게시글, 홈 화면 등등 일부 화면에서 데이터를 받아와 UI에 바인딩시킬때 상대적으로 느리게 받아와지는 느낌이 들었다

  • 기존에 나와있는 개발상황은 거의 진행되었으나 해당 프로젝트를 어떻게 개선시킬 수 있을지 고민해보는 시간을 가졌다

APIService 기존 코드

switch statusCode {
	case 200..<300:
    	if decodedData.data != nil {
        	return observer(.success(.success(decodedData.data!)))
        }
        return observer(.success(.success(EmptyModel() as! T)))
    case 400..<500:
    	return observer(.failure(HaramError.requestError))
    case 500..<600:
    	return observer(.failure(HaramError.serverError))
    default:
    	return observer(.failure(HaramError.unknownedError))
}
  • 기존 API를 호출하는 코드의 일부이다, 해당 reuest함수의 리턴값으로는 일반적으로 네트워크 호출에 대한 결과만을 반환하기위해서 Single을 이용하였고 Single의 Element로 Observable<Result<T, HaramError>>타입을 가지게 개발하였다

  • 허나 이러한 리턴타입으로 인해 위 코드에서처럼 하나의 리턴을 던져줌에도 뎁스가 깊어보이고 불필요하다는 생각이 들었다

  • 또한 API호출에 대한 오류에 따른 동작을 구현해주어야했는데 이와같은 리턴값은 onNext를 통한 일반적으로 성공적으로 값을 반환하는 경우에도 성공과 실패에 따른 불필요한 로직을 추가한다는 문제가 인지되었다

APIService 개선코드

switch statusCode {
	case 200..<300:
    	if decodedData.data != nil {
       		 return observer.onNext(.success(decodedData.data!))
        }
        return observer.onNext(.success(EmptyModel() as! T))
    case 400..<500:
    	return observer.onNext(.failure(HaramError.requestError))
    case 500..<600:
    	return observer.onNext(.failure(HaramError.serverError))
    default:
    	return observer.onNext(.failure(HaramError.unknownedError)
}
  • 나는 이와같은 문제를 그냥 리턴타입을 Single타입으로 던져주었다, 이렇게 코드를 개선하니 확실히 눈에 띄게 코드가 줄어들었고 성공과 실패에 대한 의미가 구분지어줄 수 있었다

  • 또한 API를 통해 값을 받아올 때 특정 에러에 대한 로직처리를 할때 공통적으로 compactMap을 통한 결과값이 nil값을 받는지에 대한 코드를 줄일 수 있었다

  • viewModel에서 subscribe를 통해 값을 받아올때에도 onSuccess, onFailure를 이용해 확실히 오류인지 아닌지에 대한 처리를 쉽게 이해할 수 있었다

APIService에 Cache-control 적용시키기

  • 다양한 레퍼런스를 통해 찾아본 결과 swift의 URLSession은 기본적으로 캐시를 이용해 값을 캐시화시키고 기존 값과 크게 다를바가 없다면 이처럼 데이터를 캐시화하는것은 매우 유용한 로직일 것이다

  • 하지만 실시간으로 값이 천차만별로 변하고 호출할때마다 새로운 데이터를 받아와야하는 경우에는 이같은 캐시화는 무의미한 리소스를 낭비하는 것이며 최신화된 데이터를 사용자로 하여금 받아지는것이 힘들어질 것이다

  • 위와 같은 문제를 해결할 수 있는 것이 Cache-control이라 하는 헤더값을 통해 해당 API는 캐시화시키지말아줘라고하는 부분을 추가할 필요가 있음을 깨달았다

URLRequest의 헤더값에 Cache-control 추가하는 방법

case .noCache:
      // 토큰이 존재하지 않는 경우 default 리턴
      guard let token = UserManager.shared.accessToken else {
        return HeaderType.default.toHTTPHeader
      }

      // default 헤더 값에 `Authorization token` 및 `Content-Type` 추가
      var defaultHeaders = HTTPHeaders.default
      defaultHeaders.add(.authorization(bearerToken: token))
      defaultHeaders.add(.contentType("application/json"))
      defaultHeaders.add(name: "Cache-Control", value: "no-store")
      return defaultHeaders
    }

* Cache-control을 적용시킬 수 있는 방법으로 위 코드에서철 ㅁ헤더값의 Cache-control의 value값을 no-store을 넣어주는 방법이 있을 수 있다

> 다른 방법으로는 URLSessionConfiguration을 이용하여 캐시화시키지않음을 언급하는 방법 또한 존재한다

Entity 프로토콜 채택 개선

  • URL의 body값으로 인코딩한 값을 넣는 역할만을 하는 Entity이든 API호출을 통해 받은 응답값을 디코딩하기위한 Entity 또한 모두 Codable을 채택하고 있었다

  • Codable프로토콜은 Encodable & Decodable 프로토콜 2개를 채택하기에 하나의 역할만을 하는 Entity에 Codable을 채택하는것은 불필요하다 생각하여 이를 역할에 맞게 프로토콜을 채택해주었다

0개의 댓글