2026/04/02

오늘의 이야기

여러 가지 방법으로 다국어 앱을 만들어 보기는 합니다. 이번에는 fork 한 외국어 앱에 한국어를 담아 보도록 하겠습니다.  google gemini api을 호출하는 기능을 이용해 볼 생각입니다. 


 


# Gemini API Key AI********nPU

import google.generativeai as genai
import os
import re

baseDir = 'C:/workspaces/Smart-AutoClicker0510/'

GOOGLE_API_KEY = 'AI********nPU'
genai.configure(api_key=GOOGLE_API_KEY)


# for m in genai.list_models():
# if 'generateContent' in m.supported_generation_methods:
# print(m.name)

def geminiFunc(orgString):
model = genai.GenerativeModel('gemini-pro')
prompt = '''
Translate English sentences '{0}' into Korean naturally. Use expressions that feel natural to Korean speakers.
'''.format(orgString)
response = model.generate_content(prompt)
try:
rValue = response.text
except:
rValue = ''
for item in response.parts:
rValue = rValue + item
rValue = re.sub("'","", rValue)
return rValue.strip()


def getTranslate(line):
xList = line.split('>')
try:
xItem = xList[1].split('<')[0]
except:
xItem = xList[1]
return geminiFunc(xItem)


def getName(line):
xName = line.strip().split('"')
return xName[1]


def doRead(path, fileName):
path = re.sub(r"\\", '/', path)
xPath = path.split('/')
xPath[xPath.index('values')] = 'values-ko'
nPath = '/'.join(xPath)
f = open(fileName, 'r', encoding='UTF-8')
if not os.path.isdir(nPath):
os.makedirs(nPath)
ot = open(os.path.join(nPath, 'strings.xml'), 'w', encoding='UTF-8')
rValue = ''
rName = ''
addTy = False
while True:
line = f.readline()
if not line: break
if line.strip() == '': continue
try:
if line.strip().startswith('<string name') and '</string>' in line and 'false' not in line:
rValue = getTranslate(line)
rName = getName(line)
rValue = '<string name="{0}">{1}</string>'.format(rName, rValue)
print(rValue.strip())
ot.write(rValue + '\n')
addTy = False
elif line.strip().startswith('<string name') and '</string>' not in line and 'false' not in line:
rValue = line.strip().split('>')[1]
rName = getName(line)
addTy = True
elif addTy and '</string' in line:
rValue += line.strip().split('<')[0]
rValue = geminiFunc(rValue)
rValue = '<string name="{0}">{1}</string>'.format(rName, rValue)
print(rValue.strip())
ot.write(rValue + '\n')
rValue = ''
addTy = False
else:
if addTy:
rValue += line
else:
rValue = line
print(rValue.strip())
ot.write(rValue + '\n')
except:
print(path, fileName, line)
ot.close()
f.close()


print('JOB START...')
for (root, directory, files) in os.walk(baseDir):
for file in files:
if not ('values-' not in root and 'strings.xml' in file): continue
print(root, file)
doRead(root, os.path.join(root, file))
print('JOB END...')

 


이전 글에서도 한번 해 보았던 기억이 있기는 합니다. 이번에 조금 더 수정을 해 보았습니다.


 


실행결과



 


이번에는 앱에 정리 되어 있는 strings.xml 파일을 찾아서 한 줄씩 읽어 한국어 파일을 만들고 values-ko 폴더에 저장하는 것 까지을 한 번에 해 보았습니다. 그렇게 하고 앱을 실행해 보면 한국 어을 모르던 앱이 한국어를 표시하게 됩니다. 


 


다만,  gemini api 을 호출할 때 번역을 조금 자연스럽게 해 달라고 prompt을 만들었더니, 조금은 앱이 이상한(?) 표현을 할 수 도 있습니다.


 



prompt = '''
Translate English sentences '{0}' into Korean naturally. Use expressions that feel natural to Korean speakers.
'''.format(orgString)


 


번역은 자연스럽게 하기는 하겠지만, 그런 것이 앱에서 표현 되는 게 맞는 가 싶기도 합니다.  아무튼...


 


번역된 앱 실행 모습



 


한국어로 표시를 하기 시작했습니다. ㅋ~


 


한국어가 표시 되도록 수정된 github 링크을 공유해  드려요.   원작자의 코드을 fork 해서 수정한 버전 임을 알려 드려요.


 


https://github.com/nari4169/Smart-AutoClicker



 


GitHub - nari4169/Smart-AutoClicker: An open-source auto clicker on images for Android


An open-source auto clicker on images for Android. Contribute to nari4169/Smart-AutoClicker development by creating an account on GitHub.


github.com




 


 





오늘의 이야기

MAD(Modern Android Development)란 무엇인가?

• MAD(Modern Android Development)는 최신 기술을 사용하여 더 나은 앱을 더 빠르고 쉽게 구축하는 방법을 알려주는 일련의 비디오 및 기사입니다.

• MAD는 단순히 코드를 작성하는 것이 아니라 예외적인 경험을 만드는 것에 관한 것입니다.

• 시각적으로 놀라울 뿐만 아니라 쉽게 매끄럽고 성능이 뛰어난 앱을 구축하기 위해 최신 도구와 모범 사례의 힘을 활용하는 것입니다.

• MAD의 핵심 구성 요소는 직관적 인터페이스, 반응성능, 원활한 데이터 관리, 모듈러 아키텍처, 현대 공구입니다.

• 직관적 인터페이스는 제트팩 컴포즈와 자재 3이 조화롭게 작동하여 손끝이 자연스럽게 확장된 것처럼 느껴지는 아름답고 사용자 친화적인 UI를 만듭니다.

• 반응성능은 Kotlin Coroutines and Flow가 동시성과 반응성의 힘을 발휘하여 무거운 부하에도 앱을 반응성 있고 효율적으로 유지합니다.

• 원활한 데이터 관리를 위해 Ktor와의 강력한 네트워킹에서 Room과의 오프라인 지속성에 이르기까지 앱이 필요한 데이터에 언제 어디서나 액세스할 수 있도록 보장합니다.

https://zoewave.medium.com/production-mad-android-app-726c2e0bcf3f

Pro Modern Android Dev (MAD)

This doc tries to manage the complexity of a MAD*

zoewave.medium.com





오늘의 이야기


#스하리1000명프로젝트,
韓国で迷子になりましたか?韓国語が話せなくても、このアプリを使えば簡単に移動できます。
あなたの言語で話すだけで、翻訳、検索が行われ、結果があなたの言語で表示されます。
旅行者に最適!英語、日本語、中国語、ベトナム語などを含む 10 以上の言語をサポートします。
今すぐ試してみましょう!
https://play.google.com/store/apps/details?id=com.billcoreatech.opdgang1127




2026/04/01

오늘의 이야기

build gradle 설정'



오늘 갑자기 빌드를 하는데... 오류가 나왔습니다. 


FAILURE: Build failed with an exception.

* What went wrong:
Circular dependency between the following tasks:
:app:extractDeepLinksDemoDebug
\--- :app:injectCrashlyticsMappingFileIdDemoDebug
\--- :app:kspDemoDebugKotlin
\--- :app:processDemoDebugResources
+--- :app:mapDemoDebugSourceSetPaths
| \--- :app:injectCrashlyticsMappingFileIdDemoDebug (*)
+--- :app:mergeDemoDebugResources
| \--- :app:injectCrashlyticsMappingFileIdDemoDebug (*)
+--- :app:parseDemoDebugLocalResources
| \--- :app:packageDemoDebugResources
| \--- :app:injectCrashlyticsMappingFileIdDemoDebug (*)
+--- :app:processDemoDebugManifest
| \--- :app:processDemoDebugMainManifest
| \--- :app:extractDeepLinksDemoDebug (*)
\--- :app:processDemoDebugManifestForPackage
\--- :app:processDemoDebugManifest (*)

 


 


구글링을 통해 알아본 바로는...


 


https://github.com/firebase/firebase-android-sdk/issues/5930



 


"Circular dependency" with `injectCrashlyticsMappingFileId` task in `firebase-crashlytics-gradle` version `3.0.0` · Issue #593


[READ] Step 1: Are you in the right place? yes [REQUIRED] Step 2: Describe your environment Using https://github.com/android/nowinandroid on main at commit afad1b9a [REQUIRED] Step 3: Describe the ...


github.com




 


이 글에서 원인을 찾을 수 있었습니다.


 


buildscript {
ext {
compose_version = '1.6.0'
raamcosta_version = '1.9.54'
}
dependencies {
classpath 'com.android.tools.build:gradle:8.4.0'
classpath 'com.google.gms:google-services:4.4.1'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9' // 3.0.0 에서는 빌드 오류 ?
}
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.4.0' apply false
id 'com.android.library' version '8.4.0' apply false
id 'org.jetbrains.kotlin.android' version '1.9.23' apply false
}

 


com.google.firebase:firebase-crashlytics-gradle 가 패치가 되기는 한 것 같은데... 그것이 오류를 발생시키고 있다는 사실을...


 


다음 확인이 될 때 까지는 패치를 적용할 수 없을 것 같습니다.  ㅠㅠ


 


 





오늘의 이야기

안드로이드 오리엔테이션 API 업데이트: 정밀한 장치 오리엔테이션 측정을 위한 센서 융합

compass



• 안드로이드의 새로운 오리엔테이션 API는 가속도계, 자이로스코프, 자력계 데이터를 융합하여 장치 오리엔테이션 계산을 단순화합니다. 따라서 보다 정확하고 일관된 측정을 제공합니다.

• API를 사용하려면 Google Play 위치 서비스를 버전 21.2.0으로 업데이트하고 융합 오리엔테이션 제공업체 클라이언트를 얻습니다.

• 원하는 대기 시간 및 실행기를 지정하여 오리엔테이션 업데이트를 수신하기 위해 청취자를 등록합니다. API는 앱이 전경에 있을 때만 샘플을 제공합니다.

• API는 방향 정보에 액세스하기 위한 다양한 방법을 제공하며, 여기에는 방향, 방향 오류 및 태도가 포함된다.

• 이전에는 개발자가 가속도계 및 자이로스코프 데이터에서 회전 행렬과 방향 각도를 수동으로 계산해야 했다. 새로운 API는 이 프로세스를 단순화합니다.

• 융합된 배향 API의 구현을 입증하기 위해 샘플 코드가 제공된다.

• API를 제트팩 컴포즈, 힐트 및 지도 회전을 위한 저장소와 통합하는 예도 포함된다.

https://proandroiddev.com/update-for-your-compass-new-android-orientation-api-dc4e5c25ca35

Update For Your Compass — New Android Orientation API

Android provides a new Fused Orientation API from multiple sensors

proandroiddev.com





오늘의 이야기



#스치니1000프로젝트 #재미 #행운기원 #Compose #Firebase

🎯 야 너 토요일마다 로또 확인하냐?
나도 맨날 "혹시나~" 하면서 봤거든 ㅋㅋ

근데 이제는 그냥 안 해
AI한테 맡겼어 🤖✨

그것도 구글 Gemini로다가!

그래서 앱 하나 만들었지
👉 "로또 예상번호 by Gemini" 🎱

AI가 분석해서 번호 딱! 뽑아줌
그냥 보고 참고만 하면 됨

재미로 해도 좋고…
혹시 모르는 거잖아? 😏


https://play.google.com/store/apps/details?id=com.billcorea.gptlotto1127




오늘의 이야기

안드로이드 스튜디오의 Gemini 로부터 코드 보호: 지적 재산권 보안 보장

gemini 가 android code 배우기



• 안드로이드 스튜디오에 제미니가 도입되면서 개발자는 프로젝트 코드를 기반으로 질문을 하고 지능적인 응답을 받을 수 있게 됐다. 그러나 민감하거나 독점적인 코드를 구글과 공유하면 지적 재산권 정책이 엄격한 조직에 대한 우려가 제기될 수 있다.

• 코드를 보호하기 위해 안드로이드 스튜디오는 코드 공유를 제어하는 옵션을 제공하여 사용자가 모든 프로젝트 코드, 특정 프로젝트 또는 전혀 공유하지 않을 것인지 선택할 수 있다. 또한 '프로젝트별 결정 요청' 옵션을 통해 특정 프로젝트에 대한 선택적 공유가 가능하다.

• 포괄적인 보호를 보장하기 위해 개발자는 디렉토리의 최상위 레벨에서 '.aiexclude'라는 빈 파일을 만들 수 있으며, 이 파일은 해당 디렉토리와 모든 하위 폴더에 대한 코드 공유를 차단합니다. 이 파일은 모든 개발자가 제외 사항을 준수하도록 소스 제어에 체크할 수 있습니다.

• 보다 세분화된 제어를 위해 개발자는 '.aiexclude' 파일을 '.gitignore' 파일처럼 취급하여 제외할 파일 이름 또는 확장자를 지정할 수 있다. 이렇게 하면 코드베이스의 원하는 부분만 보호되는 동시에 일반 질문에 제미니 스튜디오 봇을 사용할 수 있다.

https://proandroiddev.com/protect-your-code-from-gemini-in-android-studio-982a58e1ea2a

Protect your code from Gemini in Android Studio

The Studio Bot is great, but be sure you are not sharing proprietary code unintentionally

proandroiddev.com





오늘의 이야기


#스하리1000명프로젝트

스치니들!
내가 만든 이 앱은, 내 폰에 오는 알림 중에서 중요한 키워드가 있는 경우
등록해둔 친구에게 자동으로 전달해주는 앱이야 📲

예를 들어, 카드 결제 알림을 와이프나 자녀에게 보내주거나
이번 달 지출을 달력처럼 확인할 수도 있어!

앱을 함께 쓰려면 친구도 설치 & 로그인해줘야 해.
그래야 친구 목록에서 서로 선택할 수 있으니까~
서로 써보고 불편한 점 있으면 알려줘 🙏

👉 https://play.google.com/store/apps/details?id=com.nari.notify2kakao





오늘의 이야기

코틀린 코루틴에서 런블로킹과 런칭의 차이점 이해

안드로이드



• 이 기사는 런블로킹과 론칭의 거동을 구체적으로 비교하면서 코틀린 코루틴의 메커니즘을 탐구한다.

• 런블로킹은 코루틴 작업이 완료될 때까지 현재 스레드를 차단하는 코루틴을 실행하고, 런블로킹은 새로운 코루틴을 시작하고 라이프사이클을 나타내는 잡 인스턴스를 반환한다.

• RunBlocking을 주된 방법으로 사용하고 Child RunBlocking 하위 작업을 시작할 때 모든 작업이 완료될 때까지 메인 스레드가 차단되어 순차적으로 실행됩니다.

• 실행 차단 작업을 실행된 코루틴 내에서 포장하면 예상치 못한 행동이 발생하며, 실행되기 시작하지만 완료를 기다리지 않아 작업이 순서에 맞지 않게 실행됩니다.

• job.join()을 호출하면 작업과 관련된 모든 코루틴이 계속 진행하기 전에 완료되어 예상되는 순차 실행을 복원할 수 있습니다.

• 태스크1에 런블로킹 대신 런블로킹을 사용하면 태스크2가 태스크1 전에 완료되어 태스크1의 비차단 특성을 보여준다.

• 마지막으로, 발사된 코루틴 내의 모든 작업도 발사를 사용할 때, 실행 순서는 코루틴의 비동기적 특성으로 인해 더 복잡해지며, 작업은 비결정적 순서로 완료된다.

https://medium.com/google-developer-experts/kotlin-coroutine-mechanisms-runblocking-v-launch-386e1ae8e3c2

Kotlin Coroutine mechanisms: runBlocking v. launch

Introduction to coroutine behavior through playful examples

medium.com





오늘의 이야기

신협 전자금융



 


오늘은 전자세금계산서 발급을 시도해 보겠습니다.   국세청 홈텍스에서 개인 사업자 인증이 완료된 경우 전자 세금 계산서 발행을 할 수 있습니다. 


 


그전에 해야할 일이 있습니다.  전자 세금계산서 발행을 하려면 공동 인증서을 받아야 합니다.  물론 다른 방법으로 세무서에서 제공하는 보안카드을 이용할 수 있다고도 합니다. 하지만, 보안 카드을 받아야 하고 보관 해야 하는 번거러움을을 단순에 정리할 수 있습니다. 


 


금융기관이 아닌 다른 인증 기관에서 발행 하는 개인사업장 공동인 인증서는 최소 연간 8만원 이상의 비용을 요구 하고 있습니다.  수입이 많고 해야할 일이 많다면 비용 지출을 하고 준비을 할 수 있겠지만, 아직 소소한 수입만으로 지탱하고 있는 중이라서 최소 비용(4,400원)으로 인증서을 받아 보려고 합니다.


 


다만, 금융기관에서 인증서을 받으려면 최초 1회는 창구 방문이 필요 합니다.  사업자등록증을 가지고 방문을 해서 등록을 해야 합니다.  그 다음 부터는  해당 은행의 전자금융 페이지에서 발급 가능 합니다.


 


해마다 갱신을 해야 하는 데, 이번에 갱신 기간을 지난 다음 세금 계산서 발급을 하려다... 기억을 정리해 두고자 합니다.


전자세금계산서 발행은 국세청 홈텍스을 참고하시면 됩니다.


 


 





오늘의 이야기


#스하리1000명프로젝트,
外国人労働者と話すのが難しいこともありますよね?
簡単に役立つアプリを作りました!あなたは自分の言語で書き、他の人は自分の言語でそれを見ます。
設定に基づいて自動翻訳します。
簡単なチャットに非常に便利です。機会があったら見てみてください!
https://play.google.com/store/apps/details?id=com.billcoreatech.multichat416




오늘의 이야기

KMP: UI 및 Compose Multiplatform으로 안드로이드 앱을 iOS로 이동 ios • 이 기사는 코틀린 멀티플랫폼을 사용하여 기존 안드로이드 앱을 iOS로 마이그레이션하는 시리즈의 일부이다. 이 부분에서는 컴포즈 멀티플랫폼을 활용한 멀...