앱 초기 설정 및 기본 설계에 초점
일반적으로 회사 혹은 오픈소스들에는 사용하는 스타일 가이드가 존재
- Preference > Editor > Code Style > Kotlin > set from > Kotlin style guide
- Preference > Editor > Code Style > XML > Android
Android Lint는 앱 소스 파일과 lint.xml를 통해서 앱의 문제점들을 해결해 줍니다.
- Android Lint가 안드로이드의 관련된 디펜던시나 리소스 관련 부분들에 대해 정적분석을 해준다면 ktlint와 detekt는 kotlin 소스에 대한 정적분석을 실행합니다.
- ktlint와 detekt는 Kotlin 상에서 실수할 수 있는 부분을 고쳐주며 다양한 rule들을 통해 코드를 분석하여 html이나 xml과 같은 형식으로 받아서 볼 수 있습니다.
- app/build.gradle 설정 추가
configurations {
ktlint
}
dependencies {
ktlint "com.pinterest:ktlint:0.41.0"
// additional 3rd party ruleset(s) can be specified here
// just add them to the classpath (ktlint 'groupId:artifactId:version') and
// ktlint will pick them up
}
task ktlint(type: JavaExec, group: "verification") {
description = "Check Kotlin code style."
main = "com.pinterest.ktlint.Main"
classpath = configurations.ktlint
args "src/**/*.kt"
// to generate report in checkstyle format prepend following args:
// "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/ktlint.xml"
// see https://github.com/pinterest/ktlint#usage for more
}
check.dependsOn ktlint
task ktlintFormat(type: JavaExec, group: "formatting") {
description = "Fix Kotlin code style deviations."
main = "com.pinterest.ktlint.Main"
classpath = configurations.ktlint
args "-F", "src/**/*.kt"
}
KotlinDSL
val ktlint by configurations.creating
tasks.register<JavaExec>("verification") {
group = "verification"
description = "Check Kotlin code style."
classpath = ktlint
main = "com.pinterest.ktlint.Main"
args("--android", "src/**/*.kt")
}
tasks.named("check") {
dependsOn(ktlint)
}
/** 스타일 수정 후 자동으로 수정해 줌 */
tasks.register<JavaExec>("ktlintFormat"){
description = "Fix Kotlin code style deviations."
classpath = ktlint
main = "com.pinterest.ktlint.Main"
args("-F", "src/**/*.kt")
}
- configurations 이 dependencies 보다 위에 선언 되어 있어야 ktlint 적용됨
- .editorconfig 로 Rule 세팅
- rules 추가
- Kotlin 프로젝트를위한 코드 분석
- Gradle 빌드를 통한 코드 분석을위한 Gradle 플러그인
- detekt 플러그인 추가
plugins {
...
id "io.gitlab.arturbosch.detekt" version "1.16.0"
}
KotlinDSL
plugins {
...
id("io.gitlab.arturbosch.detekt") version "1.16.0"
}
- detekt.yml 생성
./gradlew detektGenerateConfig
- detekt 설정
- app/build.gradle 에 detekt 추가 하고 detekt.yml 실제 경로로 수정
detekt {
toolVersion = "1.16.0"
config = files("$rootDir/config/detekt/detekt.yml")
buildUponDefaultConfig = true
}
- 적용된 린트들을 깃에서 commit 혹은 push를 될 때마다 시켜주기 위해서 깃훅을 사용했습니다.
KotlinDSL
/** GitHooks 복사 */
tasks.register<Copy>("copyGitHooks"){
from("${rootDir}/codeConfig/git/git-hooks/") {
include("**/*")
rename("(.*)", "$1")
}
into("${rootDir}/.git/hooks")
}
/** GitHooks 설치 */
tasks.register<Exec>("installGitHooks"){
group = "git hooks"
workingDir(rootDir)
commandLine("chmod")
args("-R", "+x", ".git/hooks/")
dependsOn("copyGitHooks")
}
- GitHub 의 공동창업자인 톰 프레스턴 베르나가 만든 Semantic Versioning을 기반으로 버전 관리
Given a version number MAJOR.MINOR.PATCH, increment the:
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards compatible manner, and
- PATCH version when you make backwards compatible bug fixes.
- Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
- 비동기 처리 Coroutines
- Jetpack
- Lifecycle: 수명 주기 변경 사항을 관찰합니다.
- ViewModel: UI 관련 데이터 홀더 및 수명 주기 인식.
- Navigation: 다양한 화면 및 앱 간 탐색, 사용자가 앱내에서 이동할 때 동일한 탐색 휴리스틱과 패턴을 적용할 수 있습니다.
- Hilt: 의존성 주입
- Glide: 이미지 로딩 라이브러리
- Retrofit2 & OkHttp3: REST API 네트워크 데이터를 구성합니다.
- Timber: 유틸리티를 제공하는 가볍고 확장 가능한 API가 있는 로거.
-
User Interface Layer:
- UI 레이어의 책임은 화면에 애플리케이션 데이터를 렌더링하는 것입니다.
- 사용자 상호 작용 또는 네트워크 및 데이터베이스와의 외부 통신으로 인해 애플리케이션 데이터가 변경될 때마다 UI 요소를 업데이트해야 합니다.
-
Presentation Layer:
- 프레젠테이션 계층의 책임은 UI 계층과 도메인 계층 간의 데이터 변경 사항을 상호 작용하고 알리는 것입니다.
- 구성 변경 시 데이터를 보유하고 복원합니다.
-
Domain Layer:
- 도메인 계층은 복잡한 비즈니스 로직을 추상화하고 재사용성을 향상시키는 역할을 합니다.
- 이 계층은 복잡한 애플리케이션 데이터를 프레젠테이션 계층에 적합한 유형으로 변환하고 유사한 비즈니스 로직을 단일 기능으로 그룹화합니다.
-
Data Layer:
- 데이터 계층의 책임은 CRUD 작업(생성, 검색, 업데이트, 삭제 – 모든 시스템 이벤트)과 같은 비즈니스 로직 실행 결과를 전달하는 것입니다.
- 이 계층은 Repository나 DataSource와 같은 다양한 전략으로 실행 책임을 나누어 설계할 수 있습니다.
- master 브랜치는 production 브랜치
- production브랜치는 master 이상 권한만 push 가능
- developer 권한 사용자는 master 브랜치에서 신규 브랜치를 추가
- 신규 브랜치에서 소스를 commit 하고 push
- merge request를 생성하여 master 브랜치로 merge 요청
- merge_request를 생성하기 전에는 master 브랜치를 rebase 해서 병합 커밋을 방지
- master 권한 사용자는 developer 사용자와 함께 리뷰 진행 후 master 브랜치로 merge
- 테스트가 필요하다면 master에서 procution 브랜치로 merge하기 전에 pre-production 브랜치에서 테스트
- MVVM 에서 기본적으로 사용하는 View, ViewModel, layout 을 기본으로 생성해주는 Custom Template 추가
- Plugin Library Path: ./libs/android-mvvm-plugin-template-0.0.1.jar
- Android Studio > Preferences.. > Plugins > 오른쪽 상단 톱니바퀴 모양 클릭 > Install Plugin from Disk > jar 파일 선택 > 스튜디오 재시작
-
생성할 폴더에서 우클릭 > New > Other > Android Fragment MVVM Creator > 정보 입력
-
EntityName 규칙
- Mvvm Activity creator
- EntityName: FeatureHome 결과
- view/FeatureHomeActivity
- viewmodel/FeatureHomeViewModel
- layout/activity_feature_home
- EntityName: FeatureHome 결과
- Mvvm Fragment creator
- EntityName: FeatureHome 결과
- view/FeatureHomeFragment
- viewmodel/FeatureHomeViewModel
- layout/fragment_feature_home
- EntityName: FeatureHome 결과
- Mvvm Activity creator
- 토큰만료시 작업
- 구글 계정 로그인 클릭 후 계정 선택시 서비스 약관 링크가 걸려있는데 어디서 작성해야하는지 검토 필요
- 개인정보처리방침, 서비스 약관
- 구글 idToken 만료 및 갱신 시점
유저 관련 정보를 관리
- companion object 에 선언되어있는 메서드 활용
@JvmStatic
fun isLoggedIn() = getInstance().info != null
@JvmStatic
fun getUserInfo() = getInstance().info
@JvmStatic
fun getIdToken() = getInstance().info?.idToken
@JvmStatic
fun getUserName() = getInstance().info?.userName
@JvmStatic
fun getEmail() = getInstance().info?.userEmail
- 로그인 여부, 상세 유저 정보를 가져올수 있습니다.
로그인, 로그아웃, 인증 관련 정보를 관리
fun signIn()
fun signOut(updateAction: () -> Unit)
fun revokeAccess(updateAction: () -> Unit)
- 위의 public fun 을 사용해서 로그인, 로그아웃 계정연결 해제
화면에서 로그인 상태를 옵저빙하고 로그인 여부에 따라서 처리해야 할 작업을 처리
observeChangedLogin { isSignedIn ->
if (isSignedIn) {
moveToNext()
}
}
- 사용 예시로 Activity, Fragment 에서 옵저버를 선언하고 로그인 상태가 변경되었을때 호출이 되며 이후 액션 추가