Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DI 관련 트러블 슈팅 - 1 #6

Open
Brandnew-one opened this issue Apr 4, 2023 · 0 comments
Open

DI 관련 트러블 슈팅 - 1 #6

Brandnew-one opened this issue Apr 4, 2023 · 0 comments
Assignees
Labels
help wanted Extra attention is needed

Comments

@Brandnew-one
Copy link
Owner

DI중 만난 문제

깃헙 레포에 올린 아주 작은 토이 프로젝트에서는 미처 생각하지 못했었는데 회사 프로젝트에 적용하면서 생각 해볼만한 문제를 마주쳤다.

1) Usecase의 중복 init

final class DefaultSearchMediaUseCase: SearchMediaUseCase {
  private let mediaRepository: MediaRepository
  private let mediaDetailRepository: MediaDetailRepository

  init(
    mediaRepository: MediaRepository,
    mediaDetailRepository: MediaDetailRepository
  ) {
    self.mediaRepository = mediaRepository
    self.mediaDetailRepository = mediaDetailRepository
  }
...
}
final class ~~ViewModel {
	private let usecase: SearchMediaUsecase

	init(
		usecase: SearchMediaUsecase
	) {
		self.usecase = usecase
	}
}

여러 viewModel을 만들다 보면 중복되는 usecase가 생긴다.

usecase에 Datatorage를 포함하고 있는 Repository가 있는 경우, Realm이 여러번 init 되는 문제가 발생한다

Realm 공식 홈페이지에서 zero-copy design으로 db의 변경 내용이 동일한 데이터를 가리키는 모든 객체에 반영된다는 내용을 확인해 런타임 중 문제가 발생하지는 않았지만, 어차피 동일한 DataStorage를 가리키는 usecase가 서로 다른 viewModel이 만들어질 때마다 새롭게 만들어질 필요가 있을까? 하는 의문이 들었다.

import Foundation

final class AppDI: AppDIInterface {
  private let mediaUsecase: SearchMediaUseCase = DefaultSearchMediaUseCase(
    mediaRepository: MediaRepositoryImpl(),
    mediaDetailRepository: MediaDetailRepositoryImpl(RealmDataStorage.shared)
  )

  func mediaDetailViewModel(
    _ media: Media
  ) -> MediaDetailViewModel {
    return MediaDetailViewModel(
      media: media,
      usecase: mediaUsecase
    )
  }
}

기존에 메서드를 통해서 usecsae를 만들던 형태에서 AppDI의 프로퍼티에 usecase를 가지고 있도록 설정했다.

하지만 AppDI는 앱이 시작하는 시점에 Init되는데 그럼 유저가 모든 화면을 돌아다니지 않아서 메모리에 올라와 있을 필요가 없는 usecase도 시작하는 시점에 모두 메모리에 올라가는 문제가 발생한다.

import Foundation

final class AppDI: AppDIInterface {
  private lazy var mediaUsecase: SearchMediaUseCase = {
    let mediaRepository: MediaRepository = MediaRepositoryImpl()
    let mediaDetailRepository: MediaDetailRepository = MediaDetailRepositoryImpl(RealmDataStorage.shared)
    return DefaultSearchMediaUseCase(
      mediaRepository: mediaRepository,
      mediaDetailRepository: mediaDetailRepository
    )
  }()

  func mediaDetailViewModel(
    _ media: Media
  ) -> MediaDetailViewModel {
    return MediaDetailViewModel(
      media: media,
      usecase: mediaUsecase
    )
  }
}

위의 문제를 해결하기 위해서 usecase를 lazy를 통해서 사용되는 시점에 메모리에 올라가도록 설정했다.

물론, 유저가 모든 화면을 돌아다니면 현재 당장 필요없는 usecase가 메모리에 올라가는 문제는 피할 수 없겠지만 앱이 시작하는 시점에 불필요한 메모리 사용은 막을 수 있다.

(더 좋은 아이디어가 떠오르면 추가하도록 하겠습니다.)

@Brandnew-one Brandnew-one added the help wanted Extra attention is needed label Apr 4, 2023
@Brandnew-one Brandnew-one self-assigned this Apr 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant