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

[ADD] 개발자 모드 추가 #290

Merged
merged 15 commits into from
Dec 20, 2023
Merged

Conversation

dongx0915
Copy link
Member

@dongx0915 dongx0915 commented Dec 10, 2023

📌 개요

✨ 작업 내용

  • 개발자 모드 추가
  • 사용자 정보(토큰), 기기 정보, 화면 정보 등만 추가 해두었습니다. (추가할 만한 정보들이 있다면 추천 부탁드립니다~!)
    + 서버 모드 변경 기능 추가
  • 디버그 모드에서만 보이도록 설정 하였습니다.
  • 릴리즈 모드에서는 코드 조차 노출되지 않도록 debug 패키지로 분리 해두었습니다.

✨ PR 포인트

  • scheme을 통해 Activity를 여는 방식과 Fragment만 선언해서 일반 Fragment를 여는 방식이 있는데, 어떤 부분이 더 좋을 지 의견 부탁드립니다.

  • scheme으로 Activity를 여는 방식이 신기해서 공유 드릴겸 일단 해당 방법으로 구현해두었습니다~!
    + 갤럭시 쓰는 분들이라면 개발자 모드 내의 정보들이 정확하게 나오는 지 확인 한 번씩만 부탁 드립니다

  • ApiMode 클래스나 Application 클래스 내의 getBaseUrl() 등은 어디에 위치하면 좋을 지도 의견 부탁드립니다.

📸 스크린샷/동영상

릴리즈 모드 디버그 모드 개발자 모드 화면
image image image

@dongx0915 dongx0915 added ADD ➕ feat 이외의 부수적인 코드, 파일, 라이브러리 추가 동현 🐨 동현 담당 labels Dec 10, 2023
@dongx0915 dongx0915 self-assigned this Dec 10, 2023
@dongx0915 dongx0915 removed the request for review from Larry7939 December 10, 2023 04:59
Copy link
Member

@leeeha leeeha left a comment

Choose a reason for hiding this comment

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

개발자 모드 설정 방법에 대해 알아갑니다!! 수고하셨어요 👍👍

app/build.gradle Outdated

packagingOptions {
exclude 'AndroidManifest.xml'
}
Copy link
Member

Choose a reason for hiding this comment

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

오호.. 이건 왜 설정해야 하는지 알 수 있을까요?!

Copy link
Member

Choose a reason for hiding this comment

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

릴리즈 모드일 때는 디버그 모드 매니페스트 파일이 적용되면 안 돼서 그런 건가요??

Copy link
Member Author

Choose a reason for hiding this comment

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

넵 AndroidManifest.xml이 2개가 되어서 추가한 옵션인데, 지금 해보니 해당 옵션이 없어도 잘 빌드가 되네요

혹시 해당 옵션 없을 때 release/debug 모드 각각에서 빌드 잘 되는지 확인 가능할까요??


<data
android:host="devmode"
android:scheme="runnect" />
Copy link
Member

Choose a reason for hiding this comment

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

오호 새로운 방식 배워갑니다!!

private val DEF_PACKAGE = "android"
private val CLIPBOARD_LABEL = "keyword"
private val STATUS_BAR_HEIGHT = "status_bar_height"
private val NAVIGATION_BAR_HEIGHT = "navigation_bar_height"
Copy link
Member

Choose a reason for hiding this comment

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

이런 경고가 뜨고 있는데 변하지 않는 상수 문자열이라면, companion object 안에 const로 선언해주는 게 어떨까요??

Copy link
Member Author

Choose a reason for hiding this comment

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

해당 부분 회사에서도 피드백 받았었는데, 특정 액티비티 내에서만 사용될 상수라면 companion object에 올리는게 더 비효율적이라는 의견이었습니다.

공유 될 필요가 없는데, 정적으로 할당하는게 메모리 낭비라고 보는 것 같아요!
더 좋은 의견 있으면 공유 부탁드립니다~!

Copy link
Member

Choose a reason for hiding this comment

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

어제 회의에서 논의한 대로 상수는 companion object에서 정의하는 걸로 해요! :)
저희 프로젝트보다 규모가 훨씬 큰 회사에서는 이런 디테일한 부분에서도 메모리 관리가 중요하다는 걸 배울 수 있었네요! 코멘트 감사합니다 🫡


private val clipboardManager: ClipboardManager? by lazy {
context?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
}
Copy link
Member

Choose a reason for hiding this comment

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

