[Android] 라이브러리 출시법 및 팁 feat.WTBarChart - 나의 첫 번째 라이브러리

양현진·2022년 6월 9일
2

Oh My Android

목록 보기
1/22
post-thumbnail

프로젝트도 한게 손가락에 뽑은 주제에 갑자기 라이브러리를 하게된 이유는 그냥..그냥이었다. 그저 구글에 내 라이브러리가 있다면 너무 기쁠 것 같아 시작하게 되었다.

그래도 개발을 시작할 때 가장 많이 진행하는 프로젝트 중 하나인 TODO앱을 겨냥해서 개발한거라 잘 쓰일것 같아 희망을 본다!
우선 링크에 나름 노력해서 상세하게 설명했다.

많은 관심 부탁드려용!😫

모듈 만들기

라이브러리를 만들기 위해 우선 모듈을 생성해야 한다.
File -> New -> New Module

Android Library 선택 후 Module name 기입 후 Finish

여기서 Module name은 app폴더와 같게 path 이름 정도로 생각하면 된다. 나중에 implementation 때 지어지는 이름이 아니니 안심.
네이밍은 앞에 라이브러리 이름을 줄여쓰고 뒤에 Lib를 붙이는 듯 하다. ex - WTChartLib

이후 본인이 원하는 기능을 담은 코드를 작성한다.
코드를 다 작성했으면 이제 배포를 해야하는데, 배포전에 라이브러리 출시에 도움이 되는 몇가지를 보자.

1. Explicit API Mode

build.gradle(Module) - android 스코프에 기입


"명백한 API 모드"
Kotlin에서 제공하는 이 기능은 라이브러리 출시 전, 파일 내 모든 클래스와 메서드, 변수에 대해 접근 제어자들을 명시하게 만드는 기능이다.
접근 제어자는 밑에서 말하겠지만 라이브러리 개발시에 상당히 중요한 역할을 한다. 되도록이면 public을 지양하는 편이 좋기에 모든 곳에 접근 제어자를 명시함으로써 실수를 방지하게 도와준다.

strict(엄격)과 warning(주의) 두 가지가 있는데 strict는 명시를 하지 않으면 컴파일 에러를 발생시키고 warning은 경고창(오줌)을 발생시킨다.
이왕 쓸거면 strict가 눈에 훨씬 잘 보이니 이 모드를 추천!

2. resourcePrefix

build.gradle(Module) - android 스코프에 기입

이 기능은 모듈안에 있는 resource파일에 대해 prefix(접두사)를 사용자 정의하고 추가하도록 강제하는 기능이다.
예를 들면 R.drawable.chart_shape라는 파일이 있으면 정의한 접두사를 붙여 R.drawable.wtbar_chart_shape로 바꿔야한다.

이건 개인적으로 라이브러리를 출시한다면 필수적으로 해야한다 느끼는게, Android Studio는 빌드 시 module과 app중에 같은 소스파일이 있다면 app모듈을 우선순위에 둔다. app과 module에 같은 이름의 파일 ex - R.layout.main_activity가 있다면 app에 있는 layout resource를 채용한다.

이렇게 되면 어떤 문제가 발생할까, 대충 생각해도 버그가 날 가능성이 농후하다.
첫 번째로, 해당 모듈을 가져다 쓰는 개발자가 우연찮게 동일한 이름의 resource파일을 정의했다면 빌드 시 모듈은 app의 resource파일을 가져다 쓰게된다. 그러면 당연히 라이브러리 개발자가 의도한 기능이랑 달라지게 된다. color면 색이 변경되고, string이면 글자가 변경되고, drawable이면 모양이 변경된다. 이번에 만든 WTBarChart는 각 view들의 크기로 계산을 하기때문에 drawable이 변경되면 치명적인 버그로 이어진다. 하지만 제일 중요한 것은 layout파일이다. 이 layout파일 이름을 동일하게 정의했다면 99.9999%의 확률로 crash가 나버린다. layout에는 각 view들의 id값이 정의된 경우가 대다수이고, 라이브러리 개발자는 그 id값으로 다음 기능을 구현하게 되는데, id값이 없거나, 같더라도 타입이 다르거나 (ex - TextView id, ImageView id)하면 바로 앱이 터져버린다.

