현재 개발중인 웹서비스는 bootstrap 5 로 개발중에 있다.

그리고 해당 웹서비스의 사용 방법을 안내하고 사용자 경험을 향상시키기 위해 온보딩 라이브러리를 도입하려는데

처음엔 bootstrap tour 라는 솔루션을 발견하여 이름도 bootstrap 이 들어갔기에 bootstrap5와 궁합도 잘 맞을거라 생각하고 테스트를 시도했다.

하지만 5분여만에 포기하게 되었는데 그 이유는 적용하자마자 발생한 스크립트 오류와 마지막 릴리즈가 2017년 8월이라는 것이었다.

그래서 Copilot 에게 bootstrap5 에서 사용가능한 bootstrap tour 와 유사한 솔루션들을 물어보았다.

다음은 답변으로 전달 받은 목록들이다.

  1. bs5-intro-tour
    > https://iprogramista.pl/Bs5IntroTour
  2. intro.js
    > https://introjs.com/
    > https://blog.naver.com/happycgi/222115121163
  3. driver.js
    > https://driverjs.com/
    > https://youtu.be/oHXkrHWqSTg?si=1pTYkH9pfS4tT_ky
  4. UserGuiding
    > https://userguiding.com/blog/bootstrap-tour-alternatives

위 목록중 1번은 포루투갈인의 사이트로 예상된다.

나머지 솔루션들은 libhunt.com 사이트에서도 추천해주는 라이브러리들인데 -> https://www.libhunt.com/r/bootstrap-tour

모두 오픈 소스들이다.

다만 intro.js 와 UserGuiding 은 좀더 사용자층이 넓고 상용화 버전까지 있어서 라이브러리에 대한 신뢰도도 있지만 상업용 사이트에서 사용하기 위해서는 intro.js 는 $50로 UserGuiding 은 월 $89 유료 결재가 필요하다.

그래서 driver.js 의 라이센스를 살펴보니 MIT 이다. (개인이든 기업이든 무료)

다만 오픈 소스의 문제점은 프로그램의 안정성과 불순한(?) 코드의 유입이 있다.

공짜로 편리하게 이용하고자 사용하는 오픈소스 라이브러리이지만 서비스 해킹의 위협을 받을 수도 있기 때문에 조심스러울 수 밖에 없다.

 

 

Intro

나는 2008년부터 유지해온 도메인 한개와 2023년부터 새롭게 추가한 도메인 한개로 총 2개의 도메인을 소유하고 있다.

이들 도메인을 통해 web, ftp 서버들을 운영중이며 해당 도메인들에 무료 인증서들을 설치하여 ssl 서비스를 제공하고 있었다.
그리고 무료 인증서는 Let's Encrypt 라는 인증 기관을 통해서 제공 받고 있다.

위 내용은 수년동안 잘 이용하던 무료 보안 서비스에 대한 개요의 시작이며
여기엔 Let's Encrypt, Certbot, Win-ACME 등의 키워드들이 등장한다.
그래서 프롤로그는 copilot 이 설명해준 위 키워드들에 대한 정의로 시작한다.
 

Prologue

ChatGPT 는 너무나 편리하다.
항상 내 옆에서 내가 필요로 하는 소소한 정보들을 자세하게 친절히 알려준다.
수년간 Let's Encrypt 를 통해 무료 인증서를 발급 받아 사용해 왔지만
발급받기 위해 사용한 certbot 이라는 프로그램조차 어디서 만들고 인증서를 어떤 경유로 받아오는지 알지 못했었다. ^^;
아래와 같이 copilot 이 정리해준 덕분에 내가 이용하는 프로그램의 특성도 쉽게 알 수 있었다.

Let’s Encrypt는 무료 SSL/TLS 인증서를 발급하는 인증 기관입니다. 
이때, Let’s Encrypt에서는 ACME(Automatic Certificate Management Environment) 프로토콜을 사용하여 지정된 도메인 이름을 제어하는지 확인하고 인증서를 발급합니다.

Certbot과 Win-ACME는 모두 ACME 프로토콜을 구현한 클라이언트 도구로, 이 도구들을 통해 사용자는 ACME를 지원하는 인증 기관에서 SSL/TLS 인증서를 쉽게 관리할 수 있습니다.

Certbot은 전자 프론티어 재단 (EFF)에서 개발한 무료 오픈 소스 도구로, SSL/TLS 인증서를 요청하거나 취소하는 데 사용됩니다. 
Certbot은 ACME 프로토콜을 사용하여 인증서를 발급받습니다. 
대부분의 경우 Certbot 클라이언트에서 시작할 것을 권장하며, 원하는 항목에 따라 간단히 인증서를 받거나 설치에도 도움이 될 수 있습니다.

Win-ACME는 Windows 환경에서 Let’s Encrypt 인증서를 쉽게 설치하고 관리할 수 있도록 도와주는 도구입니다. 
Win-ACME는 ACME 프로토콜을 구현하며, 이 도구를 통해 사용자는 Windows 서버에서 SSL/TLS 인증서를 쉽게 발급하고 관리할 수 있습니다.

따라서, Certbot과 Win-ACME는 모두 Let’s Encrypt와 같은 ACME를 지원하는 인증 기관에서 SSL/TLS 인증서를 발급받는 데 사용되는 도구입니다. 
이 두 도구는 각각 리눅스와 윈도우 환경에서 사용되며, 사용자의 요구에 따라 적절한 도구를 선택하여 사용할 수 있습니다.

 

인증서 갱신의 실패

그동안 무료 인증서를 발급 받으면서 3년여동안 사용한 프로그램은 certbot 이었다.
certbot 은 여러 os 환경을 지원해주는데 나는 관리 편이상 windows 환경을 선호하였기에 windows 버전의 certbot 을 애용하였고 이에 대한 배포 절차 문서까지 작성해서 인증서 관리를 매우 효율적으로 작업하였다.

초기에 구축했던 환경은 docker 를 이용한 linux 환경이었는데,
linux 에서 인증서 파일을 발급받아 windows 로 옮기는 번거로움과 가상 환경의 os 도 관리해야만 하는 관리 포인트의 복잡성이 너무나 불편해서 순수 windows 로만 관리하게끔 certbot 프로그램을 windows 용으로만 사용하고 있었다.

그런데 바로 어제 올해 2월에 발급받은 인증서가 만료됨에 따라서 새로운 인증서로 갱신하기 위해 문서를 열어 그동안 수없이 수행했던 절차를 진행했는데,
하루 꼬박 걸려 시도해봐도 좀처럼 새로운 인증서 갱신이 성공하지를 못했다.
그리고 오늘 오전에서야 그 원인을 알게 되었고, 그에 대한 기록을 이렇게 남겨놓는다.

사실 위와 같은 문제는 작년말 인증서를 갱신할때도 일시적인 장애로 동일한 문제를 겪었던 기억이 있는데,
단 며칠만에 정상화되길래 당시에 별다른 조치없이 그대로 현재까지 인증서 갱신 절차를 유지해왔었다.
하지만 어제 재발급 시도하면서 동일한 오류를 또 접하면서 이번 문제는 쉽게 해결될 수 없음을 직감하였다.

원인은 'Certbot, 2024년 Windows 베타 지원 중단' 때문이다.
내용은 Certbot Discontinuing Windows Beta Support in 2024 - Client dev - Let's Encrypt Community Support (letsencrypt.org) 문서에 나와 있다.

위와 같은 이유로 windows용 certbot 프로그램을 기존에 2.6 버전에서 2.9 버전으로까지 변경하며 인증서 갱신을 다시 시도해 봤지만 또다시 실패하였고 지금은 포기한 상태다.

크게 의미는 없지만 windows 용 certbot 프로그램의 마지막 버전은 다음의 경로에서 받을 수 있다.
-> Certbot - Browse /v2.9.0 at SourceForge.net

인증서 발급시 내가 겪은 오류는 dns txt record 변경을 통해 let's encrypt 의 dns challenges 를 시도시 failed 하는 오류였다.
이것은 나의 도메인을 호스팅하는 업체에 연결된 name server 와 전세계 dns 서버들에 저장된 txt record 값이 설정한 값과 일치하지 않아 발생하는 오류이다.
dig나 nslookup 으로는 정상적으로 출력되나 certbot 에서 엔터키를 입력한 순간엔 부정한 값으로 failed 되버리는 것이다.

원인은 알지만 해결책은... 쉽지 않다.
도메인 서버와 네임 서버 그리고 dns 서버까지 이들이 가진 데이터를 한번에 통일시키기 보다는 다른 방법을 찾는게 손쉬울 것 같다. (하루를 기다려도 모든 dns 서버들이 변경한 record 값을 가지지 못한다)
그래서 오류에 대한 구글링의 정보들을 살펴보았다.
수많은 문서들 중에 두개의 문서 정도가 잘 정제된 내용으로 보였다.

물론 그렇다고해서 위 문서들로 해결책을 찾은 것은 아니다.
왜냐하면 나는 도메인을 구매한 회사와 내 도메인의 포워딩 정보를 관리하는 회사가 다르기 때문에 이들을 통해 문제를 해결한다는 것은 매우 난해한 문제를 가지고 있다.

그래서 결과적으로는 dns 의 txt record 수정이 필요한 와일드카드(wildcard) 도메인 인증서를 포기하기로 최종 결정하였다.

win-acme 의 사용

와일드카드(wildcard) 인증서를 포기하기 전까지만 해도 나는 혹시 certbot 이 아닌 win-acme 로 발급 시도하면 어떨까?
혹시 성공할까? 기대를 했었다.
하지만 검색으로 찾아낸 여럿 문서들은 하나같이 내가 아는 수준에서의 발급 절차만 기재되었을뿐 별다른 추가 내용을 찾을 수 없었고
당연하게도 동일한 절차에서는 win-acme 로도 와일드카드(wildcard) 인증서는 동일한 오류로 인해 발급 받을 수 없었다.

메인 도메인과 서브 도메인들에 대해 각각 적용될 인증서를 발급 받는다면 와일드카드(wildcard) 도메인 인증서가 필요하지 않다.
나는 두개의 도메인을 소유하고 있고 서브 도메인은 세개가 있으므로 총 5개의 도메인에 대해서만 인증서를 발급받으면 된다.
갯수가 얼마 안되니 굳이 와일드카드(wildcard) 인증서에 연연하지 않아도 되었던 것이었다.

Epilogue

그렇게 인증서 발급 프로그램과 운영 정책을 바꾸면서 나는 이제 행복해졌다.
내 기억엔 2년전에 처음 dns txt record 오류를 만났을때 장장 보름을 고생했던 기억이 있다.
그때의 작업으로 인증서 발급 절차까지 수립하면서 2년을 무사고로 잘 보냈었는데...

이번에 certbot 의 windows 지원 종료와 dns txt record 오류의 재발은 또다시 나에게 3일간의 고통과 절망의 시간을 안겨 주었으며
그것으로 깨달은 점은 누군가와의 논쟁에서 정론을 논하게 되면 서로 합의하기가 너무나 어렵고 그로 인한 손실이 막대하다는 것이다.
하지만 서로가 조금씩 반걸음을 후퇴하여 양보를 통해 합의점을 찾게 되면 불가능한 일도 가능하게 된다.

과거 이전 회사에서 아무런 권한도 없이 그저 메신저 역할로써만 다양한 사람들간의 분쟁을 조정해주는 업무를 수행하며 당시에 참 곤욕스러웠던 일들을 상기해보면,
내가 상대하는 사람들이 가진 서로간의 이기심들을 알면서도 모른척하며 어떻게든 사람들을 조율 하는 것이 참 어려운 일이었구나... 라고 회상하게 되었다.
당시 나의 역할에 대한 한계를 더 상위의 누군가에게 종용 할수만 있었다면 아마 조율 업무 자체도 할만 했었을지도 모른다...
그래서 그들을 관찰하며 부서장들간의 보이지 않는 업무 협력 관계가 참 중요하다는 것을 알게 되었다.
당시의 업무는 권한과 책임을 모두 갖추었어야만 무사히(?) 진행이 가능했는데
정작 그것을 갖춰야만 했던 사람들이 제대로 자기 역할을 못했던 것 같다.

 
 
 
 
 
 

이번에 주문한 생수에 침전물이 보인다.

끓였다가 식히면 더 잘 보인다.

그래서 조사했다.

 

* 천연미네랄 : 칼슘,마그네슘,나트륨 (https://www.goodmorningcc.com/news/articleView.html?idxno=297408)

* 생수안의 미네랄이 분유먹는 아기에게 미치는 영향
생수에 포함된 미네랄은 성인에게는 수돗물보다 효율적으로 미네랄을 섭취할 수 있는 장점이 있지만, 아기에게는 다를 수 있습니다. 
아기의 위장 면역력이 약하기 때문에, 생수 속 미네랄이 설사 등의 증상을 일으킬 수 있어 주의가 필요합니다¹[4]. 
특히, 분유를 탈 때 사용하는 물은 아기의 건강에 직접적인 영향을 미치므로, 미네랄 함량이 높은 생수를 사용할 경우에는 더욱 신중해야 합니다.

아기분유생수를 선택할 때는 다음과 같은 사항을 고려하는 것이 좋습니다:
- **미네랄 밸런스**: 아기의 뼈를 튼튼하게 하고 성장에 도움을 줄 수 있는 미네랄 밸런스가 중요합니다²[2].
- **안전성**: 무균상태로 유통되는 생수를 선택하여 세균 번식의 위험을 최소화합니다²[2].
- **미네랄 함량**: 일반 생수 대비 미네랄 함량이 높은 생수를 선택할 수도 있지만, 아기의 건강 상태와 의사의 조언을 고려해야 합니다²[2].

아기가 분유를 먹는 경우, 생수를 사용하기 전에 소아과 의사와 상담하는 것이 가장 안전한 방법입니다. 
의사는 아기의 건강 상태와 필요에 맞는 물의 종류를 추천해 줄 수 있습니다. 
또한, 분유에 사용되는 물은 멸균된 용기로 준비하는 것이 좋습니다³[6]. 
분유를 준비할 때는 항상 아기의 건강과 안전을 최우선으로 고려해야 합니다.

출처: Bing과의 대화, 2024. 4. 25.

 

* 미네랄 함유량이 많은 물로 분유를 타서 아기에게 먹일 경우 유의해야 할 사항
미네랄 함유량이 높은 물로 아기의 분유를 준비할 때는 몇 가지 중요한 사항을 고려해야 합니다. 
아기의 건강과 안전을 위해 다음 지침을 따르는 것이 좋습니다:

1. **미네랄 함량 확인**: 사용하는 물의 미네랄 함량, 특히 나트륨과 불소의 수치가 낮은지 확인하세요¹[4].
2. **물 끓이기**: 안전한 출처에서 얻은 물을 사용하더라도, 분유를 준비하기 전에 반드시 물을 끓여야 합니다. 물을 실온으로 식힌 후 사용하세요²[3].
3. **분유 제조 지침 준수**: 분유 제조사의 지침에 따라 정확한 양의 물과 분유를 사용하여 영양 불균형을 피하세요³[1]⁴[2].
4. **위생적인 준비**: 분유를 준비하기 전에 손을 깨끗이 씻고, 청결한 환경에서 분유를 준비하세요³[1].
5. **안전한 보관**: 분유를 준비한 후에는 적절한 온도에서 안전하게 보관하고, 빠른 시간 내에 사용하세요³[1].

아기가 2개월 미만이거나, 조산아이거나, 면역 체계가 약한 경우에는 크로노박터와 같은 세균 감염을 예방하기 위해 추가적인 주의가 필요합니다³[1]. 
분유를 준비할 때는 항상 아기의 건강과 안전을 최우선으로 고려해야 하며, 불확실한 경우에는 소아과 의사와 상담하는 것이 가장 좋습니다.

출처: Bing과의 대화, 2024. 4. 25.

 

* 분유먹는 아기가 과도하게 미네랄을 섭취한 경우 발생 할 수 있는 증상
분유를 먹는 아기가 과도하게 미네랄을 섭취한 경우, 다음과 같은 증상이 발생할 수 있습니다:

1. **무기력**: 아기가 피곤해 보이거나 활동량이 감소할 수 있습니다.
2. **복통**: 복부 통증이 나타날 수 있습니다.
3. **구토와 메스꺼움**: 아기가 구토를 자주 하거나 메스꺼워할 수 있습니다.
4. **식욕 부진**: 아기가 식사를 거부하거나 식욕이 떨어질 수 있습니다.
5. **변비**: 변이 불규칙하게 발생하거나 변비가 생길 수 있습니다.
6. **뇌에 영향**: 미네랄 중독으로 인해 뇌에 영향을 줄 수 있으며, 경련, 헤드헌팅, 혼란 등의 증상이 나타날 수 있습니다¹[1]²[2].

특히, 미네랄 중독은 아기의 건강에 심각한 영향을 미칠 수 있으므로, 미네랄 함유량이 높은 물이나 음식을 아기에게 제공할 때는 주의해야 합니다. 만약 아기가 이러한 증상을 보인다면 즉시 소아과 의사와 상담하여 적절한 조치를 취해야 합니다.

출처: Bing과의 대화, 2024. 4. 25.

Google API 는 Google Workspace 의 서비스들을 Program Library 나 REST 로 접근하여 제어할 수 있는 API 이다.
Google Workspace 에서 제공하는 서비스 목록은 다음과 같다.
Google Workspace  |  Google for Developers

 

Google Workspace  |  Google for Developers

Google Workspace 앱을 개선하고 연결.

developers.google.com

그중 Google Drive 를 접속하기 위해 java 와 javascript 라이브러리들을 조사했다.

Google API Client Libraries 목록은 다음과 같다.
API Client Libraries  |  Google for Developers

 

API Client Libraries  |  Google for Developers

클라이언트 라이브러리에 액세스하여 Google 제품용 API에 대한 코딩을 쉽게 할 수 있습니다. 자바, Python, PHP, .NET 등에 대한 지원을 포함합니다.

developers.google.com

위 링크의 문서에서 JavaScript 버전이 있는데 안에 들어가보면 조금(?)의 설명과 함께 몇가지 사용 예제는 있지만 내가 원하는 API Document 는 없다.
GitHub - google/google-api-javascript-client: Google APIs Client Library for browser JavaScript, aka gapi.

 

GitHub - google/google-api-javascript-client: Google APIs Client Library for browser JavaScript, aka gapi.

Google APIs Client Library for browser JavaScript, aka gapi. - google/google-api-javascript-client

github.com

어차피 javascript library 를 사용하려면 "https://apis.google.com/js/api.js" 파일만 import 하면 되는데
원본 소스에 대한 별도의 배포 사이트도 없고 API Document 마저 없어서 사용하기가 참 난해하다.
열심히 찾아봤지만 없었다.

javascript 버전의 Google Drive API Library 사용 예제는 다음의 공식 문서에 나와 있다.
JavaScript quickstart  |  Google Drive  |  Google for Developers

 

자바스크립트 빠른 시작  |  Google Drive  |  Google for Developers

Google Drive API에 요청을 전송하는 JavaScript 웹 애플리케이션을 만드는 방법을 알아봅니다.

developers.google.com

위 예제와 함께 stackoverflow 에서 찾은 샘플을 조합해서 file upload 까지는 성공했는데...
정확한 사용법을 몰라서 수소문을 해봤다.

먼저 stackoverflow 에서의 검색이다.
https://stackoverflow.com/search?tab=newest&q=gapi.client.drive.files.create&searchOn=3

 

Human verification

Stack Overflow | The World’s Largest Online Community for Developers

stackoverflow.com

열심히 찾다보면 나름의 정립을 통해 분명 API 사용법도 익숙해질거다.
하지만 그만큼 시간과 노력이 필요하고 언제 다시 사용할지 모를 지식만 쌓아놓고 시간만 허비할수도 있는데
그로 인해 의욕도 상실하고 비즈니스의 중요한 타이밍(?)도 놓치게 될 수 있다.

그래서 빠른 해결을 위해 AI에게 물어보았다.
"gapi.client.drive 의 api document 주소를 알려줘" 라고 물어보니 세가지 Chat AI (Gemini, Copilot, Clova X)모두 Google 공식 문서를 보라고 알려주었다.
REST Resource: about  |  Google Drive  |  Google for Developers

 

REST Resource: about  |  Google Drive  |  Google for Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 REST Resource: about 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 리소스: About 사용자, 사용

developers.google.com

javascript library 내에서 당연하게도 google rest api 를 이용하고 있어서라고 생각하는데
문제는 REST API 의 스펙을 안다고해도 javascript library 내의 class 와 function 들의 API 는 또 다르기 때문에 API Document 가 필요한건데... 그 문서를 찾을수가 없었다.
게다가 function 에 넘겨주는 파라미터들이 json 객체들이라서 어떤 구성의 param 목록이 지원되고 어떻게 설정해야 하는지에 대한 내용을 현재까지도 찾지 못하고 있다.

결국은 AI 들에게 질문을 바꿔서 나름 의미있는 답을 얻게 되었는데
function 의 실사용 예를 들어 구체적인 사용 방법을 물어보며 AI 들의 성능을 비교해 보았다.

[Prompt]
gapi.client.drive.files.create 함수의 resource 인자값 metadata 에는 어떤 설정값이 있어?

그에 대한 코파러(Copilot)의 답변

더보기

[Copilot]

`gapi.client.drive.files.create` 함수의 `resource` 인자는 파일에 대한 메타데이터를 설정하는 데 사용됩니다¹². 
이 메타데이터에는 다음과 같은 설정값이 포함될 수 있습니다:

- `name`: 생성할 파일의 이름¹².
- `mimeType`: 파일의 MIME 타입¹².
- `parents`: 파일이 위치할 폴더의 ID를 포함하는 배열. 예를 들어, `'parents': ['appDataFolder']`는 파일을 앱 데이터 폴더에 생성하도록 지정합니다².

이러한 설정값 외에도 Google Drive API는 파일 메타데이터에 대한 추가적인 설정값을 제공합니다¹². 
이러한 설정값은 파일의 속성을 더욱 세밀하게 제어할 수 있게 해줍니다¹². 
그러나 항상 Google Drive API의 공식 문서를 참조하여 해당 설정값이 올바르게 지원되는지 확인하는 것이 좋습니다¹².

출처: Bing과의 대화, 2024. 3. 29.
(1) Create File with Google Drive Api v3 (javascript) - Stack Overflow. https://stackoverflow.com/questions/34905363/create-file-with-google-drive-api-v3-javascript.
(2) gapi.client.drive.files.create does not work - Stack Overflow. https://stackoverflow.com/questions/65945670/gapi-client-drive-files-create-does-not-work.
(3) google drive javascript api gapi.client.drive.files undefined. https://stackoverflow.com/questions/14262884/google-drive-javascript-api-gapi-client-drive-files-undefined.
(4) Getting Started | google-api-javascript-client. https://google.github.io/google-api-javascript-client/docs/start.html.
(5) undefined. https://www.googleapis.com/discovery/v1/apis/drive/v3/rest.
(6) undefined. https://www.googleapis.com/auth/drive.appdata.
(7) undefined. https://people.googleapis.com/.

그리고 클로바래(ClovaX) 의 답변

더보기

[Clova X]

gapi.client.drive.files.create 함수의 resource 인자값인 metadata에는 다음과 같은 설정값이 있습니다.

- **name**: 파일의 이름을 설정합니다. (필수)
- **mimeType**: 파일의 MIME 타입을 설정합니다. (필수)
- **parents**: 파일이 저장될 부모 폴더의 ID를 배열로 설정합니다.
- **description**: 파일의 설명을 설정합니다.
- **starred**: 파일을 즐겨찾기에 추가할지 여부를 부울 값으로 설정합니다.
- **trashed**: 파일을 휴지통에 넣을지 여부를 부울 값으로 설정합니다.
- **explicitlyTrashed**: 파일을 명시적으로 휴지통에 넣을지 여부를 부울 값으로 설정합니다.
- **properties**: 파일의 속성을 객체로 설정합니다. 속성의 이름과 값을 key-value 쌍으로 설정합니다.

metadata에 설정할 수 있는 값은 Google Drive API에서 지원하는 파일의 속성에 따라 다릅니다.

더 궁금하신 점이 있으시면 말씀해주세요.

마지막으로 잼민이(Gemini)의 답변

더보기

[Gemini]

Google Drive API 문서에 따르면, gapi.client.drive.files.create 함수의 resource 인자값 metadata에는 다음과 같은 설정값이 있습니다.

* **description** (optional) - 파일의 설명입니다.
* **mimeType** (optional) - 파일의 미디어 유형입니다.
* **parents** (optional) - 파일을 저장할 폴더의 ID 목록입니다.
* **properties** (optional) - 파일에 대한 사용자 지정 속성입니다.
* **thumbnail** (optional) - 파일의 썸네일입니다.

다음은 각 설정값에 대한 자세한 설명입니다.

* **description** (optional) - 파일의 설명은 최대 255자까지 입력할 수 있습니다. 이 설명은 파일을 검색할 때 사용됩니다.
* **mimeType** (optional) - 파일의 미디어 유형은 파일의 종류를 나타냅니다. 예를 들어, 이미지의 미디어 유형은 "image/jpeg"입니다.
* **parents** (optional) - 파일을 저장할 폴더의 ID 목록입니다. 여러 개의 폴더에 파일을 저장하려면 이 설정값을 사용합니다.
* **properties** (optional) - 파일에 대한 사용자 지정 속성을 설정하려면 이 설정값을 사용합니다. 속성의 이름과 값은 모두 문자열입니다.
* **thumbnail** (optional) - 파일의 썸네일은 최대 256KB 크기의 이미지 파일입니다. 썸네일은 파일을 검색할 때 사용됩니다.

이러한 설정값은 모두 선택 사항입니다. 설정하지 않으면 기본값이 사용됩니다.

특이한 점은 잼민이(Gemini) 의 경우 Prompt 에 코드를 구체적으로 입력하니 Google Workspace 에서 문서를 검색하여 답변을 생성하겠다고 나한테 확인창을 띄워주었다.

그렇다는건 지금까지 잼민이(Gemini) 는 내가 하는 질문에 대한 답변을 작성할때 자기네들 서비스의 문서조차 검토도 안했다는 의미로 보였다. (그래서 그렇게 엉망이었나보다)

하지만 그렇게 자기네 서비스의 문서들까지 검토했음에도 불구하고 결과적으로 내가 선택한 답변은 Copilot 의 내용이었다.

우리의 잼민이(Gemini)는 아직까지는 많이 미숙한 아이인가보다.

 

 

 

이 포스팅의 부제는 "여전히 Copilot 만한게 읍네" 이다.

애초에 Google 의 API를 이용하는 것이니 당연히 잼민이(Gemini)를 이용해야 한다고 생각했었다.

그래서 하루죙일 잼민이한테 "샘플좀 구해줘~", "제발 좀 오류 없는 샘플좀 구해줘~" 라고 애걸 복걸 했는데...

prompt 던진 횟수만해도 30여번은 넘은 듯 하다.

그리고 그 횟수만큼 코딩 오류와 실행 실패 그리고 의존 라이브러리 점검을 해야만 했다.

참으로 절망과 고통의 시간이었다...

 

이전에 이미 js 와 servlet 으로 Google Identity Flow 를 진행하여 Access Token 까지 획득해 놓은 상태이다.

그래서 Google Drive API 를 이용할땐 OAuth 절차가 필요없었다.

로그인 이후 Google Drive API 에서 불필요하게 사용자 인증 요청창이 다시 출력되지 않도록 OAuth 절차를 생략하고 Access Token 을 이용해서 GoogleCredentials 객체를 생성하기만 하면 되었었다.

그래서 잼민이에게 "Access Token 을 이용해서 GoogleCredentials 객체 생성 예제 알려줘~" 라고 가볍게 질문을 던진게 화근이 되었다.

 

잼민이는 무려 7년~8년전의 샘플 예제까지 검토해주는 기염을 토했는데 그 결과  샘플 코드들에서 deprecated 와 undefined 에러들을 수없이 봐야만 했다.

그때마다 implement 한 library 들의 버전을 반복해서 체크했는데... 

구글 서비스 가이드 문서들도 샅샅이 뒤져가면서 구글의 문서들을 검토하느라 약 2일간 24시간을 컴퓨터 앞에서 인상쓰고 있었다.

그렇게 도저히 해법을 찾지 못했던 와중에 느닷없이

나와 동거중인 애 둘딸린 여왕님이 "prompt 를 제대로 안했나보네~" 라고 핀잔을 주면서 "prompt 좀 제대로 만들어서 던져바" 라고 조언 아닌 조언을 준것이 정말 귀한 한마디였다... 흑흑

심기일전하여 작성한 프롬프트의 내용은 다음과 같다.

[Prompt]
Google Drive 서비스 API를 이용하기 위해 Access Token으로 Credential을 생성하는 코드 예제를 알려주는데 
다음의 조건에 맞게 찾아줘
    - java 버전
    - 2020년 이후에 작성
    - 사용하는 패키지, 클래스, 메서드들 중에 deprecated 는 없어야 함
    - 사용된 패키지 라이브러리들의 버전들도 함께 출력

그에 대한 잼민이(Gemini) 의 답변은 다음과 같았다.

더보기

## Google Drive 서비스 API를 이용하기 위해 Access Token으로 Credential을 생성하는 Java 코드 예제 (2020년 이후, deprecated 없음)

다음은 Java 11+ 버전에서 Google Drive 서비스 API를 이용하기 위해 Access Token으로 Credential을 생성하는 코드 예제입니다. 2020년 이후에 작성되었으며, 사용하는 패키지, 클래스, 메서드들 중에 deprecated는 없습니다. 또한, 사용된 패키지 라이브러리들의 버전도 함께 출력합니다.

**코드 예제:**

```java
import com.google.auth.oauth2.GoogleCredentials;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.drive.Drive;

public class DriveService {

    public static void main(String[] args) throws Exception {
        // Access Token을 입력하세요.
        String accessToken = "ACCESS_TOKEN";

        // Google Drive 서비스를 위한 Credential 객체를 생성합니다.
        GoogleCredentials credentials = GoogleCredentials.create(
            GoogleCredentials.getApplicationDefault()
                .createScoped(DriveScopes.DRIVE)
                .setAccessToken(accessToken)
        );

        // Google Drive 서비스를 사용할 수 있는 Drive 객체를 생성합니다.
        Drive drive = new Drive.Builder(
            GoogleNetHttpTransport.newTrustedTransport(),
            JacksonFactory.getDefaultInstance(),
            credentials
        ).setApplicationName("Drive Service").build();

        // Google Drive API를 사용하는 코드를 작성합니다.
        // ...
    }
}

```

**사용된 패키지 라이브러리들의 버전:**

* com.google.auth.oauth2:google-auth-library-oauth2:1.21.0
* com.google.api.client:google-api-client:1.35.0
* com.google.api.client:google-api-client-jackson2:1.35.0
* com.google.api.client:google-api-client-googleapis:1.35.0
* com.google.apis:google-api-services-drive:v3-rev2023-02-16

**참고:**

* `GoogleCredentials.getApplicationDefault()` 메서드는 현재 사용자의 환경에서 Google Cloud Platform SDK를 사용하여 설정된 기본 자격 증명을 가져옵니다. 
* `DriveScopes.DRIVE` 상수는 Google Drive 서비스에 대한 모든 범위를 제공합니다.
* `GoogleNetHttpTransport.newTrustedTransport()` 메서드는 HTTPS를 사용하여 Google API 서버와 통신하는 데 사용할 수 있는 신뢰할 수 있는 HTTP 전송 객체를 생성합니다.
* `JacksonFactory.getDefaultInstance()` 메서드는 JSON 데이터를 처리하는 데 사용할 수 있는 기본 Jackson JSON 팩토리를 생성합니다.
* `setApplicationName()` 메서드는 Google API 요청에 사용될 애플리케이션 이름을 설정합니다.

**추가 정보:**

* Google Drive API: [유효하지 않은 URL 삭제됨]
* Google Cloud Platform SDK: [https://cloud.google.com/sdk/](https://cloud.google.com/sdk/)
* Google Auth Library for Java: [https://github.com/google/google-auth-library-java](https://github.com/google/google-auth-library-java)

**주의:**

* Access Token은 비밀 정보입니다. 안전하게 보관해야 합니다.
* 코드를 실행하기 전에 Google Cloud Platform SDK를 설치하고 환경 변수를 설정해야 합니다.

**2020년 이후 코드 예제를 찾는 이유:**

2020년 이전에 작성된 코드 예제는 더 이상 사용되지 않는 deprecated API 또는 패키지를 사용할 수 있습니다. 최신 코드 예제를 사용하여 최상의 호환성과 안정성을 확보하는 것이 좋습니다.

역시나 deprecated 오류를 발생시키는 구버전의 Class, Method 들이 있었다. (심지어 Library 의 버전도 부정확하다)

prompt 를 제대로 적용하지도 않았으면서 부연 설명까지 그럴듯하게 작성해서 나에게 사기를 친다. ㄷㄷㄷ

결국 잼민이를 뒤로하고 마지막으로 ChatGPT 의 후예인 Copilot 에게도 동일하게 prompt 를 던져보았다.

그리고 Copilot 의 답변은 다음과 같았다.

더보기

Google Drive 서비스 API를 이용하기 위해 Access Token으로 Credential을 생성하는 Java 코드 예제는 다음과 같습니다¹:

```java
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.AccessToken;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.auth.http.HttpCredentialsAdapter;

public class GoogleDriveService {
    public Drive getDriveService(String accessToken) throws IOException, GeneralSecurityException {
        return new Drive.Builder(
            new NetHttpTransport(),
            GsonFactory.getDefaultInstance(),
            new HttpCredentialsAdapter(getCredentials(accessToken))
        )
        .setApplicationName("appname")
        .build();
    }

    public GoogleCredentials getCredentials(String accessToken) throws FileNotFoundException, IOException {
        return GoogleCredentials.newBuilder()
        .setAccessToken(new AccessToken(accessToken, null))
        .build();
    }
}
```

이 코드는 2022년에 작성되었으며, deprecated된 메서드나 클래스를 사용하지 않았습니다¹. 사용된 패키지 라이브러리들의 버전은 다음과 같습니다¹:

- `com.google.api-client:google-api-client`: 1.33.0
- `com.google.apis:google-api-services-drive`: v3-rev20211107-1.32.1
- `com.google.http-client:google-http-client-gson`: 1.19.0
- `com.google.auth:google-auth-library-oauth2-http`: 1.3.0

더 자세한 내용은 ¹를 참고해주세요.

출처: Bing과의 대화, 2024. 3. 28.
(1) access token으로 구글 자격증명 가져오기(feat. google drive api). https://velog.io/@sangeun-jo/access-token으로-구글-자격증명-가져오기feat.-google-drive-api.
(2) Java - Google Drive API 활용하기 : 네이버 블로그. https://m.blog.naver.com/chae1789/221920372316.
(3) Class Credential (1.34.1) | Java client library | Google Cloud. https://cloud.google.com/java/docs/reference/google-oauth-client/latest/com.google.api.client.auth.oauth2.Credential.
(4) Google Drive API 빠른 시작 샘플(java) 실행하기 :: 기운바다. https://kiunsea.tistory.com/22.
(5) undefined. https://console.developers.google.com/flows/enableapi?apiid=drive.
(6) undefined. https://developers.google.com/drive/api/v3/quickstart/java.
(7) undefined. https://github.com/googleapis/google-api-java-client-services/tree/master/clients/google-api-services-drive/v3.

 

지금은 Copilot 의 답변으로 샘플 실행에 성공했고 서비스에도 적용하였다.

그래서 난 행복하다.

이제 AI 없는 작업은 생각할 수가 없다.

 

Google Drive 를 접근하기 위한 API 를 사용하려면

우선 구글 계정으로 OAuth 를 통과하고 발급 받은 access token 을 이용하면 Drive API 를 이용 할 수 있는데

그러한 일련의 절차를 API Library (Google Drive API v3 라이브러리) 만으로 일괄 처리할 수 있는 예제가 있다.

 

개발자는 그냥 library 를 import 하고 구글 클라우드 콘솔(console.cloud.google.com)에서 다운받은 OAuth 2.0 클라이언트 (credentials.json) 파일을 넣어준 후 필요한 클래스들을 사용하여 메서드를 호출하면

사용자의 Google Drive 에 있는 파일 목록을 조회하고 새로운 파일을 업로드하거나 다운로드 할 수 있게 된다.

그걸 모르고 일주일동안 Web환경에서 Google OAuth 처리를 위해 고군분투 했었다. ㅎㅎ

javascript 와 servlet 을 이용하여 code, access token, refresh token 을 발급받아 저장하는 로직까지 구현했는데...

굳이 js 와 servlet 을 오가면서 인증 파일들을 주고 받을 필요가 없었다.

각설하고, 그렇다면 위에 얘기한 샘플 예제는 어디있는고 하니..

https://developers.google.com/drive/api/quickstart/java#set_up_the_sample

 

자바 빠른 시작  |  Google Drive  |  Google for Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 자바 빠른 시작 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 빠른 시작에서는 Google Work

developers.google.com

 

샘플 실행 절차는 다음과 같다.

  1. 위 링크의 예제를 DriveQuickstart.java 클래스로 만들어 저장한다.
  2. [Google Cloud Console / API 및 서비스 / 사용자 인증 정보 / OAuth 2.0 클라이언트 ID / 승인된 리디렉션 URI] 에 "http://localhost:8888/Callback" 추가 저장해준다.
  3. https://developers.google.com/drive/api/quickstart/java#prepare_the_workspace 경로에서 gradle 내용을 참고하여 의존 라이브러리들을 추가한다.
  4. DriveQuickstart.java 클래스를 run 하면 main 함수가 자동 실행된다.
  5. 구글 계정 로그인 창이 열리고 로그인 이후 사용자 동의 화면도 연속적으로 출력된다.
  6. 이후 프로그램 실행 콘솔에는 로그인 계정의 Google Drive 에 있는 파일 목록을 출력해준다. 

참고로 필요한 라이브러리를 gradle 로 다운받으면 좋겠지만

본인이 생성한 프로젝트가 gradle project 가 아니라면 jar 파일들만 따로 classpath 에 import 하는게 편할텐데

필요한 jar 파일들은 "google-api-client", "google-oauth-client-jetty", "google-api-services-drive" 이다.

jar 파일들을 다운 받는 방법은 다음과 같다.

  1. gradle 내용에서 dependncies 에 implementation 으로 기술된 jar 라이브러리명 들을 copy 한다.
  2. 브라우저에서 https://central.sonatype.com/ 주소로(Maven Central) 접속한다.
  3. 검색창에 필요한 jar 파일의 이름을 입력하여 검색한다.
  4. 결과 목록에서 찾으려는 항목을 보면 "Latest version x.x.x View all" 링크가 있다.
  5. View all 을 들어가보면 이전 버전들도 보이고 원하는 버전을 찾아 Browse 링크를 클릭한다.
  6. Browse 링크를 열면 Central Repository 로 접속된다.
  7. 파일 목록중 OOO.jar 파일을 찾아 다운로드 하면 된다.
  8. jar 파일을 다운받아 classpath 에 넣으면 된다.

 

마지막으로 사용하는 라이브러리들의 API Document 주소들이다.

1. Google Drive API v3 Library ( google-api-services-drive ) : Overview (Drive API v3 (Rev. 197) 1.25.0) (google.com)

 

Drive API v3 (Rev. 197) 1.25.0

 

developers.google.com

2. Java용 Google API Client Library ( google-api-client ) : google-api-client overview (2.1.2)

 

google-api-client overview (2.1.2)  |  Java client library  |  Google Cloud

Send feedback google-api-client overview (2.1.2) Stay organized with collections Save and categorize content based on your preferences. Google APIs. Google APIs support based on the Apache HTTP Client. Google's additions to OAuth 2.0 authorization as speci

cloud.google.com

 

어제 그동안 유용하게 만들어 사용하던 유틸 패키지에 심각한 버그를 발견하였다.

그리고 그에 대한 해결책으로 힌트를 준 것은 다름아닌 Gemini 였다.

그동안 잘못된 사용법인 줄도 모르고 열심히 코딩해서 뭔가 핀트가 어긋난 동작을 할때마다 계속 수정해서 사용한 유틸클래스였는데

이상하게 자꾸만 오동작하길래 Gemini 에게 물어보니 정확한 오류 지점을 알려주고 해결책까지 주었다. (ㅜ.ㅜ)

이제 내 머리는 COMMON API 를 이용한 간단한 로직 개발의 코딩 영역에서 한계에 다다른 것 같다.

 

다만 그나마 잘 굴러가지 않는 머리를 활용할 방법은

그동안의 경험으로 쌓여져온 아키텍처에 대한 실루엣과 비즈니스의 추상적 레이어에 대한 설계밖에 없는 것 같다.

구현 가능 여부는 코딩 단계까지 들어가봐야 알 수 있는 부분들이 종종 있는데

그럴땐 우회 방안들을 찾거나 해당 기능 구현을 과감히 포기하고 공략 지점을 바꾸거나 타겟팅을 바꾸는 식으로 전략, 전술 능력을 키우는데에 중점을 둬야겠다.

 

지금까지 API 를 개발하는 RND 에서 근무하면서 코드 레벨로만 기능 구현과 버그 수정 작업을 너무나 오래 해왔었는데

그나마 그 시간이 의미가 있었던 것은 그 시간동안 쌓아온 코딩 스킬의 데이터베이스를 활용하여 나만의 솔루션을 만들어 볼 수 있었다는 것이었다.

그런데 지금 나와 엇비슷한 연차가 된 개발자들은 모두들 개발관리자로써 솔루션 레벨로 제품 기능의 방향성에 주안점을 두고 설계 업무를 수행하고 있을텐데... 그들은 더이상 코더가 아니다.

 

과거엔 프로그램을 개발하기 위해 모든 레벨의 개발 영역에 대해 하나부터 열까지 모든 것을 고민하려면 많은 시간이 필요했는데

그래서 그 시간을 단축시키기 위해서 많은 코더들이 필요했는데

이젠 코더들의 양적인 증대가 더이상 의미 없는 시대에 접어들었다는 느낌이다.

'긁적 > 개발 이야기' 카테고리의 다른 글

ChatGPT 에게 칭찬 받았다  (3) 2024.12.05
오늘 드디어 ChatGPT 의 진가를 맛보았다  (1) 2024.11.18

구글에서는 2020년 6월 3일부터 기본API 와 클라우드 전용API를 각각 구분해주기 위해서 
하나였던 ML Kit를 제목과 같이 두 가지로 나누었다고 한다. 
 
기본 API는(ML Kit) 라틴어 기반의 모든 텍스트를 인식할 수 있고,  
클라우드 기반의 API는(Cloud Vision API) 더 많은 텍스트 언어를 지원한다고 한다.
그 외에도 이미지 인식 사례 등에서 아래 표와 같은 차이를 드러낸다.

중요한건 상업적으로 이용하려면 유료 사용이 필수가 된다.
아마 ml kit 로 개발했다하더라도 android 버전업 되는 순간 cloud 전용 기술이 될 것 같다.

 

+ Recent posts