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

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

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

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

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

 

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

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

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

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

 

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

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

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

 

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

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

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

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

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

 

지니박스에 카카오와 네이버의 소셜 로그인을 구현후 구글의 자동 로그인이 필요하여 잼민이(Gemini)에게 먼저 물어보았다.
그리고 답변은 다음과 같다.

더보기

사용자 로그인 경험을 향상시키기 위해 첫 로그인 이후 알림 없이 자동 로그인을 설정하고 싶으시군요! 
Google OAuth를 이용하면 간단하게 자동 로그인 기능을 구현할 수 있습니다. 

두 가지 방법을 소개해 드리겠습니다.

1. 서버 측 코드를 이용한 자동 로그인
사용자 동의: 로그인 과정에서 사용자에게 자동 로그인 여부를 선택할 수 있는 옵션을 제공합니다.
Authorization Code 획득: 사용자가 자동 로그인을 선택하면, Google OAuth를 통해 Authorization Code를 발급받습니다.
Refresh Token 발급: Authorization Code를 사용하여 Refresh Token을 발급받습니다. Refresh Token은 만료 기간이 길기 때문에 사용자의 로그인 상태를 유지하는 데 사용됩니다.
Refresh Token 저장: Refresh Token을 사용자의 기기에 안전하게 저장합니다. 일반적으로 쿠키 또는 로컬 스토리지에 저장합니다.
자동 로그인: 사용자가 사이트 또는 앱을 다시 방문할 때, 저장된 Refresh Token을 사용하여 자동으로 로그인합니다.

2. 클라이언트 측 코드를 이용한 자동 로그인
Google APIs Client Library: Google APIs Client Library를 사용하여 OAuth 흐름을 구현합니다.
사용자 동의: 로그인 과정에서 사용자에게 자동 로그인 여부를 선택할 수 있는 옵션을 제공합니다.
Authorization Code 획득: 사용자가 자동 로그인을 선택하면, Google OAuth를 통해 Authorization Code를 발급받습니다.
Refresh Token 발급: Authorization Code를 사용하여 Refresh Token을 발급받습니다.
Refresh Token 저장: Refresh Token을 사용자의 기기에 안전하게 저장합니다. 일반적으로 쿠키 또는 로컬 스토리지에 저장합니다.
자동 로그인: 사용자가 사이트 또는 앱을 다시 방문할 때, 저장된 Refresh Token을 사용하여 자동으로 로그인합니다.

참고 사항
자동 로그인 기능은 사용자 편의성을 위해 제공하지만, 보안 측면에서 주의가 필요합니다.
사용자에게 자동 로그인 기능의 장점과 단점을 명확하게 설명하고, 선택권을 제공해야 합니다.
자동 로그인 기능을 비활성화할 수 있는 방법도 제공해야 합니다.
Refresh Token을 안전하게 저장하고 관리해야 합니다.

추가 정보
Google OAuth 2.0: [유효하지 않은 URL 삭제됨]
Google APIs Client Library: https://developers.google.com/api-client-library/
자동 로그인 기능 구현 시 참고할 수 있는 샘플 코드와 라이브러리
Google OAuth 2.0 Playground: [유효하지 않은 URL 삭제됨]
Auth0: https://auth0.com/
Okta: https://www.okta.com/
 
도움이 되었기를 바랍니다! 궁금한 점이 있으면 언제든지 질문해 주세요.

위 내용에 따라 refresh token 를 얻어서 스토리지에 저장후 사용자가 서비스에 로그인 할때마다 꺼내서 구글 계정도 함께 인증하는데 사용하면 되겠다! 라고 생각했다.

그래서 이전부터 조사중에 있던 Google API 에서 Authentication(인증) 관련된 javascript library 에서 refresh token 을 얻는 방법을 열심히 찾았었다.

관련 javascript library 는 다음과 같다.

더보기

Google Accounts JavaScript Library
    https://accounts.google.com/gsi/client 라이브러리를 임포트하고
    google.accounts.oauth2 객체를 이용하여 사용자 인증 프로세스를 진행한다.

Google APIs Client Library
    https://apis.google.com/js/api.js 라이브러리를 임포트하고
    gapi.client 객체를 이용하여 사용자 인증 프로세스에서 얻은 access token 으로
    google workspace api 에 필요한 데이터를 요청하게 된다.

하지만 위와 같은 javascript library 들에서는 refresh token 을 얻는 API를 찾을 수가 없었다.
대신 Google REST API 에서는 몇가지 옵션을 통해서 refresh token 을 얻을 수 있었는데 (실습 내용)
어떻게든 javascript library 를 이용해보려고 Gemini 와 Bing 그리고 Google 공식 사이트를 샅샅이 뒤져보았지만 해당 API에 대한 Specification Document 를 찾을 수도 없었다.

그래서 API 찾는 것을 포기하고 Stackoverflow 에서 "google.accounts.oauth2 refresh token" 키워드로 검색한 결과 다음과 같은 Q&A 를 통해 javascript api 를 이용할게 아니라 애초에 Google Identity 에 대한 전체적인 흐름 학습이 먼저였다는 것을 겨우 알게 되었다.

https://stackoverflow.com/questions/77796811/google-accounts-oauth2-tokenclient-how-to-get-refresh-token

 

google.accounts.oauth2 TokenClient, how to get refresh token

Using gapi my goal is to authenticate the user, then save their refresh token, which is to be later used for performing background tasks on the server side. For this I have made a simple authentica...

stackoverflow.com

위에 나온 Gemini 의 답변에서 누락된 부분은
client(브라우저) 로만 인증 프로세싱을 구현하게 되면 인증에서의 중요한 key와 code, token 등이 노출 될 수 있으므로
안전한 사용자 자동 인증 서비스를 위해서 client(브라우저) 와 service server(지니박스) 를 연계하여 인증 프로세스를 구축하는 것을 권장한다.

그리고 인증 프로세스의 전체 내용은
client(브라우저) 에서 authorization code(승인 코드) 를 발급받고 이를 service server(지니박스) 에 넘겨  authorization server(구글 인증서버) 로부터  access token 와 refrsh token 을 발급받아
access token 은 지금 요청받은 사용자 요구를 처리하고 refresh token 은 스토리지에 저장하여
사용자가 이후 서비스에 재로그인시 google authentication 에도 함께 자동 로그인하게 처리하라는 내용이었다.
token 요청시 client_secret 이라는 매우 조심스러운 값을 인증 서버로 전달해야 하므로 위와 같은 인증 처리 절차가 필요하다.

참고로 google identity 의 Authentication 과 Authorization 에 대한 내용은 다음의 문서에서 학습이 가능하다.

Google Identity  |  Google for Developers

 

Google ID 플랫폼  |  Google for Developers

사용자가 앱에 로그인하고 앱에 Google 서비스 사용 권한을 부여하도록 돕습니다.

developers.google.com

 

위 문서에서 Google OAuth2.0 에 대한 전체적인 Flow 는 다음의 문서에 잘 나와 있다.

Using OAuth 2.0 to Access Google APIs  |  Authorization  |  Google for Developers

 

OAuth 2.0을 사용하여 Google API에 액세스하기  |  Authorization  |  Google for Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 OAuth 2.0을 사용하여 Google API에 액세스하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

developers.google.com

 

마지막으로 다음의 내용에서 sample code 를 보면 Google APIs Client Library (JavaScript) 를 이용하지 않고 순수 JavaScript code 로 form submit 을 이용하여 REST API를 호출하는 방법을 보여준다.

https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow#redirecting

 

클라이언트 측 웹 애플리케이션용 OAuth 2.0  |  Authorization  |  Google for Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 클라이언트 측 웹 애플리케이션용 OAuth 2.0 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

developers.google.com

 

또한 다음의 sample code 에서는 XMLHttpRequest 객체를 이용한 완전한 Ajax 예제도 보여주고 있다. 

https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow#example

 

클라이언트 측 웹 애플리케이션용 OAuth 2.0  |  Authorization  |  Google for Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 클라이언트 측 웹 애플리케이션용 OAuth 2.0 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

developers.google.com

 

어차피 Google REST API 를 알고 있다면 복잡하게 Google APIs Client Library 를 이용하지 말고
그냥 REST API 를 호출하는 것이 추후 유지보수에서도 효율적일 것으로 판단하였다.
그래서 웹브라우저와 서버 CGI 모두 Google REST API 를 호출하여 데이터를 취할 수 있도록 수정 적용하였다.

 

sns의 시작을 facebook 으로 봐야할지는 모르겠지만

초창기 pc통신부터 살아온 아재 입장에서 sns 의 진정한 시작은 커뮤니티 게시글의 댓글이었다고 본다.

댓글은 절대 장황하게 풀어쓰지 않는다.

임팩트 있는 문장을 찝어 짧게 의표를 찔러 주어야만 의미 있는 댓글이 되기 때문이다.

그렇게 무수히 많은 댓글의 역사는 지금도 그렇게 흘러가고 있는데 20년전 등장한 sns 의 시작은 현재 대규모 스트리밍 서비스인 youtube 에서도 사람들을 현혹하고 있다.

최근들어 인터넷을 하며 자각하게 된 증상중 하나가 무언가 길게 감상하는 것을 못하게 되었다.

가령 커뮤니티의 글중 장문의 내용이나 배우고 싶은 기술의 긴 강의나 장황한 샘플 예제 등을 정독할 수 없게 되었다.

