Skip to content

Conversation

tjrkdgnl
Copy link
Collaborator

@tjrkdgnl tjrkdgnl commented Oct 1, 2025

변경사항 요약

  • logger를 생성합니다. 앞으로 Log를 남기고 싶을 때는 logger를 주입받아서 사용하면 됩니다.
  • 모든 모듈에 buildVariant를 구분하도록 합니다.
  • 크래시리틱스를 추가했습니다.
  • google-services.json 파일이 필요할텐데 회의하며 관련 파일을 드리겠습니다

@tjrkdgnl tjrkdgnl self-assigned this Oct 1, 2025
@tjrkdgnl tjrkdgnl added the Chore This issue or pull request already exists label Oct 1, 2025
@tjrkdgnl tjrkdgnl changed the title Feature/logger [Feature] Logger 구현 Oct 1, 2025
Base automatically changed from chore/feature-plugin-생성 to develop October 4, 2025 06:31
Copy link
Collaborator

@dudwls901 dudwls901 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기존 시스템 로그를 완벽히 대체하려는 것으로 보이는데,
그렇다면 object로 진입점을 뚫어줘서 어디서든 접근가능하게 하는 게 편할 거 같은데 어때
로거를 매번 주입받아 사용해야 하는 건 좀 불편한 거 같아서

