기본 콘텐츠로 건너뛰기

[상추 키우기] 두 번째 상추...

 게으름으로 인하여 두 번째 상추 재배는 수확까지 끝난 다음에야 포스팅을 하게 되었습니다. 두 번째 상추 재배는 새로운 그로잉스펀지와 재배기에 심을 수 있는 12포트 중에서 4포트만 사용하여 상추를 재배했습니다. 그리고, TDS 측정기를 이용하여 양액의 농도 측정도 하면서 재배를 하였습니다. 수경 재배기를 살 때 포함되어 왔던 그로잉스펀지는 지난번 상추 재배로 인하여 모두 소비되어서 알리에서 새로운 스펀지를 주문했습니다. 주문하면서 실수로 동그란 스펀지가 아닌 네모 스펀지를 주문하는 바람에 포트에 넣었을 때 약간의 공간이 생깁니다만 크게 문제가 되지는 않습니다. 그런데 이번에 스펀지는 번들 스펀지에 비해서 밀도가 높다라고 해야할지 스펀지에 구멍이 적은 것 같습니다. 상추 뿌리가 스펀지를 뚫고 나오는데 지난번 보다 오래 걸린것 같습니다. 다음에 주문할 때에는 이런 부분을 좀 주의해야 할 것 같습니다. 그리고, 스펀지와 함께 TDS 측정기도 함께 구매해서 양액의 농도도 측정하였습니다. 상추의 경우 560 ~ 840 정도의 TDS 범위로 양액을 맞춰주라고 하는데, 수경 재배기에 번들된 양액을 12포트 분량으로 혼합하면 이 범위를 만족합니다. 지난번 재배에서는 이 값을 몰라서 싹을 틔우는 시기와 어린 시기에 양액 농도를 낮게 했었는데 그럴 필요는 없었던 것 같습니다. 약 5주 가량 길러서 수확하기 직전의 상태입니다. 12포트를 키울 떄 보다 빛을 잘 받아서 그런지 웃자람도 없고, 상치 잎의 크기도 지난번보다 상대적으로 컸습니다. 보통 상추를 키울때, 잎이 커지면 일부를 따 먹으면서 계속 키우는데 4포트만 키우게 되면 잎을 따 먹기에는 양이 너무 적어서 다 키워서 한번에 수확을 해야 했습니다. 그래서 다음 재배는 포트수를 조금 더 늘려서 시도해보겠습니다. 

Java, Android, Gradle.. 익숙해지지 않는 개발 환경...

 나는 여러 해 동안 iOS/안드로이드 개발을 해오고 있다. iOS/안드로이드 개발하기 이전에는 MFC 기반의 개발을 다년간 했었고, 일로 인해서 VB, ASP, JAVA, JSP 등도 약간씩 하기도 했었습니다.

MFC 개발 환경에 익숙했어서 인지, 늙어서 그런지, 게을러서 그런지 안드로이드 개발에서 아직도 적응이 되지 않는 부분이 Gradle 기반으로 하는 빌드 환경 구성 부분은 아직도 익숙해지지 못했습니다. 게을러서이겠지요.

예전에 MFC 기반으로 개발하던 시절에 비해서 안드로이드 개발 환경은 변화가 비교적 자주 발생하고, SDK 버전 변경시, Android Studio 업데이트 시 어쩔 수 없이 뭔가를 해줘야하는 상황이 발생하는데 그때 그때 찾아보고 대응하는 식으로 하다보니 문제를 키우는게 아닌가 싶기도 합니다.

그리고, 현업에서 개발환경에 변화를 줬다가 기대치 않은 문제가 발생하기도 하고, 급히 처리해야 하는 고객 요구 사항을 제때 대응하지 못하는 문제가 발생할 수 있어서, 반드시 업데이트가 필요한 상황이 아니면 개발 환경은 건드리지 않는 것을 철칙으로 삼아오다보니 새로운 개발환경 적응에 늦게 따라갈 수 밖에 없기도 했습니다.