? 이용해서 nullable 타입으로 처리를 꼼꼼하게 해주셨네요!
타입 캐스팅이 불가능하다는 런타임 에러를 방지할 수 있어서 좋은 거 같아요 👍

}

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences_developer_menu, rootKey)
Copy link
Member

Choose a reason for hiding this comment

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

PreferenceFragmentCompat 사용해본 적이 별로 없었는데 편리하네요 👍
앱을 꺼도 데이터가 유지되어야 하는 설정 화면에서 보통 많이 사용하는 거 같아요!

Copy link
Member Author

Choose a reason for hiding this comment

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

무엇보다 간단하게 레이아웃을 구성할 수 있어서 좋은 것 같습니다!
관리하기도 매우 편한 것 같네요

android:background="@color/white"
tools:context=".developer.RunnectDeveloperActivity">

<fragment
Copy link
Member

Choose a reason for hiding this comment

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

매우 간단한 화면이긴 하지만, fragment 태그 대신에 FragmentContainerView 를 사용하는 게 어떨까요??

Copy link
Contributor

Choose a reason for hiding this comment

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

@leeeha 특별한 이유가 있나요?!

Copy link
Member Author

Choose a reason for hiding this comment

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

https://charlezz.medium.com/%ED%94%84%EB%A0%88%EA%B7%B8%EB%A8%BC%ED%8A%B8-%EC%A0%84%EC%9A%A9-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-fragmentcontainerview-570911b1bbb0

여기에 간단하게나마 잘 정리되어 있는 것 같네요!
FragmentContainerView로 수정하도록 하겠습니다~!


private fun copyToText(text: String): Boolean {
val clipData = ClipData.newPlainText(CLIPBOARD_LABEL, text)
clipboardManager?.setPrimaryClip(clipData)
Copy link
Member

Choose a reason for hiding this comment

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

클립보드에 복사하는 방법 배워갑니다~!

Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(DEV_MODE_SCHEME)
}.let(this::startActivity)
}
Copy link
Member

Choose a reason for hiding this comment

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

오.. this::startActivity 이렇게 함수 호출하는 방식은 가끔 봤었는데, 코드 가독성이 좀 더 올라간다는 것 외에 또 다른 장점이 있을까요?? 단점도 혹시 있다면 알고 싶네요!

Copy link
Member Author

Choose a reason for hiding this comment

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

가독성 외에는 큰 장점은 없습니다!
약간의 단점이라면 리플렉션이라 성능이 떨어지는데, 아주 미미한 수준이라 신경 쓸 정도는 아니라고 하네요!

Copy link
Member

Choose a reason for hiding this comment

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

apply, let 같은 스코프 함수를 활용하여 보다 코틀린스럽게 코드를 짜시는 거 같네요! 배워갑니다! :)

return if (resourceId > 0) {
resources.getDimensionPixelSize(resourceId)
} else 0
}
Copy link
Member

Choose a reason for hiding this comment

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

SuppressLint 어노테이션을 붙이지 않고 구현할 수 있는 방법은 없을까요?!

Copy link
Member Author

Choose a reason for hiding this comment

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

굿굿 경고 안뜨는 방법이 있었네요👍 수정했습니다

}

private fun initDisplayInfo() {
val metrics = activity?.resources?.displayMetrics ?: return
Copy link
Member

Choose a reason for hiding this comment

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

널처리 굿!


activity?.finishAffinity() //루트액티비티 종료
exitProcess(0)
}
Copy link
Member

Choose a reason for hiding this comment

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

앱을 강제로 종료시키는 코드는 이렇게 작성해볼 수 있군요! finishAffinity 라는 함수는 처음 보네요 👀

android:key="dev_pref_key_api_mode"
android:title="서버 모드 설정"
app:iconSpaceReserved="false" />
</PreferenceCategory>
Copy link
Member

Choose a reason for hiding this comment

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

레이아웃 코드를 간결하게 구성할 수 있어서 좋네요 👍

Copy link
Contributor

@unam98 unam98 left a comment

Choose a reason for hiding this comment

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

갤럭시에서 잘 돌아갑니다~! 많이 배워갑니당 굿굿

Comment on lines +34 to +36
const val API_MODE = "API_MODE"

fun getBaseUrl(): String {
Copy link
Contributor

Choose a reason for hiding this comment

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

pr 포인트 보고 고민을 해봤는데 처음엔 옮긴다면 getBaseUrl()이 직접적으로 쓰이는 RetrofitModule로 옮겨볼 수 있겠다고 생각했습니다. 그런데 retrofit은 싱글톤으로 생성되고 앱을 사용되는 동안 수시로 쓰일 테니, 즉 retrofit 객체도 ApplicationcCass와 같이 객체가 계속 살아있을 테니 결과적으로 ApplicationClass 안에 두는 거나 RetrofitModule 안에 두는 거나 큰 차이 없겠단 생각이 들었습니다.

Copy link
Member Author

Choose a reason for hiding this comment

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

initApiMode()에서 PreferenceManager에 접근해야해서 getBaseUrl()도 같이 Application 쪽에 넣어 뒀는데 나중에 멀티 모듈로 바꾸게 된다면 공통 모듈로 분리해야할 것 같습니다.

이 부분은 좀 더 찾아볼게요~ 현재는 유지해도 될 것 같습니다

android:background="@color/white"
tools:context=".developer.RunnectDeveloperActivity">

<fragment
Copy link
Contributor

Choose a reason for hiding this comment

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

@leeeha 특별한 이유가 있나요?!

JAVA;

companion object {
private fun asValue(mode: String): ApiMode = when(mode.uppercase()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

uppercase() 꼼꼼하시네요!

@@ -70,5 +89,6 @@ class MySettingFragment : BindingFragment<FragmentMySettingBinding>(R.layout.fra
"https://docs.google.com/forms/d/e/1FAIpQLSek2rkClKfGaz1zwTEHX3Oojbq_pbF3ifPYMYezBU0_pe-_Tg/viewform"
const val TERMS_URL =
"https://third-sight-046.notion.site/Runnect-5dfee19ccff04c388590e5ee335e77ed"
private const val DEV_MODE_SCHEME = "runnect://devmode"
Copy link
Contributor

Choose a reason for hiding this comment

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

이 내용이군요. 새롭게 배워갑니다! 저는 기존에 보편적으로 쓰는 방법들과 비교해서 이 방법이 어떤 효용이 있는지 잘 모르겠는데 동현님은 어떻게 느끼시는지 궁금합니다!

https://gun0912.tistory.com/13

Copy link
Member Author

Choose a reason for hiding this comment

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

스킴을 이용하는 방법이다 보니까 기존 코드를 건드리지 않고 액티비티를 교체할 수도 있지 않을까요?
액티비티로 띄우던 걸 웹뷰로 띄운다거나, 다른 액티비티를 띄운다거나..

다른 액티비티로 바꿀 때도 호출하는 쪽은 놔두고 새 액티비티에 스킴만 동일하게 지정해주면 되니까 이 정도 장점 말고는 딱히 모르겠습니다!
큰 차이는 없는거 같아요

@@ -75,6 +82,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.core:core:1.9.0'
implementation 'com.google.firebase:firebase-common-ktx:20.1.0'
implementation 'androidx.preference:preference-ktx:1.2.1'
Copy link
Contributor

Choose a reason for hiding this comment

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

이런 게 있었군요! 새로 알아갑니다! 이 라이브러리를 쓰면 어떤 게 좋은가요?!

제 개인적인 생각에는 큰 효용을 주는 게 아니라면 개발자 모드 정도의 layout은 기존의 방식으로도 금방 짤 수 있으니 이것만을 위한 라이브러리 추가는 (미미할 수 있겠지만) 앱 용량 아깝다는 생각이 조금 들기도 했습니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

https://developer.android.com/guide/topics/ui/settings/organize-your-settings?hl=ko

설정 화면에 특화된 라이브러리인데, 단순히 화면을 구성하는 것 외에도 값 저장, 계층 구조 표현 등 다양한 기능을 지원하는 것 같습니다!
간단한 레이아웃이라도 직접 구현하면 은근 손이 많이가더라구요

설정 화면 정도에선 충분히 쓸만한 메리트가 있다고 생각합니다~!

@dongx0915 dongx0915 force-pushed the feature/feat-add-developer-mode branch from fd040df to ea89969 Compare December 14, 2023 15:40
@unam98 unam98 force-pushed the develop branch 2 times, most recently from 9538b84 to 55b4ded Compare December 20, 2023 13:17
@dongx0915 dongx0915 merged commit a9e5c88 into develop Dec 20, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ADD ➕ feat 이외의 부수적인 코드, 파일, 라이브러리 추가 동현 🐨 동현 담당
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ADD] 개발자 모드 추가
3 participants