항상 시간에 쫓기고 빠른 결과를 도출해야 하는 압박에 시달린 결과일수도 있지만

현대 사회의 굉장히 많은  정보 홍수속에서 누구나 그렇게 많은 정보들을 접하고 사는데 나만 느긋하게 살면 뒤쳐진다는 강박관념이 생겨서인 듯 하다.

이젠 유튜브에서 누군가 요약해놓은 논평만 보고 굉장히 자극적인 shorts 만 멍하니 바라보고 영화나 게임조차 남이 대신 감상하고 플레이한 영상의 파편들을 짜집기하고 해설한 영상들만 찾고 있다.

나만의 문제일까?

차라리 그렇다면 그것을 감지한 것만으로도 다행일텐데

이제 곧 6살이 되는 첫째에게 학습이라는 명목으로 노출한 유튜브를 나와 같은 방식으로 감상하는 것을 어떻게 해석해야 할지 걱정이다.

무조건 부정적으로 봐야하는건지 자연스러운 시대의 흐름으로 봐도 좋을런지...

나도 혈기 왕성한 10대에 pc게임에 빠져 허우적 거리던 세대라서 편향된 시선이 되지 않으려고 그렇게 애쓰는 중이다.

'긁적' 카테고리의 다른 글

첫째 사진  (0) 2023.12.11
눈이 예쁜 여배우들 (시얼샤 로넌, 에이바 미셸)  (0) 2023.11.12
새로운 시작 (인연이란)  (2) 2023.09.24

첫째가 두돌정도 되었을때 찍은 스튜디오 사진이다.
스튜디오 광고용으로 업체 블로그에 올린게 있길래 캡춰했다.
지금은 사업을 접었는지 스튜디오도 없고 블로그 갱신도 안되고 있는데... 왠지 서운하다.

 

 

service worker 에 빠져 지내는 며칠간 겨우 겨우 돌아가는 샘플을 작성했는데 fcm 만을 활용하다보니 web-push 와의 차이점을 정확히 구분하지 못하고 있었다.
getToken()으로 fcm 을 이용하는데 넷상에 존재하는 어떤 샘플들은 fcm 과 pushManager.subscribe() 로만 작성한 코드들이 발견되었다.

너무나 많은 블로그들의 샘플들이 제각각으로 코딩이 되어 있다보니 어느것이 올바른 사용법인지 헷갈리기 시작했다.
분명 동작은 했을테니 포스팅을 한걸텐데...만에 하나 deprecated 된 API를 사용한 날엔 코딩한다고 수시간이 헛고생으로 끝날테니 쉽사리 도전도 못하고 있었다. (대부분의 포스트들이 5~8년전에 작성된 것이어서 더욱 두려웠음)
그래서 분명 getToken() 만으로 정상적으로 noitification 이 동작하는데 pushManager 는 언제 사용하게 되는지 넷상의 레퍼런스들을 찾아봤지만 명확하게 정의해준 문서를 도저히 찾을 수 없었다.
어딘가에 있겠지만 이제 세상의 네트는 너무나 방대하다보니 일일이 내용들을 살펴보기가 힘들더라...

그래서 우리의 AI 친구들에게 물어보니 다음과 같은 답변을 주었다.

[질문]
firebase 에서는 getToken 함수 호출시 pushmanager 의 subscribe 기능이 포함된거야?
[Copilot]
네, Firebase에서는 getToken 함수를 호출하면 PushManager의 subscribe 기능이 포함됩니다. 
즉, Firebase에서 제공하는 FCM(파이어베이스 클라우드 메시징) 서비스에 구독하고, 푸시 알림을 받을 수 있는 토큰을 발급받습니다. 
이 토큰은 서버에서 특정 기기에 푸시 알림을 보내기 위해 사용됩니다. 
getToken 함수의 사용법은 다음 웹 사이트를 참고하세요.
Firebase Cloud Messaging | Firebase: FCM 서비스에 대한 설명과 가이드를 제공합니다.
Firebase용 Cloud Functions 클라이언트 SDK | Firebase: Firebase 앱에서 함수를 호출하는 방법을 제공합니다.
[Bard]
네, 맞습니다. Firebase 에서 getToken() 함수를 호출하면 pushManager 의 subscribe() 기능이 자동으로 호출됩니다. 즉, getToken() 함수를 호출하면 push 알림을 수신할 수 있는 준비가 완료됩니다.

getToken() 함수는 Firebase Cloud Messaging(FCM)에서 발급한 토큰을 반환합니다. 이 토큰은 push 알림을 수신하는 데 사용됩니다. getToken() 함수를 호출하면 다음과 같은 순서로 동작합니다.