최근에 flutter 기반으로 개발을 하고 있다보니 내 입장에선 좀 더 복잡해진것 같은데, 서론이 너무 길어진것 같으니 본론으로 들어가도록 하겠습니다.

얼마전부터 개발을 하면서 run 명령을 내리면 에러가 한번 발생하고 다시 실행하면 실행이되는 문제가 발생하기 시작했습니다. 예를 들어서 Log.d(TAG, ""); 와 같은 오류가 없는 라인을 추가 했음에도 오류가 한번 발생하고 다시 실행하는 정상 실행되는 이해할 수 없는 문제였습니다.

처음 문제가 발생했던 시점에는 처리해야할 급한 일들이 산재해 있고, flutter는 hot reload라는 기능을 통해서 빌드 없이(?) 바로 수정 사항이 반영되기 때문에 일을 하는데 크게 불편하지 않은 상황이어서 무시하고 진행을 했습니다. 그런데 최근에 flutter 쪽 코드가 아닌 java 코드를 수정해야하는 부분들을 개발하다보니 이 부분이 개발에 상당한 장애로 다가오기 시작했습니다. 빌드하는데 걸리는 시간이 몇분이 소요되는데 한번 실행해보려면 빌드를 한참하다가 오류가 발생하고, 다시 실행해야 수정한 내용의 결과를 볼 수 있어서 1시간 동안 얼마의 작업을 하지 못하는 상황이 계속되었습니다. 그래서 급한 일도 어느정도 처리되고 해서 이 문제를 해결하기로 했습니다.

일단 발생하는 오류는 다음과 같습니다.

FAILURE: Build failed with an exception.


* What went wrong:

Execution failed for task ':app:compileDebugJavaWithJavac'.

> kotlin.KotlinNullPointerException


* Try:

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.


* Get more help at https://help.gradle.org


BUILD FAILED in 55s

Running Gradle task 'assembleDebug'...                             56.6s

Exception: Gradle task assembleDebug failed with exit code 1


kotlin을 사용하는 코드는 없는데 java 컴파일 단계에서 kotlin 관련 예외가 발생한다고 나오는 이상한?? 오류가 발생합니다. 

직접적인 오류 메시지를 이용한 검색으로는 크게 관계가 있어 보이는 내용을 찾을 수 없습니다.


그래서 개발툴이 시키는데로 --stacktrace를 수행해 보았습니다.

android % ./gradlew assembleDebug --stacktrace


좀 더 자세한 오류 메시지가 보이기 시작합니다.

android % ./gradlew assembleDebug --stacktrace

An exception has occurred in the compiler (1.8.0_312). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.AssertionError: annotationType(): unrecognized Attribute name MODULE (class com.sun.tools.javac.util.UnsharedNameTable$NameImpl)
        at com.sun.tools.javac.util.Assert.error(Assert.java:133)
        at com.sun.tools.javac.code.TypeAnnotations.annotationType(TypeAnnotations.java:231)
        at com.sun.tools.javac.code.TypeAnnotations$TypeAnnotationPositions.separateAnnotationsKinds(TypeAnnotations.java:294)
        at com.sun.tools.javac.code.TypeAnnotations$TypeAnnotationPositions.visitMethodDef(TypeAnnotations.java:1066)
        at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:778)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
.... 이하 생략 ....

java compiler 관련 문제로 보입니다.

검색 결과 stackoverflow에 compile sdk version 이 31이고, java 8을 사용하고, lamda를 사용하는 코드가 있는 경우에 발생한다라는 내용이 있었습니다. [1]

아마 문제가 발생한 시점에 앱 배포를 준비하면서 플레이 스토어가 31이상을 요구하여 변경하면서 생기기 시작했던 것 같습니다.

JDK 11로 변경하라는 내용과 함께 안드로이드가 JDK 11을 사용하는 것을 요구한다는 내용도 보였습니다.

답에 있는데로 하면 되어야 하는데..

Settings > Build, Execution, Deployment > Build Tools > Gradle > Gradle JDK

안드로이드 스튜디오에서 이 메뉴를 찾을 수 없었습니다.

답글에서 사용한 안드로이드 스튜디오는 Arctic Fox인데 사용하던 안드로이드 스튜디오는 Bumblebee 버전으로 더 높은 버전이었습니다. 버전 차이로 없어진가가 싶어서 다운그레이드를 하려다가 새 버전이 있다기에 업그레이드를 결정했습니다.

Chipmunk 버전으로 업그레이드 했음에도 해당 메뉴는 보이지 않았습니다. 문득 flutter 프로젝트 대신 안드로이드 프로젝트를 열어볼까라는 생각에 안드로이드 프로젝트를 열어 보았습니다. 그 결과 해당 메뉴가 보였고, 정상적으로 11을 사용하는 것으로 설정되어 있었습니다.

그래서 문제 해결의 희망을 갖고 다시 빌드를 수행했으나... 여전히 동일한 문제가 발생했습니다.

다시 검색해보아도 별 내용이 없어서 다시 JDK 11에 좀 더 집착해보기로 했습니다. 

내 컴퓨터에 JDK 11 이 깔려는 있을까???? 

% java -version

openjdk version "1.8.0_312"

OpenJDK Runtime Environment Corretto-8.312.07.1 (build 1.8.0_312-b07)

OpenJDK 64-Bit Server VM Corretto-8.312.07.1 (build 25.312-b07, mixed mode)


아하.. JDK 8이 깔려 있군요..

% brew tap adoptopenjdk/openjdk

Running `brew update --preinstall`...

==> Auto-updated Homebrew!

Updated 3 taps (homebrew/core, homebrew/cask and mono0926/license-plist).

==> New Formulae

age-plugin-yubikey         libxcvt                    spirv-headers

ansible-language-server    libxfont2                  sqls

arxiv_latex_cleaner        lndir                      sse2neon

bartib                     localtunnel                stanc3

... 중략 ...


% brew install --cask adoptopenjdk11

==> Downloading https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/down

==> Downloading from https://objects.githubusercontent.com/github-production-rel

######################################################################## 100.0%

==> Installing Cask adoptopenjdk11

... 중략 ...


 % java -version

openjdk version "11.0.11" 2021-04-20

OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9)

OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)



이젠 JDK 11도 깔렸으니 문제가 해결되길 기대하며 다시 빌드를 시도했으나 동일한 문제가 발생했습니다.

JDK 11을 깔기는 하였으나 아직 프로젝트는 1.8을 사용하는 것으로 설정되어 있으니, 이걸 변경하기로 결정했습니다.

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

다시 빌드시도...

이번에는 Intent, Context 이런 것들의 심볼을 모르겠다라는 오류들이 주루룩 나오기 시작했습니다.

/MainApplication.java:60: error: cannot access Application
public class MainApplication extends FlutterApplication {
       ^
  class file for android.app.Application not found

이 문제는 gradle을 7.0 이상을 사용하라는 내용을 찾을 수 있었습니다. [2]

그래서 프로젝트 build.gradle에서 gradle 버전을 아래와 같이 변경했습니다.

dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
classpath 'com.android.tools.build:gradle:7.2.0'

이번에는 친절하게도 gradle 배포 경로 변경하라는 오류가 나왔습니다.

* What went wrong:
A problem occurred evaluating project ':app'.
> Failed to apply plugin 'com.android.internal.version-check'.
   > Minimum supported Gradle version is 7.3.3. Current version is 6.7. If using the gradle wrapper, try editing the distributionUrl in .../android/gradle/wrapper/gradle-wrapper.properties to gradle-7.3.3-all.zip

gradle-wrapper.properties 파일의 내용을 아래와 같이 수정했습니다.

distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip

이제 성공적으로 빌드가 되고, 그 동안의 문제가 해결되었습니다.

이런 빌드 환경의 종속성 문제에 언제쯤 익숙해 질 수 있을지.. 은퇴하는게 빠를것 같기도 합니다.

혹시 위 내용중 제가 잘못 이해한 부분이 있으면 댓글 부탁드립니다.

참고 : [1] https://stackoverflow.com/questions/68344424/unrecognized-attribute-name-module-class-com-sun-tools-javac-util-sharednametab
[2] https://stackoverflow.com/questions/66551892/android-sourcecompatibility-javaversion-version-11-error-package-android-os
[3] https://bcp0109.tistory.com/302
[4] https://www.mobileit.cz/Blog/Pages/android-java-release-train.aspx





댓글

이 블로그의 인기 게시물

Admob UMP(Google User Messaging Platform) SDK를 이용한 GDPR(General Data Protection Regulation) 대응

얼마 전 부터 운영중인 앱의 Admob 계정을 들어가면 화면 상단에 아래와 같은 눈에 거슬리는 공지가 표시되기 시작했습니다. "올해 안에 EEA 및 영국 사용자에게 광고를 게재하는 모든 게시자는 Google에서 인증한 동의 관리 플랫폼(CMP)을 사용해야 합니다. Google의 자체 동의 관리 솔루션을 포함하여 Google에서 인증한 CMP 이면 어떤 것이든 이 목적으로 사용할 수 있습니다. Google의 동의 관리 솔루션을 사용하는 데 관심이 있으면 먼저 GDPR 메시지를 설정하고 UMP SDK를 구현하세요." 유럽쪽 사용자에 대해서 GDPR(General Data Protection Regulation) 동의 를 받을 수 있도록 하라는 것이다. GDPR 동의에 대해서 처리해야할 법적인 절차를 잘 모르니 친절한(?) Google의 도움을 받을 수 있다고 하니 받는 것으로 했습니다. 메시지를 보면 구글에서 인증한 동의 관리 플랫폼(CMP)를 사용하거나, 구글에서 제공하는 UMP SDK를 이용해서 구현 하면 된다는 내용입니다. 구글에서 UMP SDK를 제공한다고 하니, 이용하기로 합니다. UMP SDK 는 별도의 SDK 형태로 배포되지 않고, Admob SDK에 포함되어 있고, UMP SDK를 이용하여 구현하는 것은 가이드 페이지에 있는 것을 따라가면 되는 수준이라 여기에서는 생략하도록 합니다. # 참고 : - https://support.google.com/admob/answer/10113207 - https://developers.google.com/admob/ios/privacy - https://developers.google.com/admob/android/privacy - https://developers.google.com/admob/flutter/eu-consent 저의 경우에는 구현은 어렵지 않게 했으나, 이 것의 동작을 이해하는데 오랜 시간이 필요했습니다. 그 이유는 사용자로부터 개인정보 이용에 대한 동의를 얻지 못했을 때 광

[상추 키우기] 수경재배기에 양액 투입

 상추를 파종한지 10일이 지나서 상추들이 이만큼 자랐습니다. 상추의 뿌리가 포트 밖으로 빠져나올 정도로 길게 자랐습니다. 그래도 아직은 뿌리의 가닥 수도 작고, 가늘고 약합니다. 사무실에 사람이 있는 동안은 난방을 하니까 괜찮은데, 저녁에는 아직도 기온이 많이 내려가기 때문에 성장이 더딘것 같습니다. 이제 낮기온도 꽤 올라가고 꽃도 피기 시작하니까 멀지 않아서 폭풍 성장을 할 것 같습니다. 수경재배기 메뉴얼에서는 2주에 한 번 전체 물을 갈아주고, 그 외에는 보충을 해주라고 되어 있습니다. 아직 상추가 싹이 작기도 하고, 10일 밖에 지나지 않았지만, 그 동안 물로만 키우고 있었기 때문에 오늘은 양액을 넣어 주기로 했습니다. 그래서 전체 물갈이를 할 예정입니다. 우선 양액을 준비합니다. 국내에서 많이 판매되는 양액이 있기는 합니다만, 수경재배기에 포함되어 있는 양액을 먼저 사용하려고 합니다. 수경재배기에 포함되어 있는 양액은 액체 상태가 아닌 알갱이 상태로 두 개의 병에 담겨 있습니다. 각 병에 물 100ml 씩을 넣고 알갱이가 다 녹을 때까지 섞어 줍니다. 병에 100ml 눈금이 표시되어 있기 때문에 눈금까지 넣어 주면 됩니다. 메뉴얼 상에는 역삼투압 방식으로 정수된 물을 사용하라고 하는데, 전 그냥 수돗물을 사용했습니다. 순수한 물을 사용하면 아무래도 양액의 농도나 같은 것들이 좀 더 정확해 지지 않을까 싶긴 합니다만, 사무실에 정수기도 없고.... 그렇다고 약국에 증류수를 사러가기도 뭐하고.. 근처에 약국도 없고.. ^^;;;;;;; 여튼, 알갱이가 다 녹을 때까지 섞어 줍니다. A용액은 약간 노란빛이 드는 액체가 되고, B용액은 투명색을 그대로 유지합니다. 그리고, 2L 생수병에 물 2L를 채우고, A용액을 10ml 넣어준 다음에 B용액 10ml 를 추가하였습니다. A/B용액이 직접 만나게 되면 화학 반응이 일어날 수 있는 모양입니다. 그래서 A용액이 물에 충분히 희석된 다음에 B용액을 넣었습니다.  메뉴얼에는 12포트이면 각각 15ml를 넣으라고

[iOS] Privacy Manifest(PrivacyInfo.xcprivacy)

 Apple App Store는 2024년 5월 1일부터 배포되는 앱(신규, 업데이트 모두)에 대해서 Privacy Manifest 를 포함을 요구하고 있습니다. 아마 저를 포함하는 많은 개발자들이 이 사항을 가지고 머리를 싸매고 있지 않을까 생각이 됩니다. Privacy Manifest를 프로젝트에 포함시키는 것은 기술적으로 어렵지 않고 애플도 비교적 잘 설명된 문서들을 제공하고 있습니다. ( 참고1 , 참고2 ) 그리고, 이미 많은 글에서 이것에 대해서 설명하고 있습니다. 저는 애플의 이러한 정책의 방향성은 훌륭하다고 생각합니다. 요즘 개인정보 관련한 정보 제공 요구가 나날이 강화되고 있는데, 앱 개발자 입장에서 내가 작성한 코드에 대해서는 그나마 알 수 있지만, 요즘과 같이 많은 서드파티 SDK 의존성을 바탕으로 앱을 개발하고 있는 상황에서 각 서드파티 SDK에서 수집되는 정보를 일일이 파악할 수도 없으며, 이들이 이 정보를 이용하는 목적은 더더욱 알기가 어렵기 때문입니다. 그리고, 단순 "수집"이냐 "추적"이냐 까지 파고 들려면, 용어도 어렵고, 정책적 부분이 판단도 애매한 상황에서 개발자가 자신이 개발한 앱에서 수집하는 개인정보에 대해서 모두 제공하는 것은 불가에 가깝습니다. 그래서 앱 스토어에서 "앱이 수집하는 개인정보" 섹션을 채우라고 했을 때는 개인정보를 수집할 것 같은 서드파티들의 기술지원 페이지를 참고해서 항목들을 정리해야하만 했습니다. 이번 애플 정책 요구에서 눈에 띄는것은 각 서드파티에서 제공하는 SDK에도 Privacy Manifest를 포함하도록 요청하고 있습니다. 이로 인해서 개발자는 내가 개발하는 코드에서 수집되는 정보에 대해서 좀 더 집중할 수 있습니다. 다만, 오래된 서드파티 SDK 버전을 사용하는 경우에는 부득이 업데이트를 하거나 대안을 찾거나 하는 피곤한 상황이 생기긴 했습니다.. ^^; 저도 이번 정책 변경으로 개발중인 앱을 요건에 맞게 수정 하는 작업을 진행했습니다.