Github 에 있는 남의 코드를 읽다보면 FIXME, TODO 같은 것을 간혹 발견할 수 있다. 평소에 이런 주석을 많이 보기는 했지만 적극적으로 이용하지는 않았는데, 앞으로 이를 적급적으로 활용하는게 좋을 것 같아서 이런 코드를 찾아 봤다.

따로 정리된 규칙이 있는지 찾아 봤는데, 딱히 없는 것 같다. 그래도 가장 정리는 된 문서는 https://peps.python.org/pep-0350/ 이거 같다. 

*  FIXME : 깔끔하지 않는 코드라서 정리가 필요한 코드
* TODO : 처리해야 하는 작업,  보통 함수 이름만 만들어 두고 내부는 TODO로 하는 식으로 처리하는 것 같다. 
* HACK : 버그를 수정하기 위한 유연하지 못한 방법, (알려진 버그 하나만을 처리하기 위한 좀 무식한 코드나 꼼수에 사용하는 것 같다. )
여기 까지가 사람들이 가장 많이 사용하는 codetag 인 것 같고, 다음 codetag 들은 잘 사용하면 유용할 것 같다.

* SEE : 참고해야할 다른 코드나 문서 URL 을 표시할 때
* NOTE : 코드를 리뷰하는 사람이 다는 코멘트
* !!! : 주의, 경고 사항 
* ??? : 알 수 없음. 물음.   (가끔 내가 작성한 코드이긴 하나 왜 이런 코드가 들어가 있지 하고 생각할 때 추가할만하다.)
* BUG : 버그,(알고 있는 버그인데 특수한 사항에만 적용되는 경우라서 알고 있는데, 딱히 수정하지 않을 때 사용할만 하다. )
* PORT : 호환성 문제(개발환경에서만 문제가 된다든지, 배포 환경에서만 동작한다든지에 관한 사항)

크롬 127 부터 window.ai 기능이 실험적으로 도입되었다. 이 기능을 이용해서 간단한 AI 기능을 사용할 수 있다. 실험적 기능이라 모두에게 적용되는 것은 아니고 세팅이 좀 복잡하다. 

https://dev.to/grahamthedev/windowai-running-ai-locally-from-devtools-202j   사이트에 제시되는 방법을 사용해서 빠르면 10분(내 윈도우즈 PC는 설정후 10분 후에 사용이 가능했다.), 느리면 3~4일(내 회사 Intel Macbook은 토~일 요일 포함 4일 정도 소요 되었다. ) 후에 window.ai 기능을 사용할 수 있다. 

 매우 간단하 nano AI 기능이다. WebGPU 를 사용하기 때문에 좋은 그래픽 카드를 사용하면 가속을 받을 수 있다. Chrome 이 어떤 그래픽 카드까지 지원하는지 알 수 없으나 엔비디아는 확실히 지원하는 것 같다. 

저기에 표시된 API 가 어느 순간 변경되어 버렸다. 

// 초기 버전
const chatSession = await window.ai.createTextSession()

// 현재 동작하는 버전
const chatSession = await window.ai.assistant.create()
 

둘 중에 어느 것이 동작하는지 확인이 필요하다. (beta 기능도 아닌 실험적인 기능이라서 빠르게 API가 변경된 것 같다.) 

인터넷에 찾아보니 사람들은 `Gemma 2B 2b-it-gpu-int4` 모델을 활용하는 거라고 추정하고 있다. 이 주소에서 https://www.kaggle.com/models/google/gemma/tfLite/gemma-2b-it-gpu-int4  에서 다양한 형태로 다운받을 수 있다.   
(chrome 에 있는 것은 gemini nano 로 보인다.  https://huggingface.co/oongaboongahacker/Gemini-Nano  에 누가 올려났다.  )

 


대충 코드를 만들었는데, 아래 처럼 하면 1번은 대화가 가능한 것 같다. 물론 대화 세션이 유지되게 하려면 좀 다른 방법이 필요한 것 같다. 그것까지는 잘 모르겠다. 

<!DOCTYPE html>
<html>
  <head>
    <title>Test </title>
  </head>

  <body>
    <textarea id="promp_area" rows="8" style="width: 800px;"></textarea>
    <br/>
    <button  id="ask_btn">ASK</button>
    <br/><br/><br/><br/>
    <textarea id="promp_result" rows="16" style="width: 800px;"></textarea>

    <script>
      let chatSession;
      const start = async function(){
        chatSession = await window.ai.assistant.create();
      }
      start();
      
      async function ask(){
        console.log("==== ask start ====")
        let promp_area = document.getElementById("promp_area");
        let promp_result = document.getElementById("promp_result");

        let promp_text = promp_area.value;
        const stream = chatSession.promptStreaming(promp_text);
        let result = "==== start ====\n"
        let previous = '';

        for await (const chunk of stream) {
          const sub_result = chunk.slice(previous.length);
          console.log(sub_result);
          result += sub_result;
          previous = chunk;
          promp_result.value = result;
        }
        result += "\n==== end ===="
        promp_result.value = result;

        console.log("==== ask end ====")
      }

      const ask_btn = document.getElementById("ask_btn");
      ask_btn.onclick = ask;

      let promp_area = document.getElementById("promp_area");
      promp_area.onkeydown = function(event){
        const isAlt = event.altKey || event.metaKey;
        if(event.key == "Enter"  &&  isAlt){
          ask();
        }
      };



    </script>
  </body>

</html>

 

javascript 코드를 물어 봤는데, 실제로 동작하는 코드를 만들어 냈다. 
```자바스크립트 함수가 필요해. 특정 숫자를 입력으로 받고 소수인지 판단하는 isPrimeNumber 라는 함수를 만들어줘.```
라고 질문하자.아래 코드를 만들어 주었다. 

==== start ====
 ```js
function isPrimeNumber(num) {
  // 1과 같은 숫자는 소수가 아니다
  if (num === 1) {
    return false;
  }

  // 2부터 루트까지 소수 판별
  for (let i = 2; i * i <= num; i++) {
    if (num % i === 0) {
      return false;
    }
  }

  // 소수
  return true;
}
```
==== end ====

이 코드 실제로 잘 동작했다. 


그리고 더 나가서 
```
자바스크립트 함수가 필요해. 특정 숫자를 입력으로 받고 소수인지 판단하는 isPrimeNumber 라는 함수를 만들어줘. 가능한 효율적으로 만들어줘.
```
라고 질문했더니 아래 코드를 만들었다. 

==== start ====
 ```js
function isPrimeNumber(num) {
  // 1과 같은 숫자는 소수가 아니다
  if (num === 1) {
    return false;
  }

  // 2부터 루트까지 소수 판별
  for (let i = 2; i * i <= num; i++) {
    if (num % i === 0) {
      return false;
    }
  }

  // 소수 판별 루트 단위로 
  let 판별 = Math.sqrt(num).floor();
  for (let i = 3; i * i <= 판별; i += 2) {
    if (num % i === 0) {
      return false;
    }
  }

  // 소수 판별
  return true;
}
```
==== end ====

이건 Math.sqrt(num).floor() 이 구문에서 에러가 발생했다. 의도는 충분히 알 것 같다. 
(몰랐는데 크롬 javascript 에서 한글 변수가 동작하네!!! 이건 몰랐다.) 

이 정도면 초보 프로그래머 수준은 되는 것 같다. 


물론 애도 세종대왕 맥북 던짐 사건에는 헛소리 한다. 
```
세종대왕 맥북프로 던짐 사건 알려줘.
```

==== start ====
 **세종대왕 맥북프로 던짐 사건**
세종대왕 맥북프로 던지기 사건은 1998년 9월 27일에 일어난 사건이다. 이 사건은 세종대왕이 맥북프로를 땅에 던져버린 것으로 알려져 있다.

이 사건의 배경에는 1997년 11월 10일에 일어난 세종대왕 유비리 폭행사건이 있다. 세종대왕 유비리 폭행사건은 세종대왕이 유비리에게 폭행을 가한 것으로 알려져 있다. 이 사건 이후 세종대왕은 폭력적이고 잔혹한 통치자로 널리 널렸다.

세종대왕 맥북프로 던지기 사건은 세종대왕이 폭력적이고 잔혹한 통치자로 널리 널리 널렸다는 것을 보여준 사건이다.
==== end ====

 

아직 API 가 변경중에 있고, 모델도 변경가능한 상태라 어떻게 일괄성을 유지해서 개발에 이용할 수 있을지는 잘 모르겠다. 그래도 생각보다 AI가 가까이 있다고 느껴지게 된다. 

 회사에서 사용하는 테스트용 클라우드 서버를 ubuntu 20.04 에서 ubuntu 22.04 로 업그레이드 한 후 가끔식 서버가 먹통이 되는 현상이 발생하고 있다. 웹서버가 동작하지 않고 ssh 조차 접속되지 않는 현상이 가끔씩 발생했다. 이 현상이 발생하면 cloud 서버 관리 사이트에 들어가서 강제로 재부팅을 시키곤 했다. 

 로그를 분석해 보면 cron 서버스가 동작하면서 밤사이 CPU 사용률이 100%가 되는 현상이다. 그래서 우선 불필요한 cron 서비스를 제거했다. 어차피 테스트 서버라서 잘 작동하지 않아도 문제될 것은 없다. 그러다 평소 습관대로 free -h 명령어를 사용해 보았다. 이 명령어는 메모리가 어떻게 사용되고 있냐를 확인하는 명령어 이다. 그런데 swap 메모리가 전혀 사용되지 않는 것을 확인 했다. 

               total        used        free      shared  buff/cache   available
Mem:           ...............................................
Swap:          8.0Gi          0B       8.0Gi

대충 위와 같이 swap 의 used 가 0 인 것을 발견했다. 

이 서버가 테스트 서버인지라 메모리가 2G가 안된다. 그래서 Postgresql 돌리고 웹서버 돌리고 하는데, 메모리가 좀 많이 필요한 편이다.(그리고 웹서비스도 2개가 돌아간다.) 그래서 처음 세팅시 swap 을 설정해서 가상 메모리를 사용하고 있다.(이 값이 설정안되면 파이썬 라이브러리가 설치가 안되는 문제도 가끔씩 발생된다.)  어차피 테스트 서버라 속도가 좀 늦어도 상관없다. 그래도 하드가 SSD 라 꽤 괜찮은 속도를 유지하고 있는 편이다.

서버가 가끔식 먹통이 되는게 swap 이 동작하지 않은게 원인 같았다. 내 추론으로는 메모리가 부족해서 프로그램이 돌다가 엄청나게 느려지거나  sagement fault 이 발생하면서 큰 문제를 일으킨 것으로 생각하는게 맞을 것 같다. 뭐, 더 이상 문제가 발생하지 않는다면 swap 이 동작하지 않는게 원인이겠지.

어째든 찾아보니 vm.swappiness  라고 하는 설정이 있었다. 이 값으로 swap 메모리를 어떠한 비율로 사용할 것인지 결정하는 값이 있었다. 이 테스트 서버의 경우 0 으로 설정되어서 전혀 사용하지 않음으로 설정된 상태였다. (자세한 설정은 vm.swappiness 으로 검색해 보기 바란다.)

이 값을 기본값인 60으로 설정하고 나니 swap 메모리를 사용하기 시작했다. 

다른 서버들을 확인해보니 이 cloud 서버들만 vm.swappiness 가 0 으로 설정되어있었다. 실제 서비스 서버는 메모리가 충분한 상태이기 때문에 변경은 필요 없어 보였다.

가끔씩 클라우드마다 다른 설정값을 보이는 경우가 있다. 내 생각에는 클라우드마다 ubuntu 서버를 수정해서 배포하는 것 같다. 그러다보니 여러 클라우드를 사용하다보면 좀 다양한 현상을 겪게 된다. 

 

어째든 이번일은 이것으로 마무리 되고 더 이상 문제가 안 생기기를 바란다.