1. pushManager 의 subscribe() 함수를 호출하여 push 알림을 수신할 수 있도록 등록합니다.
2. FCM에서 토큰을 발급합니다.
3. 토큰을 반환합니다.

따라서 getToken() 함수를 호출하면 pushManager 의 subscribe() 기능이 포함되어 있다고 할 수 있습니다.

다음은 getToken() 함수를 사용하는 예입니다.

JavaScript
// Firebase SDK를 초기화합니다.
firebase.initializeApp();

// 토큰을 가져옵니다.
const token = firebase.messaging().getToken();

// 토큰을 출력합니다.
console.log(token);

이 코드를 실행하면 다음과 같은 출력이 표시됩니다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FwaS50b2tlbi5jb20iLCJzdWIiOiJhZG1pbiIsImV4cCI6MTY1NjI2MzQ3NCwiaWF0IjoxNjUyMjY0NDc0fQ.7s2s0v707264236345657682345678901234567890

이 토큰을 사용하여 push 알림을 수신할 수 있습니다.

두 AI 들의 답변이 동일한 걸로 봐선 Chat AI 의 할루시네이션은 아니라고 생각했다.
하지만 여전히 정확한 레퍼런스를 제시하지 못하고 있길래 내가 직접 어떤 코드가 더 올바른 사용인지 추적을 해보았다.

결론은 firebase.messaging().getToken() 은 firebase-messaging.js 라이브러리를 import 하면 사용 할 수 있는 스펙으로써
내부에서 pushManager.subscribe() 를 호출하여 동작한다. (소스코드 먼저 볼걸...)

firebase-messaging.js 라이브러리 소스코드를 뒤져볼 생각을 하기 전엔 두 플랫폼의 API를 살펴보면 어떨까해서 레퍼런스들을 뒤져봤었는데...
mozilla 의 mdn 에서는 Push API 와 Notifications API 별도로 있는 것을 확인하였다.
- https://developer.mozilla.org/en-US/docs/Web/API/Push_API (메세지 수신 처리)
- https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API (알림 출력 처리)
그리고 firebase 의 messaging API 도 살펴봤는데 둘의 상관관계에 대해서는 발견 할 수 없었다.
- https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessaging#getToken()

결국 그렇게 2시간여를 소비하다가 불현듯 떠오른 생각이 "firebase-messaging.js 소스를 보면 되겄네?"
다음은 firebase-messaging.js 에 정의된 getToken 함수의 내용중 일부이다.

async function getToken$1(e, t) {
    ...
    getTokenInternal(e)
}

async function getTokenInternal(e) {
    ...
    return e.pushManager.subscribe({
        userVisibleOnly: !0,
        applicationServerKey: base64ToArray(t)
    })
    ...
}

처음부터 소스 코드를 봤으면 몇시간을 허비하지 않아도 되었는데...

맑고 푸른눈의 예쁜 여배우들인데 두사람의 이미지가 비슷해서 헷갈렸다.

나이 차이가 많은 배우들이지만 마스크 이미지가 비슷하고 자주 보는 얼굴들이 아니다보니 그런가보다.

왼쪽이 '시얼샤 로넌' 이고 오른쪽이 '에이바 미셸' 이다.

시얼샤 로넌은 영화 '호스트' 라는 sf 물에서 처음 봤고 에이바 미셸은 '톨 걸' 이라는 청춘 시트콤 영화에서 알게 되었다.

'긁적' 카테고리의 다른 글

모든것이 인스턴트화 되는 느낌이다  (0) 2023.12.16
첫째 사진  (0) 2023.12.11
새로운 시작 (인연이란)  (2) 2023.09.24

pwa 의 service worker 학습한다고 아주 먼~ 후배들의 샘플들을 보다가 동일한 기능의 함수 정의 코드인데 잠시 멈칫했다.
15년동안 내가 아는 방식으로만 하다보니 몇년전에 접하고 아직 익숙치 않았던 arrow function 정의 문법에서 세대 차이를 느끼게 되었다. ㅜ.ㅜ
몇년전에 유튭으로 학습하긴 했는데 업무에서 사용할 일이 없다보니... 에효;;

self.oninstall = (e) => {
    console.log('service worker installed')
}
//oninstall 이벤트 함수를 정의하는데 아규먼트는 e라는 이벤트 객체다.
//그리고 함수 블럭의 정의는 괄호와 같다.

다음은 동일한 내용의 레거시 코드다.

self.addEventListener('install', function (event) {
    console.log('service worker installed');
});
//self element 의 addEventListener 함수를 통해서 install 이벤트를 등록할건데
//event 아규먼트를 넘겨받는 이벤트 함수 블럭의 내용은 괄호와 같다.

20년전에 처음 script 접하면서 익숙치 않은 프로그래밍을 배웠던 설렘(?)처럼 많이 부담스럽다.

+ Recent posts