티스토리 뷰

제네릭을 사용하면 코드의 중복을 제거할 수 있다는 장점이 있습니다. 같은 일을 하는 메소드가 parameter type이 달라서, return type이 달라서 중복 된 코드를 짜야한다면 불필요하게 파일이 길어지겠죠? 이번에 제네릭을 사용해보니까 네트워크 요청을 할 때 유용하게 사용할 수 있더라구요. 그래서 그 경험을 공유해보고자 합니다.

 

네트워크 통신을 하다보니 비슷한 로직을 가진 서버에 데이터를 요청하여 받아오면 모델에 맞게 decoding을 진행해서 필요에 따라 가공해서 사용하는게 일반적이죠? 예를 들어 Album, Artist, Playlist 모델이 있다면 func fetchAlbum( ), func fetchArtist( ), func fetchPlaylist( )라는 메소드를 통해 그 일련의 과정들을 거칠텐데, 아래와 비슷하게 생겼을 것 같아요.

func fetchAlbum(completion: @escaping (Result<Album, Error> -> ()) {
   network.requestData() { result in
      switch result {
         case .success(let data) :
            guard let requestForm = try? JSONDecoder().decode(Album.self, from: data) else {
               // decoding error 처리
               return
            }
            completion(.success(requestForm))
         case .failure(let error):
            compleion(.failure(error))
         }
      }
   }
}

func fetchArtist(completion: @escaping (Result<Artist, Error> -> ()) {
   // 같은 로직, decode(Artist.self, from: data)
}

func fetchPlaylist(completion: @escaping (Result<Playlist, Error> -> ()) {
   // 같은 로직, decode(Playlist.self, from: data)
}

 

메소드 내의 로직은 같고, 메소드 내에서 사용되는 model type이 상이한 경우기 때문에 제네릭을 적용해 볼 수 있습니다. 그래서 기존 코드는 아래와 같이 수정해볼 수 있고 사용할 때는 사용할 model type을 지정해주면 됩니다.

func fetchtData<T: Decodable>(completion: @escaping (Result<T, NetworkError>) -> ()) {
   endpoint.requestData(params: params) { result in
      switch result {
      case .success(let data):
         guard let requestForm = try? JSONDecoder().decode(T.self, from: data) else {
            completion(.failure(.decodingError))
            return
         }
         completion(.success(requestForm))
                
         case .failure(let error):
            completion(.failure(error))
         }
      }
}

// 사용할 때
NetworkManager.fetchData() { [weak self] (result: Result<SearchResult, NetworkError>) in
   guard let self = self else { return }
   switch result {
   case .success(let searchResult):
      // 받은 데이터로 처리
   case .failure(let error):
      // 에러 처리
   }
}

 

그런데 사용하다보니 조금 고민되는 부분이 있더라구요. 메소드 명이 같고, 파라미터나 리턴타입이 다른 경우를 오버로딩이라고 부르는데, 오버로딩을 해야하는 순간과 제네릭으로 묶는게 좋은 순간이 고민됐습니다. 중복 된 코드가 좋지 않다지만, '메소드를 사용할 때 개발자의 실수를 줄일 수 있다면 분명하게 정해진 메소드가 좋지 않나?'라는 생각이 들었습니다. 만약 메소드명이 불분명하여 오버로딩이 부적격하다면 메소드명을 구체적으로 짓고 중복 된 코드가 나쁜가 싶기도 했어요. 정해진 답이 없는 문제다 보니 포럼같은 곳들 돌아다니며 찬찬히 다른 사람들의 의견을 좀 읽어봐야겠어요!

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함