2026/03/24

오늘의 이야기

가을 이미지



가을을 맞이하면서 명심해야 할 50가지 상식적인 건강 팁은 다음과 같습니다.


 


1. 수분 섭취: 하루 종일 물을 충분히 섭취하세요.


2. 균형 잡힌 식단: 다양한 과일, 야채, 통곡물, 저지방 단백질, 건강한 지방을 섭취하세요.


3. 섭취량 조절: 과식을 피하기 위해 섭취량에 주의하세요.


4. 규칙적인 운동: 일주일에 최소 150분의 적당한 운동을 목표로 하세요.


5. 적절한 수면: 매일 밤 7~9시간의 양질의 수면을 취하세요.


6. 스트레스 관리: 명상, 심호흡과 같은 이완 기법을 연습하세요.


7. 손 씻기 : 세균 확산을 막기 위해 손을 자주 씻으세요.


8. 예방접종: 권장되는 예방접종에 대한 최신 정보를 확인하세요.


9. 정기 검진: 매년 건강 검진 및 검진 일정을 계획하세요.


10. 자외선 차단: 자외선 차단제와 보호복을 사용하여 피부 손상을 예방하세요.


11. 정신 건강: 정신 건강을 우선시하고 필요한 경우 도움을 구하십시오.


12. 설탕 섭취 제한: 단 음식과 음료 섭취를 줄이세요.


13. 금연: 흡연과 간접흡연을 피하세요.


14. 알코올 섭취를 제한하세요. 알코올이 있다면 적당히 섭취하세요.


15. 활동적인 상태 유지: 일상생활에 움직임을 포함시키세요.


16. 스트레칭 : 유연성을 향상시키기 위해 운동 전후에 스트레칭을 하세요.


17. 안전벨트 착용: 운전하거나 차량에 탑승할 때는 항상 안전벨트를 착용하십시오.


18. 화면 시간 제한: 특히 잠자리에 들기 전에 과도한 화면 시간을 최소화하세요.


19. 자세 인식: 허리와 목의 긴장을 예방하기 위해 좋은 자세를 유지하십시오.


20. 가공 식품 제한: 가공이 많이 된 식품보다는 가공되지 않은 전체 식품을 선택하십시오.


21. 몸의 소리에 귀를 기울이세요: 배고픔, 포만감, 피로 신호에 주의를 기울이세요.


22. 감사하는 마음을 실천하세요: 삶에 대한 긍정적인 시각을 기르세요.


23. 사회적 연결: 친구 및 가족과 의미 있는 관계를 육성합니다.


24. 인지 자극: 퍼즐, 독서, 학습을 통해 두뇌를 활동적으로 유지하세요.


25. 워밍업: 격렬한 운동을 하기 전에 워밍업을 합니다.


26. 쿨다운(Cool-Down): 운동 후 부상을 방지하기 위해 쿨다운을 합니다.


27. 건강한 간식: 칼로리가 없는 간식보다 영양이 풍부한 간식을 선택하세요.


28. 치과 관리: 정기적으로 이를 닦고 치실을 사용하십시오.


29. 카페인 제한: 더 나은 잠을 위해 카페인을 적당히 섭취하세요.


30. 신중한 식사: 천천히 먹고 한 입씩 맛보세요.


31. 균형 잡힌 아침 식사: 영양가 있는 아침 식사로 하루를 시작하세요.


32. 눈 관리: 화면으로부터 눈을 보호하고 필요한 경우 보호 안경을 착용하십시오.


33. 알레르기: 적절한 약물을 사용하여 알레르기와 계절 반응을 관리합니다.


34. 패스트푸드를 제한하세요. 고칼로리, 저 영양 패스트푸드 섭취를 줄이세요.


35. 강력한 관계: 지지적이고 긍정적인 사람들과 함께하십시오.


36. 알코올 대안: 사교 모임에서는 무알코올 음료를 선택하세요.


37. 붉은 고기 제한: 가금류, 생선, 식물성 식품과 같은 저지방 단백질 공급원을 선택하세요.


38. 야외 활동: 야외에서 신선한 공기와 햇빛을 받으며 시간을 보내세요.


39. 손 위생: 질병을 예방하기 위해 손 위생을 잘 실천하십시오.


40. 웃음: 웃게 만들고 기쁨을 주는 활동에 시간을 투자하세요.


41. 마음 챙김: 스트레스를 줄이고 웰빙을 향상하기 위해 마음 챙김을 실천하세요.


42. 문화적 민감성: 문화적 선호도와 관행을 존중하십시오.


43. 부상 예방 : 집과 야외에서 사고를 예방하기 위해 예방 조치를 취하십시오.


44. 건강 오일: 요리와 드레싱에 올리브 오일과 같은 건강한 오일을 사용하십시오.


45. 건강 검진: 혈압, 콜레스테롤과 같은 상태에 대한 검진을 최신 상태로 유지하세요.


46. ​​위생 관행: 전반적인 건강을 위해 개인위생을 유지하십시오.


47. 호흡 운동: 휴식과 스트레스 감소를 위해 심호흡을 연습하세요.


48. 비상 연락처: 즉시 사용할 수 있는 비상 연락처 목록을 보관하세요.


49. 신체 긍정성: 신체를 포용하고 외모뿐만 아니라 전반적인 건강에 집중하세요.


50. 호기심을 가지세요: 정보에 입각한 선택을 하기 위해 건강과 복지에 대해 계속 배우십시오.


 


건강하게 가을을 시작해 보세요.





오늘의 이야기

https://developer.android.com/jetpack/compose/bom/bom-mapping?hl=en 



 


BOM과 라이브러리 버전 매핑  |  Jetpack Compose  |  Android Developers


BOM과 라이브러리 버전 매핑 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 라이브러리 그룹 2022.10.00의 버전 2022.11.00의 버전 2022.12.00의 버전 2023.01.00의 버전


developer.android.com




이글은 인터넷에서 퍼온 글임을 밝혀 둡니다.

 


개발자 문서를 한글 버전으로 보면 아직 번역이 되지 않았는지 이 정보와는 다르게 이전 버전에 대한 이야기만 나옵니다. 그래서 영어 버전으로 페이지를 열어서 구글 번역기를 돌려 보았습니다.  역시 최신 버전에 대한 이야기가 나옵니다. 


 


이제 조금은 더 다양한 디자인으로 다양하게 앱을 만들어 볼 수 있을 듯합니다. 


 


이번 릴리스에서는 수정자 성능이 크게 향상되어 구성 시간이 최대 80% 향상되었습니다 .
우리는 다양한 Compose API에서 발생하는 할당을 면밀히 조사하고 여러 영역, 특히 그래픽 스택 및 벡터 리소스 로딩에서 총할당을 줄였습니다. 이는 Compose의 메모리 공간을 줄일 뿐만 아니라 메모리 할당에 소요되는 시간을 줄이고 가비지 수집을 줄임으로써 성능을 직접적으로 향상합니다.
BasicText수정자 작업을 지원하는 새로운 렌더링 시스템으로 전환하여 초기 구성 시간에 평균 22%의 이득을 가져왔고 텍스트가 포함된 복잡한 레이아웃의 한 벤치마크에서는 최대 70%의 이득을 가져왔습니다.

 


구글이 말하는 개선사항에서 발췌했습니다.  성능이 개선됩니다. 앱이 조금은 더 빠르게 동작을 한다는 이야기가 될 듯합니다. 


 


다른 링크에서 얻은 정보도 정리를 해 보았습니다. 


멀티플랫폼 1.5.0-beta01
Compose의 Kotlin 다중 플랫폼 측면에서도 많은 일이 일어나고 있습니다! 1.5.0-beta01에는 위에서 언급한 성능 향상 기능이 포함되어 있으며 다른 플랫폼에 대한 향상된 기능도 추가되었습니다. 아래에 몇 가지 주요 내용을 나열했지만 그 안에는 더 많은 내용이 있습니다.
🍎 iOS용 Compose 하이라이트
기본 스크롤 및 느낌(일반적인 iOS 고무밴드 느낌) 단순화된 다중 플랫폼 리소스 관리 San Francisco가 이제 기본 글꼴입니다. TextField수정 및 개선 사항이 WindowInsets추가되었습니다. 120hz 화면 지원(기존 60hz) 수정됨: 더 이상 설정할 필요가 없습니다 isStatic = true (iOS에서 Compose를 처음 접하는 많은 개발자가 겪는 문제).
🖥️ 데스크톱용 Compose 하이라이트
Segoe UI는 이제 Windows의 기본 글꼴입니다. Swing 상호 운용성 개선
🌐 웹용 Compose 하이라이트
Scrollbar이제 일반적으로 사용 가능합니다(데스크톱에만 사용 가능) 사용자 정의 캔버스 ID를 설정할 수 있습니다. CanvasBasedWindow
다시 한번 말씀드리지만, 제가 가장 흥미로웠던 몇 가지 하이라이트는 다음과 같습니다. 특히 iOS 업데이트를 통해 Compose Multiplatform이 기본 환경에 훨씬 더 가까워졌습니다. 각 릴리스에는 더 많은 내용이 있으므로 릴리스 노트(아래 링크)를 읽어 보시기 바랍니다.

 


결론
Compose 1.5는 Android, iOS, 데스크톱 및 웹의 전반적인 환경을 크게 향상합니다. 멀티플랫폼 Compose를 사용하여 더 많은 앱이 구축됨에 따라 품질이 지속적으로 향상되는 것을 보니 반갑습니다. 가장 좋은 점은 종속성을 업데이트하기만 하면 이러한 개선 사항을 거의 무료로 얻을 수 있다는 것입니다.

이 글은 다음 링크에서 참조하였습니다.


https://medium.com/@jacobras/compose-1-5-is-out-heres-why-it-s-the-most-exciting-release-so- far-665fbd51ea5c



 


Compose 1.5 is out — here's why it's the most exciting release so far!


Google released Jetpack Compose 1.5 stable! It's included in the 2023.08.00 BOM (Bill of Materials), which is available since yesterday…


medium.com




 


 


나날이 발전하는(?) 구글을 보면서 오늘도 하나를 배워 봅니다.


구글의 페이지 이미지 (인터넷 펌)



 





오늘의 이야기



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

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

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

그것도 구글 Gemini로다가!

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

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

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


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




오늘의 이야기

오늘은 시도해 보지는 못했지만, 혹시 시도해 보려는 분들을 위해 검색한 정보를 모아 보도록 하겠습니다.


ms 의 가이드 중에서



 


MicroSoft 가 제공하는 Azure database 도 안드로이드에서 접속해 사용해 볼 수 있을까요?  


 


https://learn.microsoft.com/en-us/sql/connect/jdbc/step-3-proof-of-concept-connecting-to-sql-using-java?view=sql-server-ver16 



 


Step 3: Connecting to SQL using Java - JDBC Driver for SQL Server


Step 3 is a proof of concept, which shows how you can connect to SQL Server using Java and JDBC. The basic examples demonstrate selecting and inserting data.


learn.microsoft.com




이런 가이드 들은 java 을 이용한 서버(?)에서 구현이 가능한 코드 등을 제공하고 있습니다.  저는 android에서 접속을 해야 하는 데 말입니다.  was로 구성을 하는 거나, android에서 구성하는 것의 차이는 아마도 지연이 발생하는 처리를 어떻게 하는 가 일 듯합니다. 


 


https://github.com/Azure/azure-mobile-services/blob/master/docs/mobile-services-android-get-started.md


 


샘플코드등은 여기에서도 얻을 수 있습니다. 아직 실행해 보지 않았던 부분이라서 적당한 예제 인지는 검증이 필요해 보이기는 합니다. 


 


안드로이드로 가기 위해서

이제 조금 더 정보가 필요해 보입니다. 그걸 해소 하기 위해서 chatGpt을 활용해 볼 수 있을 것 같습니다.  좀 더 상세한 이야기는 정리가 되면  수정해 보겠습니다. 


 


chatGPT 을 활용해 얻은 정보를 정리해 보겠습니다. 


 


먼저 gradle 파일에 추가를 해야 한다고 합니다.


dependencies {
// Other dependencies
implementation "com.microsoft.sqlserver:mssql-jdbc:9.2.1.jre11"
}

 


이제 연결을 구현하는 코드를 가져와 봅니다. 


 


연결이 되었다면 그 다음 조회 하는 처리를 구현한 코드를 보겠습니다.  다만, chatGPT 는 android 에서 처리를 해야 한다고 하니, Thread 을 이용한 코드로 전환을 해 주었습니다.


import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import java.sql.Connection
import java.sql.DriverManager

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

connectToDatabase()
}

private fun connectToDatabase() {
Thread {
val connectionString = "jdbc:sqlserver://your-server-name.database.windows.net:1433;database=your-database-name"
val username = "your-username"
val password = "your-password"

var connection: Connection? = null

try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
connection = DriverManager.getConnection(connectionString, username, password)

// Now you can perform database operations using the 'connection' object.
} catch (e: Exception) {
e.printStackTrace()
} finally {
connection?.close()
}
}.start()
}
}

 manifest 에 internet 을 접속할 수 있는 권한은 추가 해야 합니다. 그래야 접속을 시도해 볼 수 있으니까요? 


 


이제 접속 테스트는 해 볼 수 있을 것 같습니다.  Thread 을 이용하는 것 보다는 lifecycleScope 을 이용하는 방식으로 수정을 해 보는 것이 kotlin 에 조금더 접합한 코드가 되지 않을 까 하는 생각이 듭니다. 


 


접속이 되었으니 select 하는 구문등은 상상으로 남겨 두겠습니다. 


 


다만, 이렇게 접속 DB 접속을 하는 코드 구현은 추천하지 않습니다. 요즘은 워낙 debugging 을 잘 하기 때문에 DB 접속에 대한 정보가 누출된 소지가 있습니다.  그런 부분은 관리자의 역량으로 남겨 두겠습니다.





오늘의 이야기


#스하리1000명프로젝트

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

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

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

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





오늘의 이야기

읽어오 정보 예시



 


오늘 이야기는 저 이미지와 같이 읽어 정보를 이용해서 해당 게시 홈페이지의 글들 중에서 최신 글을 찾아 열어 볼 수 있는 기능 구현 이야기를 이어 보겠습니다.


 


먼저 gradle  파일에 jsoup 사용을 위해 추가합니다. python에서는 beautifulsoup 같이 html 문서의 파싱을 등을 할 수 있습니다. 



// jsoup
implementation 'org.jsoup:jsoup:1.16.1'


 


url 정보를 받아 왔다면 이제 그 페이지를 열어서 받아온 html 문서의 내용에서 최신글을 번호를 확인해 볼 수 있는 기능 구현 코드를 보겠습니다. 


 



		var newUrl = "여기에 다가 게시자의 티스토리 블로그 URL 을 넣어 줍니다."

CoroutineScope(Dispatchers.IO).launch {
try {
val doc = Jsoup.connect(url).get()
// val document = Jsoup.parse(doc.html().trimIndent())
var detailTitleLinks = doc.select("div.detail a.title.link.link-primary")
if (detailTitleLinks.isEmpty()) {
detailTitleLinks = doc.select("div.article-content a.link-article")
}
if (detailTitleLinks.isEmpty()) {
detailTitleLinks = doc.select("div.list_content a.thumbnail_post")
}
if (detailTitleLinks.isEmpty()) {
detailTitleLinks = doc.select("div.post-item")
}
if (detailTitleLinks.isEmpty()) {
detailTitleLinks = doc.select("div.posts li a")
}
if (detailTitleLinks.isEmpty()) {
Log.e("", "doc = $doc")
}
for (link in detailTitleLinks) {
var detailHref = link.attr("href")
if (detailHref.isEmpty()) {
detailHref = link.selectFirst("a")?.attr("href").toString()
}
Log.e("", "Detail Href: $detailHref")
if (detailHref.isNotBlank()) {
newUrl = "$url/m$detailHref"
break
}
}
Log.e("", "newUrl = $newUrl")

val intent = Intent(Intent.ACTION_VIEW, Uri.parse(newUrl))
startActivity(intent)

} catch (e : Exception) {
Log.e("", "error = ${e.localizedMessage}")
}
}


위 예시 코드와 같은 함수를 하나 만들어 두면 됩니다.그럼 최신글 번호를 찾아서 바로 열어 줍니다.  이렇게 구분을 여러 가지로 해 보는 것은 티스토리 페이지가 스킨에 따라 달라지는 부분들이 있기 때문입니다. 


 


이제 다음으로 넘어가 봐야 할 텐데... 잘 될지는 모르겠습니다. 


 






오늘의 이야기

생화 라나?



94년8월에도
23년 8월에도
난 서울로 향한다.

그곳에서의 생활이 궁금해 하면서...

94년엔 친구들이 서울에 있었다면
23년엔 서울에 딸이 산다.

어떤 일이 날 기다리는 가?
어떤 날들이 날 기다리는 가?

새로운 생활을 시작해 보는 거다.





오늘의 이야기


#스하리1000명프로젝트,
A veces es difícil hablar con trabajadores extranjeros, ¿verdad?
¡Hice una aplicación sencilla que ayuda! Escribes en tu idioma y los demás lo ven en el suyo.
Se traduce automáticamente según la configuración.
Súper útil para chatear fácilmente. ¡Echa un vistazo cuando tengas la oportunidad!
https://play.google.com/store/apps/details?id=com.billcoreatech.multichat416




오늘의 이야기

이번주는 유난히도 날씨가 오락 가락 하는 한 주였던 거 같습니다.  오늘은 비가 무진장 내린 후 바다를 바라보다가 저 멀리 보길도 끝 무렵의 섬들이 보이는 것을 알게 되어  갤럭시 23 울트라의  줌 사진 비교를 한 번 올려 볼까 합니다.


 


1배

1배



 


30배 줌 

30배



 


70배

70배



 


100 배 중

100배



 


1배 기본 사진에서 이 섬을 찾아 보세요... 보이시나요?   그 옆으로 보이는 섬들이 보길도 등등의 섬들이지 않을까 싶습니다.  100배 줌으로 보이는 섬은 대관탈도라는 섬으로 인식되기는 합니다.   제주에서 추자도를 바라보면 중간에  있는 섬입니다.  대략 거래는 30Km 정도 되는 것으로 보이는데 이 정도의 Zoom이라면... 어떨까요?


 


날이 이제 가을로 넘어 갈 듯합니다. 아직도 덥기는 하지만요...  행복한 주말 보내세요.






오늘의 이야기

오늘은 새로운 댓글이 달리는 것들을 하나씩 열어 보는데 힘들어하는 나를 위해서 앱을 하나 구현해 볼까 합니다.   최종적으로는 댓글에 대한 답글로 자동화해 보는 것이 바람입니다. ㅋ~  (이런 건 그다지 좋아라 하지 않으시기는 하던데 뭐...)


 


댓글 달기가 본업(?)이 아닌지라... python  으로는 여러 가지 공부를 해 보기는 했으나, 이번에 kotlin 코드를 작성해 보았습니다. 


 


그래 들 설정 추가 하기


// jsoup
implementation 'org.jsoup:jsoup:1.16.1'


python에서 사용했던 Betifulsoup 가 비슷한 라이브러리가 있음을 알게 되었습니다. 저걸 build gradle 파일에 추가합니다. 


 



// coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"


이것들은 async 처리를 하기 위해서는 필요합니다. async 보다는 android 가 UI 가 활성화 되어 있는 경우 처리 지연이 발생하는 것을 그다지 좋게 보지 않기 때문에 지연처리를 할 수 있도록 한다고 보는 것이 이해가 쉬울 듯합니다. 


 


이전 게시글 (파이썬으로 댓글 답 달기)

다음은 새 댓글을 읽어오는 부분을 구현해 보아야 하는데, 이전 글 하나를 잠깐 보고 오겠습니다. 


https://billcorea.tistory.com/100



 


파이썬 으로 따라하는 자동화 스크립트 : 댓글에 답글 달기


오호라... 피트에 있는 글들에 글을 달기 시작했더니, 방문해 주시고 댓글도 달아주시고... 감사 감사... 이런걸 말로만 해서는 안되고 댓글에 또한 댓글로 인사를 해야 할 것 같앗 티스토리 API 을


billcorea.tistory.com




python  으로 게시물 댓글에 자동 답글을 다는 이야기를 적었던 부분인데, 예전에 기술했던 글이라 정리가 좀 미흡해 보이기는 합니다.   이제 필요한 것은  accessToken을 얻어야 하는 데, 이 부분이 번거로운 부분이 될 듯합니다.  그 이야기는 뒤에 다시 해 보도록 하겠습니다. 


 


tistory API 인증 알아보기

accessToken 을 받기 위해서는 인증을 거쳐야 합니다.  저 python 예시 나와 있는 이런저런 코드에 대한 설명이 부족하여 보기는 힘들어 보이지만.


 


https://tistory.github.io/document-tistory-apis/auth/authorization_code.html



 


Authorization Code 방식 · GitBook


No results matching ""


tistory.github.io




 


그전에 앱 등록을 해야 합니다. https://www.tistory.com/guide/api/manage/register 에서 아래 그림과 같이 나오면 등록을 해 줍니다.



등록예시



이렇게 등록해 주면 App ID, Secret Key을 얻게 됩니다. 


 


먼저 아래 URL 을 만들어 크롬이나, 에지 등에서 검색을 해 봅니다.


https://www.tistory.com/oauth/authorize?client_id=&redirect_uri={1}&response_type=code&state=someValue

여기서  {0} 에는 app ID 값으로 치환하고,  {1}는 위에 등록한 callback 주소를 입력하면 됩니다.  잘 입력을 했다면 아래 그림처럼 권한 허가를 요구하는 페이지가 보일 겁니다.




 


잘 되었다면 아래 그림과 같이 다음 페이지로 돌아 옵니다. 이때 URL에 표시된 내용들 중에 code= 뒤에 따라오는 숫자를 복사해 두어야 합니다.


code 얻기



 


다음은 아래 코드와 같이 url 을 조립해야 합니다.


https://www.tistory.com/oauth/access_token?client_id={0}&client_secret={1}&redirect_uri={2}&code={3}&grant_type=authorization_code

{0} 위에서 처럼 app id 을 넣고 {1] 위에서 확인되는 Secret Key 값을 넣습니다. {2} 에는 callback 주소로 치환하고 {3} 에는 방금 얻어온  code 뒤에 값을 채워 url을 만든 다음 크롬이나 에지 등에 입력하면 accessToken을 얻을 수 있습니다. 


 


새로운 댓글 목록 받아 오기

이제 API 가이드를 보면서 댓글 목록을 받아 오겠습니다. REST API 을 호출하도록 하고 있어서 저는 retrofit을 이용해서 해 보고자 합니다.


 



// retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'


 


gradle 파일에 최근 버전으로 추가 했습니다.  그리고 API 호출을 위해서 코드 하나를 작성했습니다. 


 


import com.google.gson.Gson
import com.google.gson.GsonBuilder
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Query
import java.lang.reflect.Type

interface RetrofitAPI {

@Headers("Content-Type: application/json;charset=UTF-8")
@GET("comment/newest")
fun doGetNewest(
@Query("access_token") accessToken : String,
@Query("output") output : String,
@Query("blogName") blogName : String,
@Query("page") page : Int,
@Query("count") count : Int,
): Call<NewestResponseMain>

companion object {
private const val baseURL = "https://www.tistory.com/apis/"
private val client = OkHttpClient.Builder().build()
private val gson : Gson = GsonBuilder().setLenient().create()

private val nullOnEmptyConverterFactory = object : Converter.Factory() {
fun converterFactory() = this
override fun responseBodyConverter(type: Type, annotations: Array<out Annotation>, retrofit: Retrofit) = object :
Converter<ResponseBody, Any?> {
val nextResponseBodyConverter = retrofit.nextResponseBodyConverter<Any?>(converterFactory(), type, annotations)
override fun convert(value: ResponseBody) = if (value.contentLength() != 0L) {
try{
nextResponseBodyConverter.convert(value)
}catch (e:Exception){
e.printStackTrace()
null
}
} else{
null
}
}
}

fun create(): RetrofitAPI {
return Retrofit.Builder()
.baseUrl(baseURL)
.addConverterFactory(nullOnEmptyConverterFactory)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build()
.create(RetrofitAPI::class.java)
}

}

}

그리고 데이터를 받아올 구조체 하나가 필요 합니다.  그래서 다음과 같이 만들었습니다.


 



data class NewestResponse(
val id : String, // 댓글 ID
val date : String, // 댓글 작성시간 timeStamp
val postId : String, // 작성된글 ID
val name : String, // 작성자
val homepage : String, // 작성자 홈페이지 주소
val comment : String, // 댓글 내용
val open : String, // Y 공개, N 비공개
val link : String,
)

data class NewestResponseMain(
val tistory : NewestItem
)

data class NewestItem(
val item : NewestComments
)

data class NewestComments(
val url : String,
val secondaryUrl : String,
val comments : ArrayList<NewestResponse>
)


실제 호출에서는 NewestResponseMain 을 이용합니다. 사유는 API 가이드를 보면 json 응답 모양을 보고 만들었습니다.


아래 응답 예시를 보면 tistory 를 큰 block으로 해서 item 아래 comments  아래 comment을 들어가야 세부 목록을 볼 수 있습니다.  그래서 모양은 이렇게 구현했습니다.


응답값 예


{
"tistory":{
"status":"200",
"item":{
"url":"http://oauth.tistory.com",
"secondaryUrl":"",
"comments":{
"comment":[
{
"id":"8176926",
"date":"1303796900",
"postId":"4",
"name":"Tistory API",
"homepage":"http://oauth.tistory.com",
"comment":"비루한 글에 칭찬을 하시니 몸둘바를 모르.. 지 않아!",
"open":"Y"
},
{
"id":"8176923",
"date":"1303796801",
"postId":"4",
"name":"글쎄 요",
"homepage":"http://shesgone.com",
"comment":"제 홈에 와서 구경해보세요^_^",
"open":"N"
},
{
"id":"8176918",
"date":"1303796711",
"postId":"4",
"name":"지나다가",
"homepage":"http://someurl.com",
"comment":"좋은 글 감사합니다.",
"open":"Y"
}
]
}
}
}
}

 


이제 호출을 구현해 보겠습니다. 


 



RetrofitAPI.create().doGetNewest(accessToken = accessToken, output = "json", blogName = "billcorea", page = pageIndex, count = 15)
.enqueue(object : Callback<NewestResponseMain> {
override fun onResponse(
call: Call<NewestResponseMain>,
response: Response<NewestResponseMain>
) {
if (response.code() == responseOk && response.body() != null) {
newests.clear()
for (item in response.body()?.tistory?.item?.comments!!) {
if (item.name != "Billcorea") {
newests.add(item)
}
}
Log.e("", "size = ${newests.size}")
} else {
Toast.makeText(context, context.getString(R.string.msgDoNotData), Toast.LENGTH_SHORT).show()
}
isActivie.value = false
}

override fun onFailure(call: Call<NewestResponseMain>, t: Throwable) {
Toast.makeText(context, context.getString(R.string.msgDoNotData, t.localizedMessage), Toast.LENGTH_SHORT).show()
}
})


 


output 은 json 타입으로 받아서 분석을 할 예정이라 json으로 기술되었으며, blogname 은 우리 블로그 URL의 prefix을 적어 둡니다.  이제 응답이 오면 어떻게 될까요?


 


조회화면



이제 이 앱을 통해서 더 열심히(?) 찾아보도록 하겠습니다.  저기 URL 주소를 클릭하면 해당 블로그의 제일 마지막 게시글을 찾아서 이동합니다. (아직 개발 중이라 안 되는 페이지도 있을 수 있습니다.  블로그 마다 테마 설정에 따라 tag 값들이 달라지기 때문에 안되는 페이지는 하나씩 보완을 해야 할 것 같습니다.)





오늘의 이야기


#billcorea #운동동아리관리앱
🏸 Schneedle, ¡una aplicación imprescindible para los clubes de bádminton!
👉 Match Play: registra puntuaciones y encuentra oponentes 🎉
¡Perfecto para cualquier lugar, solo, con amigos o en un club! 🤝
Si te gusta el bádminton, definitivamente pruébalo.

Ir a la aplicación 👉 https://play.google.com/store/apps/details?id=com.billcorea.matchplay




오늘의 이야기

가을 이미지 가을을 맞이하면서 명심해야 할 50가지 상식적인 건강 팁은 다음과 같습니다.   1. 수분 섭취: 하루 종일 물을 충분히 섭취하세요. 2. 균형 잡힌 식단: 다양한 과일, 야채, 통곡물, 저지방 단백질, 건강한 지방을 섭취하세요. 3....