-
Notifications
You must be signed in to change notification settings - Fork 2
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
[REFACTOR]전체 DI적용(#131) #132
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
추후, 새 코드가 문제 없으면 삭제
변경후 레이어가 문제없어서 기존 레이어 삭제합니다
ffalswo2
reviewed
Sep 27, 2023
Comment on lines
+10
to
+19
protocol BookmarkInOutService { | ||
func getBookmark() async throws -> BookmarkResponse? | ||
func postBookmark(model: BookmarkRequest) async throws -> BookmarkResponse? | ||
} | ||
|
||
final class BookmarkAPI: BookmarkAPIProtocol { | ||
protocol BookmarkOutService { | ||
func postBookmark(model: BookmarkRequest) async throws -> BookmarkResponse? | ||
} | ||
|
||
typealias BookmarkService = BookmarkInOutService & BookmarkOutService |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BookMark protocol을 in out으로 나눈게 계속 눈에 걸리네요
우선 in out을 나눴던게 해당 Service객체를 주입받는 Manager에서 필요한 메서드에만 접근하게 하기 위함이였고, Auth의 경우 in out이 그래도 직관적으로 플로우상 나뉘어졌다고 생각해서 괜찮았는데 이 프로토콜은 이유가 와닿지 않는데 어떤걸까용?.?
이게 아마 카톡에서 찬미랑 얘기했던 그건가 ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
[#131 ] REFACTOR : 네트워크레이어분리 및 Dependency Injection적용
🌱 작업한 내용
🌱 PR Point
🔥불편했던부분
todayViewController객체를 하나 생성하기 위해서 manager객체와 service객체를 매번 생성해서 넣어줘야하는 부분이 불편했습니다
splashviewcontroller의 경우에는 anauthorized error가 발생할 가능성이 존재하는 모든뷰에서 객체를 생성해줘야하는데 이런 경우에는 splashviewcontroller의 내부 네트워크 레이어의 변경이존재하면 모든 viewcontroller에서 변경을 해줘야하는 불편함이 존재합니다
DI를 적용하게되면 매번 객체 생성시 외부에서 필요한 객체를 생성해서 주입을 해줘야하기때문에 이런 문제에 직면할 수 있습니다
이런 부분을 해결할 수 있는 방법에 여러가지가 존재한다는걸알게 되었습니다
1. DI Container방식
DI를 적용할때 이런 부분을 해결하기 위한 대표적인 방식으로는 DI Conatiner가 있습니다
DI Conatainer은 기본적으로 key값을 가지고 어떤 객체를 등록해놓으면 resolve할때 key에 저장돠어있는 value인 완성된 객체를(여기서 완성된 객체라는건 의존성주입이 된 객체를 의미합니다) return받아서 사용할 수있게됩니다
해당 container객체를 singleton으로 만들어주고 scene delegate에서 app에서 사용할 모든 객체들을 register해주면 어떤 객체를 사용하고 싶을때 단순히 conatiner에 접근해서 key값을 가지고 resolve해주면 됩니다
2. Swinject라이브러리 사용
swinject라는라이브러리도 내부적으로 container방식으로 특정객체를 register하고 resolve할수있는 기능이 존재합니다
위의 방식처럼 custom으로 container를 만드는 경우 고려해야할 부분이 존재합니다
dictonary의 강한참조문제
container는 특정 객체의 주소를 dictionary에 저장해두기때문에 어떤 viewcontroller가 app상으로는 사라졌을지라도 dictionary가 강하게 참조하고 있기때문에 메모리에서 할당해제가 되지 않습니다
이 부분을 해결해주기 위해서 weak으로 선언해주면 dictionary에 들어가는 순간 viewcontroller객체를 참조하는 변수가 없기때문에 바로 할당해제가 되어 nil이 되게됩니다 이런경우 viewcontroller를 return받을 수 없게됩니다
swinject에서는 내부적인 reference count를 이용해 이런문제를 해결해 줍니다
3. Factory Pattern을 활용한 객체 생성
swinject의 경우 DI툴이라기 보다는 단순히 등록하고 등록된객체를를 return받는 service locator에 더 가깝다고 생각합니다
swinject를 사용하더라도 container자체가 singleton이 아니기때문에 container를 singleton으로 감싸는 wrapper객체를 따로 만들거나 scene delegate에서 만든 app에서 사용할 모든 객체를 register한 container를 매번 넘겨주면서 사용하는 방식이어야합니다
swinject는 분명 custom DI Container에서 발생할수있는 참조카운팅 문제를 해결해주는 로직을 가지고 있지만 단순히 객체를 생성해서 return해주는 역할자체는 design pattern인 factory pattern으로도 충분히 해결할 수 있다고 생각합니다
다만 factory pattern의 경우엔 매번 새로운 객체를 새로 생성해주지만 swinject의 경우 object scope를 통해서 return되는 객체를 매번 새로 생성해줄지 아니면 싱글톤처럼 공유되는 객체를 return해줄지를 선택할 수 있습니다
만약에 MVVM에서 viewmodel의 상태변화를 유지시킨채로 몇개의 viewcontroller에서 공유해야한다던가 한다면 swinject도 좋은 선택지가 될것같습니다
하지만 viewcontroller와 viewmodel이 1:1대응이며 api call을 통해 상태의 변화를 업데이트해야하는 앱의 경우(제 경우에는 100%이런경우였습니다) swinject를 단순히 service locator로 밖에 사용할 수가 없다고 생각합니다. 물론 단순 service locator로 사용하더라도 custom DI Container에 비해서는 확실한 메리트가 존재하지만 factory pattern과 비교했을때 외부라이브러리의 의존성을 감안하면서 사용해야할 이유가 없다고생각합니다
📮 관련 이슈