1. 준비물
   > Google Cloud 프로젝트
        Google Cloud 서비스를 이용하려면 기본적으로 프로젝트 생성이 필요하다.
          - Google Cloud Console 접속 (https://console.cloud.google.com)
          - 오른쪽 상단의 프로젝트 선택 → 새 프로젝트 만들기
          - 프로젝트 이름 지정 후 만들기 클릭
          - 상단 바에서 새로 만든 프로젝트가 선택되었는지 확인
   > Gemini API 활성화
          - Google Cloud Console의 좌측 메뉴에서 "API 및 서비스" → "라이브러리" 클릭
          - 검색창에 다음을 입력 : Generative Language API
          - 결과에서 "Generative Language API" 클릭
          - "사용" 버튼 클릭
   > API Key 발급
          - Google Cloud Console의 좌측 메뉴에서 "API 및 서비스" → "사용자 인증 정보" 클릭
          - 상단의 "사용자 인증 정보 만들기" → "API 키" 선택
          - 생성된 API 키는 복사하여 안전한 위치에 저장
            + (중요) API 키는 노출되지 않도록 주의
            + 필요한 경우, IP 주소 또는 referrer로 접근 제한 가능
   > Gemini 요금제 등록
        Gemini API는 사용 전 반드시 Google AI Studio에서 요금제 등록 절차를 거쳐야 실제 응답이 가능하다고 Gemini가 그랬다.
          - https://makersuite.google.com/app 접속
          - Google 계정으로 로그인
          - "API 키 생성" 또는 "설정" 메뉴로 이동
          - Billing (결제) 등록 요구 시 카드 등록 진행 (Free Tier 포함)
   > Postman
        + ver : 11.54.6


2. 테스트 절차
   > Postman 실행
        특별히 설정할게 없다. 그냥 Request 하나 생성해서 다음과 같이 입력하고 전송하면 응답이 온다.
   > POST 요청
          - Method Type : POST
          - URL : https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=[YOUR_API_KEY]
          - Body 에는 다음과 같이 전달할 프롬프트를 json 으로 작성
            + {"contents": [{"parts": [{ "text": "Hello Gemini!" }]}]}
   > 응답 확인
        응답 내용은 json이며 role 이 model 인 parts 의 내용에 응답 메세지가 있다.

java 로 web application server 를 개발할때 주로 사용하는 was 로는 tomcat 과 jetty 가 있다.

이들은 사용자 세션 관리 환경을 제공하여 사용자별로 개인화된 데이터 관리가 가능하게끔 설계 되어 있다.

그리고 이들은 '서블릿 표준 세션 인터페이스'인 jakarta.servlet.http.HttpServletRequest 의 getSession() 함수를 이용하여 jakarta.servlet.http.HttpSession 의 인스턴스를 취할 수 있다. 

그런데 위 표준 인터페이스 외에 다른 형태의 세션 인터페이스가 있는지 궁금하였고, gpt 에게 그것을 물어보게 되었는데 각 was 들은 표준 세션 인터페이스의 구현체로 별도의 내장 클래스가 존재 하는 것을 알게 되었다.

다음은 주요 웹 어플리케이션 서버들에 대한 내장 세션 클래스 목록이다.

서버 종류 세션 클래스 (일반적) 비고
Tomcat org.apache.catalina.session.StandardSession 가장 널리 사용되는 오픈 소스 서버
Jetty org.eclipse.jetty.server.session.Session Eclipse 프로젝트에서 개발된 경량형 서버
Undertow io.undertow.servlet.spec.HttpSessionImpl WildFly의 기본 서블릿 컨테이너
Spring Boot 내장 서버 (Tomcat, Jetty, Undertow 등) Spring Session에서 관리 Spring Session을 이용하여 통합 관리

그 외에 GlassFish, Payara, WildFly(JBoss) 서버들이 있는데 위와 유사하다.

위 서버들의 세션 클래스들은 내장된 고유의 클래스들로써 표준 인터페이스를 구현한 구현체이기 때문에 해당 내장 객체를 개발자가 직접 제어하는 경우는 흔치 않다고 한다.

그래서 위에 나오는 서버들은 모두 '서블릿 표준 세션 인터페이스'를 사용하여 세션 객체에 접근하여 제어하면 된다. 

하지만 '서블릿 표준 세션 인터페이스'를 지원하지 않아서 getSession() 사용이 불가한 was도 있다고 gpt가 알려주었다.

그래서 getSession() 함수가 불가한 was 또는 경우를 물어보니 다음의 경우는 사용이 불가하다고 한다.


getSession() 사용 불가 또는 제한

일반적으로 모든 Servlet 기반 WAS에서 지원되지만, 다음과 같은 경우 getSession()이 정상적으로 동작하지 않을 수 있습니다.

  1. Session 관리가 비활성화된 경우
    • web.xml 또는 application.properties에서 session-config가 비활성화되어 있는 경우
    • Spring Boot에서 server.servlet.session.timeout=0 설정 시
  2. Undertow가 Servlet 모드가 아닌 경우
    • Undertow는 기본적으로 Non-Blocking 서버로 동작하며, servlet 모듈을 명시적으로 추가해야 getSession() 사용 가능
    • Gradle에서 아래처럼 추가해야 함:
       
      dependencies {
          implementation("io.undertow:undertow-servlet")
      }
  3. Netty 기반 서버 사용 시
    • Netty는 Servlet 기반이 아니므로 getSession()을 직접 사용할 수 없음
    • Micronaut, Helidon 등 Netty 기반 프레임워크에서는 getSession()이 없는 자체적인 세션 관리 방식 사용

위와 같은 was 환경들의 세션에 대해 조사한 이유는 사용자 세션을 제어하는 데에 공통된 인터페이스가 필요하게 되었고,

내가 지금까지 습관적으로 사용했던 'jakarta.servlet.http.HttpServletRequest.getSession(true)' 코드가 어디까지 허용되는지 궁금했었다.

앞으로도 그냥 별 생각없이 getSession() 하면 된다는 것을 알게 되었다. ^^

 

 

 

1. 준비물
    > OpenAI API Key
        API Key 는 https://platform.openai.com/api-keys 에서 발급 가능하다.
        유료 결재가 필요하며 키 발급시 팝업으로 단 한번만 알려주기 때문에 별도로 저장해두고 사용해야 한다.
        분실시엔 재발급을 통해 키 확인이 가능하며 기존 키는 자동 만료된다.
        참고로 발급 받은 키를 프로젝트 문서등에 키값 내용 그대로 GitHub 에 올린 경우에도 해당 키는 자동 만료된다.
    > Assistant ID
        Assistant 는 API 를 통해 생성(Create an Assistant) 할 수 있고 Platform Dashboard 에서도 생성 할 수 있다.
        나의 경우엔 Assistant 에 'File Search' 와 'Functions' 를 설정하여 나만의 에이전트로써 기능들을 부여하였다.
    > GPT
       + model : gpt-4o
    > Postman
       + ver : 11.23.3

2. 테스트 절차
    > Postman 실행
        실행 이후 아래의 요청(Request)들을 순서대로 생성하고 공통된 설정은 다음과 같다.
        + Authorization Type 에 Bearer Token 설정후 발급 받은 API Key 입력
        + Headers 에 'Content-Type : application/json', 'OpenAI-Beta : assistants=v2' 를 추가
    > Create a Thread
        + Method Type : POST
        + URL : https://api.openai.com/v1/threads
        + Body 는 'none' 으로 설정
        + 실행하면 thread id 를 반환해주는데 이를 저장해 둔다.
    >
Add a Message to the Thread
        + Method Type : POST
        + URL : https://api.openai.com/v1/threads/{thread_id}/messages
        + Body  는 raw와 JOSN 포맷 선택후  내용은 'Create message' 를 참고하여 추가한다.
        + 실행하면 msg id 를 반환해주는데 이를 저장해 둔다.
    > Create a Run
        + Method Type : POST
        + URL : https://api.openai.com/v1/threads/{thread_id}/runs
        + Body 는 'raw'와 'JOSN' 포맷 선택후 내용은 'Create run' 를 참고하여 추가한다.
        + 실행하면 run id 를 반환해주는데 이를 저장해 둔다.
    > Retrieve Run
        + Method Type : GET
        + URL : https://api.openai.com/v1/threads/{thread_id}/runs/{run_id}
        + Body 는 'none' 으로 설정
        + 실행후 응답에 "status" : "completed" 인지 확인한다.
    > List messages
        + Method Type : GET
        + URL : https://api.openai.com/v1/threads/{thread_id}/messages
        + Body 는 'none' 으로 설정
        + 'Retrieve Run' 에서 status 가 completed 라면 'List messages' 실행후 응답에 "role": "assistant" 인 메세지가 있다.
           content 의 내용이 Agent 의 답변이다.

3. 참고자료
    > API Reference - OpenAI API
    > Assistants API quickstart - OpenAI API
    > https://www.youtube.com/watch?v=-Wne4a-8RlY

'Programing > AI API' 카테고리의 다른 글

Gemini API + Postman(포스트맨) 을 이용하여 테스트하기  (0) 2025.07.19
GUI AI Agent 가 나타났다  (1) 2024.12.28
Create an Assistant  (1) 2024.12.26

이전 회사에서 로봇 프로세스 자동화 (RPA) 도구를 접했었다.

사용자가 윈도우 어플리케이션을 조작한 기록을 기억하거나 프로그래밍하여
사용자의 업무 프로세스를 GUI에서 재현해내는 솔루션이었는데
공장에서 자동화된 로봇처럼 사무실에서 자동화된 업무를 알아서 척척 해내는 로봇이다.

그리고 오늘 GUI AI Agent 소식을 접하게 되었다.
  -> "SAP GUI AI Agent를 생성했습니다." (출처:SAP S/4 HANA 네이버 카페)

링크의 내용에서 구현에 사용된 기술은 LangGraph, GPT-4o 이다. 
문서에 나오는 시연 동영상에서 보여주는 작업 내용은 매우 초보적인 레벨의 그것이었지만
구축된 시스템이 보여주는 가능성은 드디어 자비스의 탄생을 예고하는 듯 보였다.

해당 에이전트에게 작업을 의뢰하면서 발생하는 오류를 수정하고 프로세스를 추가하다보면 어느새 한사람 분을 거뜬히 해내는 충실한 비서가 만들어지는 것이다.

대화형 AI 가 나오기 이전에는 불가능했던 다음의 기능들이 이젠 너무나 자연스럽게 받아들여지는게 작금의 현실이다.

  • 주어진 업무 프로세스를 분석하고 사용자를 대신하여 전처리 작업을 수행하여 사용자의 업무에 도움이 되는 결과값을 제공. 
  • 사용자의 선택과 화면 조작에 따라 실시간으로 가이드를 조정.
  • 고객 지원 에이전트가 사용자의 문제에 맞는 해결 단계를 실시간으로 생성하고 사용자 화면에서 가이드.
  • 사용자의 입력(클릭, 드래그 등)을 이벤트로 처리하고, 이에 따라 적절한 가이드나 화면을 즉각 제공.
  • 사용자가 잘못된 선택을 할 경우 이를 감지하고 적합한 가이드를 실시간 제공.

 

굴지의 글로벌 공룡 기업들인 Google 과 Microsoft 는 이미 Dialogflow (Google), Microsoft Bot Framework를 통해 이러한 GUI AI Agent 환경을 구축했고 더불어 OpenAI 도 Assistant(Beta) API 를 통해 GUI 와의 연동이 가능해졌다.

OpenAI 는 2023년 11월 7일부터 Assistants API 를 제공해주는데 현재까지도 베타 버전이다.

개발자들은 이 API 를 통해 Assistant 를 생성 할 수 있고 Platform Dashboard 에서도 Assistant 를 생성 할 수 있다.

Assistants API 를 통해 Assistant 를 생성하는 Curl 예제는 다음과 같다.

curl "https://api.openai.com/v1/assistants" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "OpenAI-Beta: assistants=v2" \
-d '{
  "instructions": "You are a personal math tutor. Write and run code to answer math questions.",
  "name": "Math Tutor",
  "tools": [{"type": "code_interpreter"}],
  "model": "gpt-4o"
}'

출처 :: https://platform.openai.com/docs/assistants/quickstart#step-1-create-an-assistant

Platform Dashboard 에서는 Assistant 를 생성하고 Playground 를 통해 테스트도 가능하다.

어제 올린 '오랜만의 serlvlet, jsp 삽질' 포스팅 이후에 결국 원인을 알고 임시 조치를 했다.

원인은 service-worker 에 cache 를 적용하면서 발생한 현상이었다.

service-worker 가 페이지들을 cache 하게 되면 jsp 에서 session 문제가 발생한다는 것을 이번에 알게 된 셈이다.

service-worker 가 cache 를 사용하지 않을땐 문제가 없으니

예상엔 service-worker 의 session 과 browser 의 session 이 이원화되어 동작하는 것 같다.

이를 염두에 두고 app 과 server 간의 데이터 트랜잭션을 설계해야만 한다.

 

 

나는 요즘 유행하는 spring, react, angular, vue 등등은 포기했다.

예전의 의욕 충만했던 시절로 돌아가 새로운 프레임웍을 학습하며 성취감을 느끼고 싶지만

시간과 체력도 부족하고 이젠 내 삶이 그 시간들을 기다려주지 않는다.

그래서 많이 익숙한 servlet, jsp, vanilla script , bootstrap, pwa 로 시스템을 구축했는데

수십여년을 다룬 개발 환경임에도 삽질은 여전하다. ㅎㅎ

 

현재 시스템에서는 request 의 session 에 UserSession 이라는 객체로 사용자 정보를 담아 이를 활용하고 있다.

그리고 이렇게 저장된 UserSession 을 jsp 에서 조회하여 사용자의 자격과 권한을 체크하고 사용 가능한 메뉴를 구분하고 있다.

그런데 이렇게 UserSession 을 저장하려면 로그인시에 DB 를 조회하여 사용자 정보를 취하고 그 정보들로 instance 를 생성한 후 request.setAttribute() 를 수행해야 하는데

사용자 로그인 방식이 계정 아이디/비밀번호 인증 방식과 SNS 계정 인증 방식 두가지가 있고 

두가지 방식에서 instance 저장 수행 속도가 서로 달랐다.

그래서 SNS 계정 인증 방식으로 동작할땐 현상이 발생하지 않았는데 아이디/비밀번호 인증 방식으로 동작할때는 해당 session 값이 취해지지 않아 권한 오류가 발생하고 있었다.

 

처음엔 jsp 의 출력 버퍼의 문제로 생각하고 버퍼를 조기에 flush 하면 원하는 값을 정상적으로 출력하지 않을까? 했었다.

하지만 초기에 flush 해도 문제가 발생하고 문서의 마지막에 flush 해도 증상은 여전했다.

instance 의 생성 시점의 문제라는 것을 알지를 못하니 도저히 원인을 예측하지 못하던 와중에

혹시 service worker 에서의 cache 문제인 걸까? 싶어서 service-worker.js 를 재점검 해봤지만

괜히 두어시간을 허비하며 스파게티 코드만 양산해 버린 꼴이 되었다.

그래서 service-worker.js 는 전날 저장된 상태로 다시 복원 할 수 밖에 없었고

다시 초심으로 돌아가 jsp 페이지에 javascript alert 이나 띄우며 값의 흐름을 쫓고 있었는데

이상하게 현상이 발생하지를 않는 것이었다.

 

결국 여전히 미심쩍긴 하지만 javascript 의 alert 은 ui 를 holding 상태로 만들어 server 에서의 process 가 완료될때까지 기다릴 수 있으며 이는 미리 정의된 jsp 코드에도 영향을 준다는 점을 알게 되었다.

request 에 설정한 attribute는 jsp 코드로 취하고 있는데 jsp 코드 역시 server side 프로그램인데

왜 javascript 의 alert 에 영향을 받는지 잘 모르겠다.

gpt 한테 물어봐도 jsp 코드는 server 에서 이미 실행되어 client 로 전달된 문서내에서 javascript 가 alert 을 띄우는 것이므로 javascript 의 alert 이 jsp 프로그램의 수행에 영향을 줄 수 없다는 답변을 주었다.

다만 gpt 는 센스있게도 내가 이전에 질문했던 내용을 기억하고 javascript 의 alert 에 따라 세션 값이 다르게 반환되는 현상에 대해서도 짤막하게 유추해 주었는데 그저 비동기 프로세싱에 따른 시간차 오류일 것이라고 귀띔해 주었다.

이미 현상이 그렇게 나오니 그건 맞는거 같은데... 이해 할 수 없는 현상이 되어버렸다.

 

세션을 이용하려 했던 것은 문서를 전달하는 시점에 사용자 권한까지 함께 전달하여 통신 자원 이용을 최소화하려는 것이었는데

이를 포기하고 최종적으로 그냥 서버에 사용자 권한을 한번 더 요청하자로 결론 지었다.

페이지 하나 띄우는데 ajax 통신을 3번 이상씩 수행하는게 매우 부담스럽지만

프로세스를 최소한으로 분리하면 추후 유지보수에서도 오류 분석에 있어 범위를 좁힐 수 있어 작업 효율성이 좋으므로

당장은 데이터를 별도로 요청하는 것으로 마무리 하였다.

결국 차후에는 네트웍이 완전 차단된 상태에서도 앱의 데이터를 저장, 변경하도록 아키텍처를 구성할 예정인데

이번에 겪은 오류 사항을 기억하여 앱과 서버의 데이터 동기화 매커니즘을 신중하게 설계 해야겠다.

 

마지막으로 이번 분석 작업을 통해 다시금 상기하게 된 사실은

이번 오류에서는 jsp 들간의 include 에 의한 compile 시간차가 있고 pwa 로 인해 client cache 가 있다보니

시스템 복잡도로 인해 별 것 아닌 기능조차 오류를 쫓아 원인을 분석해 나가기가 너무나 버거웠다.

그런데 규모가 큰 시스템은 이보다 더한 복잡도로 시스템을 구축해 가는데...

문제 해결에 있어 오래된 시스템에 익숙해진 개발자의 몸값이 높아지는건 당연한 일이겠다.

 

현재 개발중인 웹서비스는 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 이다. (개인이든 기업이든 무료)

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

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

 

 

+ Recent posts