Comment on lines 63 to 71
override fun logAndToast(throwable: Throwable) {
e(throwable)

Toast.makeText(
context,
context.resources.getString(R.string.error_default_message),
Toast.LENGTH_SHORT
).show()
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5; 시스템 토스트 쓰려나 우리 커스텀 토스트 쓰는 거 같은데

@tjrkdgnl
Copy link
Collaborator Author

tjrkdgnl commented Oct 4, 2025

@dudwls901 logger를 주입받아 사용하려는 이유는 UI 통합 테스트 시, Singleton으로 인해 강하게 커플링이 걸려 테스트를 방해할 수 있기 때문이야. 대신에 DI를 사용하면 목킹하여 쉽게 대처할 수 있어, 커플링을 느슨하게 줄일 수 있어. 커플링을 계속 줄이기 위해서는 싱글톤 패턴들은 조금 지양하는게 좋을 것 같아서 DI를 사용하도록했어.

Logger.LogAndToast는 MainActivity에서 Logger를 주입해 모든 Root Composable의 Navigation에서 Logger.LogAndToast를 호출하는 람다를 통해 사용할 수 있도록 하면 좋을 것 같아.

반면 ViewModel에서 자주 inject해야할 것 같은데 이건 BaseViewModel 같은 것을 만들고 여기서 Logger를 주입해 사용하는 방법으로 한다면 매번 주입할 확률이 줄어드니 괜찮을 것 같은데 어때?

@tjrkdgnl tjrkdgnl requested a review from dudwls901 October 4, 2025 08:04
@dudwls901
Copy link
Collaborator

  1. 접근 용이성
  2. 테스트 용이성

두 가지가 있을 것 같은데
우선 접근 용이성은 feature layer는 형 말대로 하면 좀 쉽게 접근할 수 있을 것 같다.
근데 프로젝트 전역에서 쓰이는 로거이니 data layer에도 이런 쉬운 접근 방식을 고려해야 할듯. (BaseViewModel 의 예시처럼)
물론 logger는 기존 시스템 로거처럼 어디서나 바로 접근할 수 있어야한다는 관점에서 얘기한 것이긴 함, 모든 레이어에서 사용할 필요가 없다는 관점이면 지금 방식으로 충분할듯

테스트 용이성은 현재 DI 방식은 유지하고 object로 진입점만 열어두는 것을 생각했음!
이렇게 했을 때 logger는 여전히 쉽게 교체가능하다고 생각했는데
테스트에 방해되는 요소가 있으려나?

object AppLogger : Logger {

    private var delegate: Logger? = null

    fun init(logger: Logger) {
        delegate = logger
    }
    ...
}

//Application
    @Inject lateinit var logger: Logger

    override fun onCreate() {
        super.onCreate()
        AppLogger.init(logger)
    }

@tjrkdgnl
Copy link
Collaborator Author

tjrkdgnl commented Oct 4, 2025

좋네. 이렇게 하면 좀 더 유연하게 사용할 수 있겠어. 수정해놓을게. 대신에 웬만해서는 주입받아 써야하는게 약속이고 어쩔 수 없는 경우에 써야한다면 직접 접근하여 사용하는 것으로 이야기하면 좋을듯

@dudwls901
Copy link
Collaborator

dudwls901 commented Oct 4, 2025

'웬만해서는 주입받아 써야하는 게 약속'이라면 object 열어두지 말고 주입 받아서 사용만 하는 게 더 좋아보이긴해!
object든 Logger Interface든 하나 정해서 그것으로만 접근하도록 강제하는 게 좋다는 생각이야.

다만 아직 모르겠는 부분은 object를 열어두었음에도 왜 주입받아 써야하는지는 잘 모르겠어..!
로거를 사용하는 client측에서 로거를 갈아끼워야할 상황을 고려한 건가?

그래서, 결론은
object만 열어두거나
Interface만 열어두거나
둘 중 하나면 된다 생각했고,
설계상 문제될 게 없으면 시스템 로그와 접근도 비슷하고 좀 더 편리한 object를 제안해본 것이었삼!🥲

@tjrkdgnl
Copy link
Collaborator Author

tjrkdgnl commented Oct 4, 2025

  • 일단 Object로 열어두어야 하는 상황은 확장함수 같은 곳에서 어쩔 수 없이 접근해야하는 상황일 때 적용할 수 있겠단 생각이 들어서야.

  • Object로 만들었음에도 DI로 일반적으로 접근해야하는 이유는 UI가 단일 목표로만 갖는 클래스가 아니기 때문이야. 우리는 UI가 오직 화면에 데이터를 보여주는 목적만 갖는다면 Object로 직접 접근해서 사용하는 것이 큰 문제가 없어. 하지만 UI 통합 테스트의 목적도 갖고 있기 때문에 Object를 직접적으로 사용하는 패턴을 사용하면 매우 테스트하기가 어려운 상황이 발생해. 즉 UI를 그리는 목적도 존재하지만 테스트 목적도 존재하기에 결합도는 최대한 느슨하게 만들어야 해. (예로 Gson object를 직접 접근할 수 있지만 굳이 주입을 받아 사용하는 것처럼)
    반대로 Utils 클래스같은 경우 하나의 목표 값을 생성을 위해 또 다른 여러 Utils 클래스가 필요하다면 이것은 필요한 클래스들을 주입받는 것 보다 오히려 내부에서 직접 접근해 사용하는게 더 응집도가 높은 방법이겠지.(주입을 받는다는 것은 주입 받는 것에 따라 return 해야할 값이 달라질 수 있다는 이야기도 되니까.) 때문에 Utils 같은 클래스들은 직접 접근하는 게 더 옳지만 View 및 ViewModel같은 경우는 우리가 테스트를 위한 목적으로도 사용될 수 있기에 Logger는 특수한 상황을 제외하고선, 웬만하면 주입받아 사용해야 해. 꼭 UI가 아닌 Data layer 등에서 사용하더라도 위 논리는 그대로 적용돼

Copy link
Member

@MinseoSONG MinseoSONG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

흠 그럼 주입 받아서 쓰는 걸 원칙으로 하되, 예외 상황인 viewmodel이나 UI 그릴 때만 만들어둔 object를 쓰는 걸로 가는걸까요??
아니면 강휘오빠 말대로 주입받아서 쓰는게 기본 원칙이기 때문에 DI만 ..?

강휘오빠 넘 수고 많앗어용 .. 코드 보면서 또 공부 왕창 해가여.. 🥹

buildTypes {
release {
debug {
applicationIdSuffix = ".dev"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p3: 오 .. 처음 봤어요
이렇게 하면 릴리즈 앱이랑 디버그 앱을 같은 기기에 동시에 설치할 수 잇군요 .. ! 배워갑니더

@tjrkdgnl
Copy link
Collaborator Author

tjrkdgnl commented Oct 4, 2025

아니 웬만해서는 주입받아 써야하고 어쩔 수 없이 사용이 필요한 경우에만 쓰면 될 것 같아. 확장함수에서 사용이 필요하다던가.. 등등..? xml 기반일 때는 커스텀 뷰에서도 사용가능하고..근데 이러한 경우를 제외하곤 거의 직접적으로 object로 접근해서 쓰는 일은 없을 것 같네

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Chore This issue or pull request already exists
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants