AI로 버그 찾기.

프로그래밍 2026. 9. 17. 20:07 Posted by UnHa Kim

최근 로컬 AI 코딩 에이전트 앱 LM Studio Bionic에 Qwen 3.8 27B Q8 모델을 얹어서 프로그래밍 작업에 애용하고 있다.

(로컬 AI이므로 전기료를 제외하면 토큰 비용이 없는 무료이다.)

 

처음에는 아이디어로만 가지고 있던 새로운 기능을 구현하는 데 주로 사용했고, (소형 LLM을 활용한 로컬 자동 코딩 : https://ghts.tistory.com/211), 지금은 기존 코드에서 버그를 찾아내는 데 주로 사용하고 있다.

 

LM Studio Bionic이 상당히 무겁고 느린 데다가, Qwen 3.8 27B 도 과추론을 일삼는 특성이 있어서, 2개의 조합은 매우 느리지만, 작업이 확실하고 깔끔하게 마무리 되는 특성 때문에 계속 사용하고 있다.

 

잠들기 전 AI에게 버그를 찾으라고 명령을 내린 후, 자고 일어나 보면 밤새 AI가 작업해서 버그 보고서 작성을 마친 상태이다.

이렇게 잠든 시간을 활용하면, 느린 속도를 어느 정도 보완할 수 있다.

무료 중소형 LLM모델이 기억도 가물가물한 오래된 코드 뭉치에서 버그를 찾아내는 것을 보면  감탄을 금할 수 없다.

 

AI가 찾아낸 버그를 수정하다보니, 거의 변동이 없던 깃허브 저장소에 커밋이 갑자기 증가했다.

(https://github.com/ghts/ghts/graphs/commit-activity)

 

 

GPU 1장에 다 들어가는 27B에 불과한 소형 모델로 토큰 비용 지출 없이 이 정도 작업이 가능하다는 게 놀라울 따름이다.

 

앞으로 얼마나 많은 변화가 올 지 가늠도 안 된다.

중국 알리바바 그룹이 개발한 Qwen 3.8 27B는 게임용 GPU 1장에 다 들어가는 작은 용량에도 불구하고, Artificial Analysis Intelligence Index가 50점이 넘어가는 (용량 대비) 엄청난 성능을 낸다.

이게 얼마나 엄청난 점수인가 하면, 2년 전 세계 최고 성능을 자랑했던 클로드 OPUS 4.5 모델과 비벼볼 수 있는 수준이다.

 

비록, 과추론(너무 오랫동안 생각)하는 경향이 있어서, 간단한 작업 하나에 10분 넘게 기다려야 하는 일이 다반사이긴 하지만, 토큰 비용을 지불하지 않고, 각자 PC에서 쓸만한 성능의 자동 코딩을 수행할 수 있는 시대가 된 것이다.

느린 속도 문제도 잠들기 전에 일을 시켜놓고, 자고 일어나면 대충 해결되어 있어서 감당 가능한 수준이다.

 

 

 

요즘 많이 쓴다는 '클로드 코드'는 터미널 인터페이스인데, 21세기에 아직도 터미널?? 이라는 생각에 손이 가질 않아서, 'ChatGPT'(일명 codex-app), 'Hermes Desktop', 'Cline'(VS Code 플러그인), 'LM Studio Bionic'등 GUI 인터페이스 에이전트 앱을 주로 사용했고, ollama를 사용해서 Qwen 3.8 27B을 백엔드로 연결해서 사용했는 데, 초기 기능 구현 코딩은 훌륭하게 해 낸다.

 

불과 2년 전에는 개별 파일 단위로 (혹은 코드 블록 단위로), AI에게 떠먹여주듯 수동으로 컨텍스트를 일일이 지정하고 '예제 코드 작성'/'코드 리뷰'/'문서화'등 보조 업무 용도로만 사용했고, 그것조차도 대단한 발전이라고 생각했는 데,

이제는 AI 모델이 알아서 프로젝트 내 수많은 파일들을 뒤져가면서 관련된 파일을 찾아내고,

'자동 코드 생성' -> '테스트 코드 작성' -> '테스트 수행' -> '오류 수정'까지 개발 프로세스 전반을 다 해 내고,

이후 적절한 추가 지시만 하면 '중복 코드 제거' 리팩토링까지 해 내는 것을 보면서,

개발 과정의 주요 업무 80% 이상을 AI가 해내는 시대가 왔다는 느낌이다.

 

물론, 아직까지는 한계가 존재한다.

초기 구현 과정에서 중복 코드를 다량 양산한다.

그래서, 초기 구현을 마친 후, 리팩토링 작업을 반복적으로 수행해줘야 한다.

리팩토링 작업도 AI 모델에게 시키면 80~90%는 해결되지만, 마지막 10~20%는 여전히 사람의 손길이 필요한 것 같다.

그리고, 가끔씩 미세한 로직 에러(혹은 논리 버그)가 숨어있는 경우도 존재한다.

 

쓸만한 수준의 초기 기능 구현은 아주 빠르게 구현되는 데,

해당 코드를 장기간 관리 가능한 수준으로 복잡성을 관리해 나가려면,

(아직까지는) 인간의 개입(내지 케어)가 필요한 것 같다.

 

결국, 장기 유지보수를 위해서 AI가 생성한 코드를 인간이 읽고 이해해야 하니까,

현직 개발자들은 AI가 엄청난 속도로 쏟아내는 코드를 읽고 이해하느라 업무량이 폭증했다고 한다.

개인적으로는 혼자서 모든 것을 개발하던 것에 비하면 체감 피로도가 확연히 줄었다.

 

 

 

 

 

 

R언어의 대입 기호 (다른 언어는 '='인데 비해서) '<-' 이다.

2개의 키를 필요로 하는 것도 모자라서, < 를 타이핑 하려면 쉬프트키까지 눌러야 하니, 다른 언어에 비해서 3배의 노력이 필요하다.

그런데, RStudio에서는 이 문제를 조금이나마 편하게 해 주는 팁이 있다.

ALT+'-' 가 바로 <-가 입력되게 하는 단축키이다.

 

Go언어 내장형 SQL 데이터베이스

프로그래밍 2022. 12. 19. 18:27 Posted by UnHa Kim

Java의 경우 프로그램 안에 SQL 데이터베이스를 내장하는 선택지가 몇 개나 존재한다.

(HSQLDB, H2 및 Apache Derby등등)

 

Go언어의 경우 (NoSQL, K/V 저장소는 있어도) 마땅한 내장형 SQL 데이터베이스가 없어서 아쉽다고 느꼈는 데, 알고보니 약 2년 전에 이미 Go언어로 작성된 SQL 데이터베이스가 작성되었는 데, 모르고 있던 것일 뿐이었다.

검색의 생활화가 시급하다는 것 또 다시 깨닫는다.

 

C언어로 작성된 sqlite를 Go언어로 포팅한 것인데, 배포 편의성을 감안하면 아주 유용할 것 같다.

 

https://gitlab.com/cznic/sqlite

 

cznic / sqlite · GitLab

Package sqlite is a CGo-free port of SQLite/SQLite3. SQLite is an in-process implementation of a self-contained, serverless, zero-configuration, transactional SQL database engine.

gitlab.com

 

https://pkg.go.dev/modernc.org/sqlite

 

sqlite package - modernc.org/sqlite - Go Packages

sqlite Package sqlite is a cgo-free port of SQLite. Although you could see mattn's driver (github.com/mattn/go-sqlite3) in go.mod file, we import it for tests only. SQLite is an in-process implementation of a self-contained, serverless, zero-configuration,

pkg.go.dev

 

IntelliJ GoLand 2021.2 이후 버전에서는 테스트 케이스 함수명이 한글로 되어 있는 경우 제대로 인식하지 못하고,

테스트 실행 시 문제가 발생한다.

 

IntellJ에 기술 지원 문의를 했더니 다음과 같은 해결책을 알려주었다.

  • Help | Find Action. (한글 언어팩을 설치한 경우에는 '도움말(H) | 액션 찾기(F)'
  • 'Registry...' 를 타이핑 (한글 언어팩을 설치한 경우에는 '레지스트리...'. 따옴표는 제외하고 입력.)
  • 'go.run.processes.with.pty'를 찾아서 비활성화.

오랜 시간 묵었던 문제가 해결되었다.

'프로그래밍' 카테고리의 다른 글

RStudio에서 대입 기호(<-) 간편하게 입력하기  (0) 2023.09.23
Go언어 내장형 SQL 데이터베이스  (0) 2022.12.19
한국투자증권 REST API  (2) 2022.07.07
Go언어 에러처리  (0) 2016.11.02
Go언어 소개  (0) 2014.11.04

한국투자증권 REST API

프로그래밍 2022. 7. 7. 12:41 Posted by UnHa Kim

그동안 증권사 API는 MS-윈도우에 특화된 DLL, OLE, OCX등의 형태로 제공되는 경우가 대부분이어서, 시스템 독립적인 프로그래밍 언어로는 (특히, 사용자가 많은 Java는 심각할 정도로) 매매 시스템을 작성하기 힘든 면이 많았다.

 

이 블로그도 Go언어로 증권사 API를 호출하기 위해서 복잡다단한 단계를 거치다가 만들게 되었다.

그런데, 이제 프로그래밍 언어에 독립적인 REST로 형태로 제공되는 API가 생겨서 그런 제약 사항이 사라졌다.

 

https://apiportal.koreainvestment.com

 

KIS Developers

잠시만 기다려 주세요

apiportal.koreainvestment.com

 

Go언어 에러처리

프로그래밍 2016. 11. 2. 10:11 Posted by UnHa Kim

Go언어를 쓰면서 느끼는 가장 큰 불편은 '에러처리'이다.

try-catch 같은 예외처리 기능이 없으며, if문에서 일일이 에러발생 여부를 확인해야 한다.


 

if 반환값, 에러 := F실행할_함수(인수1, 인수2....); 에러 != nil {

<여기에서 에러처리....>

}

 

이 방식은 다음과 같은 문제점이 있다.

 

1. 실행할_함수()는 if문에 파묻혀서 잘 보이지 않는다.

2. 소스코드가 지저분해진다. 소스코드 중간중간에 if문이 끼어들어서 흐름을 끊어놓는다.

 

그럼에도 불구하고 장점도 있다.

1. 예상하지 못한 동작이 발생하는 것이 예방된다. -> 오작동이 치명적인 경우에는 장점이 된다.

2. 각 에러마다 정확한 개별 대응이 쉽다.

 

이런 장점에도 불구하고, if문을 사용하는 에러처리 패턴이 불편하게 느껴지는 것은 사실이다.

defer, recover, panic을 조합하면 예외처리 기능처럼 에러를 뭉뚱그려서 한 번에 처리할 수 있다.

 

try-catch문은 예외가 발생하면 실행이 중단되고, catch문 내용이 실행된다.

go언어에서는 panic이 발생하면 실행이 중단되고, defer문으로 등록한 함수가 실행된다.

 

실행 흐름은 다음과 같으며 소스 코드에서 번호를 매겨놨다.

 

1. 에러발생

2. 패닉발생

3. defer

4. recover

5. 에러처리

 

func F함수_정의(인수A, 인수B,...) {

defer func() {    // 3 : 함수 실행이 종료될 때 자동으로 실행된다. 패닉이 발생해도 실행된다.

if r := recover(); r != nil {    // 4 : recover함수를 실행해서 패닉된 경우 복구한다.

<여기에서 뭉뚱그려서 에러처리>

}

}()

 

.....

반환값, 에러 := F실행할_함수(인수1, 인수2....)

if 에러 != nil {    // 1 : 에러가 발생하면 패닉을 발생시켜서 함수의 실행을 종료하도록 한다.

panic(에러)    // 2  :  패닉이 발생하면 실행이 중단되고,  defer로 함수로 넘어간다.

}

....

}

 

언뜻 보면 소스코드가 오히려 더 복잡해진 느낌이다.

그러나, 다음 2개의 도우미 함수를 사용해서 반복되는 부분을 제거할 수 있게 된다.


 

func F에러2패닉(에러 error) {

if 에러 != nil {    // 에러가 발생하면 패닉 되도록 한다.

panic(에러)

}

}

 

func F패닉_처리(함수 func(r interface{}) {

if r := recover(); r != nil {    // 패닉이 발생한 경우 패닉을 복구하고 지정된 함수를 실행한다.

함수(r)

}

}

 

도우미 함수를 이용해서 소스코드를 간단하게 수정하면 다음처럼 된다.

func F함수_정의(인수A, 인수B,...) {

defer F패닉_처리(func(r interface{}) {

<여기에서 뭉뚱그려서 에러처리>

})

 

.....

반환값1, 에러 := F실행할_함수_1(인수1, 인수2....)

F에러2패닉(에러)    // 에러는 패닉으로 전환되고, defer에 등록된 패닉처리 함수가 실행됨.

 

// 여기까지만 보면 크게 좋은 점을 모르겠으나, 

// 처리해야 할 에러가 많아지면 이러한 방식의 장점이 드러난다.

....

반환값2, 에러 := F실행할_함수_2(인수1, 인수2....)

F에러2패닉(에러)

....

반환값3, 에러 := F실행할_함수_3(인수1, 인수2....)

F에러2패닉(에러)}

...

}

 

타 언어의 try-catch 방식의 예외처리문보아야 여전히 불편하긴 하지만,

if문을 사용해서 모든 에러를 일일이 확인하는 기존의 방식보다는 훨씬 간편하다.

 

GHTS에서는 lib.S예외처리{}.S실행() 으로 되어 있으며

S예외처리의 필드값을 변경하여 실행 옵션을 선택할 수 있다.

 

Go언어 소개

프로그래밍 2014. 11. 4. 20:55 Posted by UnHa Kim

Go언어는 효율성을 추구하는 실용적인 프로그래밍 언어이다.

 

1. 개발 효율성 (혹은 생산성)

2. 실행 효율성 (멀티코어 CPU 활용)

 

이렇게 2가지의 효율성을 추구하는 대신 기능성은 포기했다.

 

Go언어는 애초에 C++언어의 과도한 복잡성과 느린 컴파일 속도 문제로 인한 개발 생산성 저하를 해결하고자 만들어졌기 때문에 단순성과 효율성 (과하다 싶을 정도로) 추구한다.

 

개발자 생산성 향상을 위해서는 다음 특징을 가진다.

1. 빠른 컴파일.

2. 단순하지만 필수기능은 다 갖춘 문법.

3. 자동 메모리 관리

4. 유니코드 지원

5. 풍부한 표준 라이브러리 및 수많은 제3자 공개 라이브러리.

6 테스트, 테스트 커버리지, 동시 사용 데이터 충돌(레이스) 감지등 풍부 개발 도구 기본 내장

 

마지막으로...

7. 소스코드 자동 정리 (써보면 입이 떡 벌어진다. 소스 코드 들여쓰기로 분쟁이 생길 소지를 원천 봉쇄.)

 

 

하드웨어의 효율적 사용을 위해서 다음 특징을 가진다.

1. AOT 컴파일. (C, C++에서 사용하는 컴파일 개념. Java나 C#이 사용하는 JIT컴파일의 반대 개념.)

2. C보다 2배 정도 느리고, Java와는 비슷한 상당히 우수한 단일 스레드 실행 속도.

3. 멀티코어 CPU를 안전하고 효율적으로 사용하기 위한 독특한 기능 (goroutine, channel)

 

Go언어에서는 포기한 기능들은 다음과 같다.

1. 상속은 지원하지 않음. 대신 mixin을 지원.

2. 에러 처리 구문이 취약함.

(try~catch~finally가 없음. 대신, defer, recover 함수를 이용해서 비슷한 효과를 낼 수 있음.)

 

이러한 장단점이 혼합된 Go언어를 실제로 사용해 본 느낌과,

1. 기능성이 약간 부족하지만 오히려 간결해서 좋은 면도 있다.

   기능이 풍부하지 않지만 꼭 있어야 하는 기능들은 거의 다 있으며,

   반대로, 쓸데없는 기능이 없기 때문에 남이 개발한 소스 코드를 읽을 때도

   처음보는 기능을 접하는 경우는 거의 없다.

   그래서, 불러다 쓰는 제 3자 라이브러리가 의심스러우면 

    (저작권 문제가 없는 한도 내에서) 거리낌없이 소스 코드를 들여다보고 만지작 거리게 된다.

2. 개발 생산성이 확연하게 높아진다.

3. 실행속도 문제로 걱정할 일이 없다.

 

트위터가 서비스 초기에 루비(Ruby)언어를 사용했으나, 성능 상의 문제로 인해서 서비스 불안정의 어려움을 겪었고, 결국은 상당 부분을 Java와 Scala언어로 다시 개발해야 했다.

드롭박스도 서비스 초기에 파이썬(Python)언어를 사용했으나, 성능 상의 문제로 인해서 백엔드 상당 부분을 Go언어로 대체하였다.

 

트위터와 드롭박스의 공통점은 높은 개발 생산성을 얻기 위해서

루비(Ruby), 파이썬(Python)등 동적언어를 사용하였으나,

성능상의 문제로 인해서 동일한 기능을 실행 성능이 높은 정적 언어로 다시 작성했다는 것이다.

 

Go언어는 개발 생산성도 높고, 실행 성능도 상당히 높은 편이므로,

이러한 고민을 동시에 해결할 수 있으며,

무한 경쟁 시대에 비용 효율성 면에서 강점을 가진다.

(거대 S/W 기업이 된 구글이 자체적인 비용 절감 차원에서 만든 것 같다.)

 

그 대신에 포기해야 하는 것이 기능성인데, 

막상 써보면 기능이 심하게 부족하다고 느껴지지는 않는다.

 

물론, C++, Java, C#등을 사용하던 사람은

1. 변수 선언 순서가 반대임.

2. 에러 처리 구문이 없고 if문으로 처리함.

등의 장애물에 좌절하곤 하지만 

실제로 사용해보면 의외로 그럭저럭 쓸만 하다.

 

Go언어를 가장 잘 설명하는 문구는  '모든 면에서 80%'이다.

파이썬(혹은 루비) 대비 80% 개발 효율성,

C++ 대비 80% 실행 효율성의 80% (사실은 50%이지만, 동적 언어보다 수백배 빠르므로 체감상 80%)

 

모든 면에서 약간씩 부족하고 아쉽지만,

반면에 치명적인 약점이 없고,

비용절감의 면에서는 타의 추종을 불허하고,

여러모로 공동작업이 편하다.