문제는 모듈을 가져다 쓰는 개발자는 원인을 찾기가 매우 어려울 것이다. 이유는 평소처럼 똑같이 코딩을 했지만 어디는 라이브러리 문서와 다른 형태가 나오고, 또 어디는 자꾸 앱이 터지니 며칠 째 골머리 앓다가 머리마저 터질 가능성이 있다.

말이 길었는데 resourcePrefix는 이를 방지하기 위함이다. 모든 파일에 사용자 정의 접두사를 추가하게 되면 네미잉이 같아질 확률이 현저히 떨어진다. 나는 wtbar_라는 걸로 정의했고, 아마 이걸 쓸 개발자들은 없을리라고 생각한다.

극악의 확률로 겹쳐질 수도 있지만 그렇다면 둘이 결혼각!

3. Non transitive R class

gradle.properties -> android.nonTransitiveRClass=true

각 라이브러리의 R 클래스의 네임스페이스를 활성화하여 해당 R 클래스에
라이브러리 자체에 선언된 리소스와 라이브러리의 종속성에서 선언된 리소스 없음,
따라서 해당 라이브러리에 대한 R 클래스의 크기를 줄입니다.

속성위에 설명되어 있는 영문을 번역한 것이다.
사실 이는 버전이 높아지면서 기본적으로 true가 되도록 변경된 것 같다.
간단하게 설명하자면, 모듈(라이브러리)를 가져다 사용하게 되면 그 모듈안에는 엄청나게 많은 R 클래스들이 있다.

다 기본적으로 Android Studio하는 것 들이다.

평소에는 유용하게 쓰일때도 있지만 문제는 다른 모듈을 추가하면 그 모듈도 똑같이 기본적은 R 파일들이 있어 중복파일이 수 없이 생긴다.
이 중복을 제거하기 위해 nonTransitiveRClasss는 새로운 모듈을 추가할 때 유용하며 활성화 시 40% 성능 향상이 있다고 한다.

4. 그 외

resource파일 기능 중에 /<\public>도 있는데, 이는 모듈 외에 다른 프로젝트에서 공개할 몇몇 resource파일만 정의하고 나머지는 숨기는 기능이다. 근데 왜 그 외로 빠졌냐면 써보려 했는데 배포하고 보니 public외에도 잘만 뜬다.. 이건 내가 못하는거라 pass

라이브러리는 다른 개발자들에게 내 코드를 제공하는 것이다. 앱 배포와 다른거라곤 사용자 고객층이 일반사람들에서 개발자로 좁혀진 것 뿐이다. 하지만 이 차이에서 이점이 생긴다. 일반사용자는 '앱'을 사용하고 개발자는 '코드'를 사용하는 것 인데, 상용중인 앱에서 리뷰에 뭐가 안돼요~ 뭐 했더니 느려요~ 앱이 꺼졌어요~ 하는 글들이 있다. 우리는 정확이 이게 어디서 발생한 버그인지 재현하기가 쉽지 않다. 하지만 모듈은, 코드를 사용하는 것 이기에 '접근 제어자'를 통해 공개하는 범위를 지정할 수 있는 장점이 있다. 대부분을 internal 또는 private으로 지정하고, 기능을 호출하는 메서드만 public으로 노출하게 되면 진입 경로가 줄어들어 그나마 앱 보다는 수월한 대응이 될 수 있다고 생각한다.

배포 준비

Android에서 라이브러리 배포 법을 검색하면 90%는 jitpack을 통한 배포법이 나오고 나 또한 jitpack으로 하였다. 하지만 더 알아보니 한가지를 더 찾았다

  • JCenter - Bintray
  • Maven - jicpack

Jcenter배포는 해보지 않아서 jitpack을 통한 배포법을 써보려 한다. 보기론 Jcenter로 하게 되면 몇가지 등록이 필요하고, jitpack은 그런거 없이 단순하긴 한데, 다른 개발자가 모듈을 추가할 시에는 setting.gradle에 jitpack.io를 하나 더 기입해야 한다.

1. 버전 관리 및 아이디 생성

build.gradle(Module)

afterEvaluate {
    publishing {
        publications {
            // Creates a Maven publication called "release".
            release(MavenPublication) {
                // Applies the component for the release build variant.
                from components.release

                // You can then customize attributes of the publication as shown below.
                groupId = 'com.github.hyunjine'
                artifactId = ''
                version = '1.0.0'
            }
            // Creates a Maven publication called “debug”.
            debug(MavenPublication) {
                // Applies the component for the debug build variant.
                from components.debug

                groupId = 'com.github.hyunjine'
                artifactId = 'final-debug'
                version = '1.0.0'
            }
        }
    }
}

gradle관련해서 아직 잘 알지 못한다. 하지만 여기서 혼자 실험을 통해 알아낸 것은 'artifactId'인데, 이는 우리가 Android Studio에 라이브러리를 추가할 때 implementation 뒤에 오는 uri?에 영향을 미친다.
artifactId가 'myLibrary'이런거로 되어있으면

implementation 'com.github.hyunjine:WTBarChart:myLibrary:1.0.0'

이렇게 되더라. 저거 하나 알아낼라고 새로운 프로젝트 만들어서
1. 프로젝트 명
2. 모듈 명
3. artifactId
4. GitHub Repository 명
을 다 다르게하고 배포해봤는데 artifactId이 주인공 이었다.
하지만 다른 라이브러리들을 보면 artifactId이 없이 바로 버전으로 이어지는걸 보고 없애는 법을 또 한참 테스트 해보니 위 코드와 같이 빈칸으로 놓으면 되는 것 같다.

추가로 앞에오는 com.github.hyunjine:WTBarChart는 깃허브 주소와 Repository이름에 영향을 받고, 맨 뒤에 오는 버전은 깃허브에서 Release Tag를 따라간다.

2. 플러그인 추가

build.gradle(Module)

id 'maven-publish'

끝.

3. jitpack.yml 추가

Project 최상위

처음에 파일을 추가하라해서 어디서 다운받는거지 했는데 그냥 Project에 New File하고 jitpack.yml로 생성후 저 두줄만 기입하면 되는거였다.

4. GitHub Release

설정이 완료된 모듈을 자신의 깃허브에 push한다. 그럼 우측에 Release가 보인다.
참고로 프로젝트에 module외에 app폴더가 있을 수도 있는데 라이브러리 배포 시 모듈만 배포되니 안심

들어가서 Choose a tag를 누르고 tag 생성 후 원하는 title과 content를 넣고 Release를 하면 된다. 여기 쓰이는 tag이 추후 implemetation에서 버전으로 나오니 유의.

5. Jitpack에 등록

여기에 들어가서 본인 Github 닉네임과 Repo이름을 적고 우측에 Look up을 클릭한다.

그럼 아래와 같은 것이 보이고 깃허브에 릴리즈한 tag가 쭉 나열된다. 우측에 Get it 버튼을 누르면 배포가 시작되고, 밑으로 스크톨하면 How to에 잘 써있다. 시간은 체감상 한 5분 걸리는 것 같다.


이 과정으로 첫 라이브러리를 배포해봤는데 다른 프로젝트에서 만든 라이브러리를 추가하고 빌드될 때 그 쾌감이 장난아니었다.

굳이 커리어를 위해서가 아니더라고 다들 한번쯤은 라이브러리를 제작해보는것을 추천한다.

tedPermission으로 유명한 박상권님의 글 중 첫 라이브러리가 로그찍는 라이브러리였다고 했던 것 같은데(맞나?)
시작부터 거창한 건 필요 없을듯 하다.

profile
Android Developer

0개의 댓글