Nov 27, 2023 - 인공지능 제대로 일 시키기

얼마전에 개발자에게 두려웠던 나머지… 라는 유투브 내용을 감명깊게 보았습니다.

YouTube Video

위 유투브 동영상은 프롬프트에서 원하는 걸 명확하게 요구해야하거나 역활부여에 대한 프롬프트 팁에 대한 설명과 함께, 챗GPT 를 잘 활용할 수 있는 내용들의 유익한 유투브 내용이었습니다.

그러한 부분이, 인공지능 제대로 일 시키기 라는 책에서도 잘 나오고 있습니다.

WORK_AI

5년 뒤에는 과연 개발자가 할일이 있을까 싶을 정도로, 현재 챗GPT 가 매우 좋은 코드 컨밴션을 가지고 코드를 작성하며,

개념적인 내용이나, 여러 디자인패턴들을 잘 사용하고 있습니다.

저는 일을 할 때, 챗GPT 를 매우 많이 사용합니다.
단순 작업을 할때도,
혹은 어려운 작업을 할때도 챗GPT 를 잘 사용합니다.

내가 원하는 결과를 얻기 위해, 적어도 3번 이상 같은 질문을 해야하는데, 이 책을 읽고 나서, 좀더 원하는 방법을 잘 찾는 노하우를 얻게 되었습니다.

책에 나오는 기본 단계 프롬프트 엔지니어링의 정리는 다음과 같습니다.

  1. 구체적으로 작성할 것
  2. 프롬프트를 작성하려는 배경을 잘 설명할 것
  3. 기대하는 응답에 대한 예시를 추가할 것 (이것은 예시를 그대로 사용하는 단점이 있을 수 있습니다. ㅠㅜ)
  4. 잘 사용되지 않거나 동응이의어가 있는 경우에 대한 정의 등을 사전에 정리함.
  5. 문법적 오류, 모호성을 제거함.
  6. 최대한 간결하게, 토큰화할 수 있게 필요한 정보가 누락되지 않게 단어를 잘 정리함.
  7. 하이퍼파라미터 튜닝 (이 책의 가장 중요한 포인트!)
  8. 반복 질문, 7번 항목을 이용하여, 동일한 질문을 조금씩 튜닝해서 원하는 겨로가에 최대한 맞출 수 있도록 처리함.
  9. 불필요한 정보를 제외하여 원하는 응답의 범위를 조절함.

직업 상 해외 이탈리아 업체들과 이메일로 소통을 해야하는 경우가 많은데, 이 때도 챗GPT 를 자주 사용합니다. ‘이러이러한 내용을 비지니스 이메일 영어로 작성해줘’ 라는 한글을 요청을 ‘비지니스 이메일’을 한글로 작성해주거나, ‘영어’ 로 이상하게 번역하는 경우가 작성을 하는 경우가 많고, ‘영어로 작성된 비지니스 이메일을’ 이라고 해도, 한글로 적다보니, 한글로 작성하는 경우가 많았습니다.

그런데, 프롬프트 방법을 알게되어,

비지니스 이메일을 작성해줘 {영어로 작성}

로, 조금 더 명확하게 명령을 내릴 수 있게 되어, 업무의 편의성이 증가되었습니다.
이 책을 읽으면서, 프롬프트에 대해 조금 더 학습할 수 있었습니다.

아직 {결과{앞의 프롬프트와 동일}} 과 같은 패턴을 동일하게 하는 법보다, 그냥 새롭게 동일한 내용을 챗GPT 에게 물어보는 것이 더 익숙하지만, 책에 내용은 30% 정도 그림 생성 AI 쪽에 대한 프롬프트를 할애하고 있어, 그 쪽에 관심이 있는 책에서 알려준 프롬프트 마켓플라이스를 좀더 검색해보면서, 좋은 프롬프트 엔지니어링을 배워야할 듯 합니다.

Nov 1, 2023 - gradlew clean build

(base) ➜  dcode-apis_231101 git:(master) ✗ ./gradlew clean build --refresh-dependencies
FAILURE: Build failed with an exception.

* What went wrong:
  Timeout waiting to lock daemon addresses registry. It is currently in use by another Gradle instance.
  Owner PID: unknown
  Our PID: 69227
  Owner Operation: unknown
  Our operation:
  Lock file: /Users/bymin/.gradle/daemon/6.7/registry.bin.lock

* Try:
  Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

–refresh-dependencies: 이 옵션은 프로젝트의 의존성(dependencies)을 새로 고침하는 역할을 합니다.
이는 프로젝트의 Gradle 설정 파일 (보통은 build.gradle 또는 build.gradle.kts)에서 정의된 의존성을 검사하고,
캐시된 의존성 정보를 업데이트합니다.
이렇게 하면 최신 버전의 라이브러리 및 종속성을 사용할 수 있게 됩니다.

(base) ➜  dcode-apis_231101 git:(master) ✗ ./gradlew --stop
Stopping Daemon(s)
2 Daemons stopped

다른 Gradle 데몬 인스턴스가 실행 중인 경우, 해당 프로세스를 종료하고 다시 시도하는 것이 좋습니다.

만약 stopped 가 잘안되면,

ps -ef | grep gradle

로 검색 후 kill -9 프로세스ID 로 처리 가능합니다.

Oct 23, 2023 - 기술 부채를 바라보는 시각

회사 내부 백엔드 팀원들에게 진행했던 소프트한 컨퍼런스 입니다.

주제는 우리가 지금 가진 기술 부채는 무엇이며,
그 부채를 해결하기 위해 우리는 무엇을 해야할 것인지 논의하는 자리였습니다.

기술부채는 무엇입니까?

기술적 부채(技術的 負債, technical debt)란, 
**사회와 각 개인들로 이루어진 소프트웨어 등의 결함에 따라서 새로운 기능을 개발하는 데 장애요인이 발생하는 것을 말함.**

부채가 이자를 내고 돈을 쓰는 시점을 당기는 것처럼 기술 부채는 기술적으로 해결되어야할 문제를 뒤로 미루고, 비즈니스 문제를 해결하는 시점을 당기는 것입니다.

기술 부채 항목들

  • 설계된 것을 문서화 하지 않는다.
  • 유닛 테스트를 작성하지 않는다.
  • 더 이상 사용되지 않는 DB의 항목을 지우지 않는다.
  • 반복되는 일을 자동화 하지 않는다.
  • 긴급하게 스펙을 변경한다.

망해가는 회사 프로세스

악취 나는 코드/작성되지 않는 테스트 => 개발속도 저하/ 품질 저하 => 비지니스 속도 저하/고객만족감소 => 수익감소 => 기술적 채무 상환 보류 => 악취나는 코드/작성되지 않는 테스트(반복)

성공하는 회사의 프로세스

향상된 코드/자동화 테스트 => 개발속도 증가/품질 향상 => 비지니스 속도 증가 => 고객 만족도증가/수익증가 => 기술적 자산에 대한 투자 => 향상된 코드(반복)

기술 부채를 어떻게 하면 없앨 수 있을까요?

  • 이 질문에 대한 답은 ‘No’ 입니다.
  • 많은 회사들이 DDD(Deadline Driven Development)에 의한 기술 부채가 발생하고 이는. 피할 수 없는 자연스러운 현상입니다.

다만 한가지 기억해야하는 것이 어떻게 빚을 갚을 것이냐는 겁니다.
빚을 지고 있으면, 마음이 불편합니다. 특이 빚을 처음 질 때 가장 불편합니다.
하지만 그 상황이 계속 되면 그 빚을 지고 있는 상황이 익숙해집니다.

빌리는 것은 쉽지만 갚은 것은 어렵습니다.
게다가 한 번에 갚는 것은 매우 어렵습니다.

지금 당장 문서를 쓰지 않고, 테스트를 작성하지 않는 것은 쉽지만 나중에 그것을 회복하기는 어렵습니다.

완성도(Completeness) vs 적시성(Timeliness)

완성도(Completeness)는 소프트웨어가 기능적 요구사항을 완벽하게 충족하는지 여부를 나타내는 것입니다.

높은 완성도는 품질 높은 소프트웨어를 만드는데 중요합니다.

완성도가 높은 소프트웨어는 적은 결함과 높은 성능을 가지며, 사용자들의 만족도가 높아지게 됩니다. 하지만 완성도를 높이기 위해서는 시간과 비용이 많이 들어가게 됩니다.
적시성(Timeliness)은 소프트웨어를 빠르게 개발하여 빠른 시장 진입이나 기업 성장에 도움을 주는 것을 의미합니다.
적시성이 높은 소프트웨어는 빠르게 수정되어 사용자들의 요구사항에 더욱 빠르게 대응할 수 있으며, 경쟁 우위를 유지하는데 중요합니다. 하지만 적시성을 높이기 위해서는 완성도를 희생할 수 있으며, 이로 인해 기술부채가 발생할 수 있습니다.
따라서 개발자들은 완성도와 적시성을 모두 고려하여 적절한 기술부채를 유지해야 합니다.

완성도를 높이기 위해 기술부채를 적극적으로 늘리는 것은 바람직하지 않지만, 완성도와 적시성 사이에서 타협점을 찾아야 합니다.

이를 통해 소프트웨어 개발의 질을 유지하면서도 빠른 시장 진입과 경쟁 우위를 유지할 수 있습니다.

documentation, test coverage등의 문제를 해결한 완성도 높은 서비스 vs 부족하더라도 시장성이 있는 서비스

→ 결국 현실적인 상황때문에, 후자를 선택할 수 밖에 없습니다.

우리의 대응

“방망이 깎던 노인” 스토리. 수필 속의 주인공이 방망이를 주문하는데, 노인이 해가 질 때 까지 방망이를 깎고 또 깎고, 재촉하는 주인공에게 노인이 이렇게 이야기합니다.

“글쎄, 재촉을 하면 점점 거칠고 늦어진다니까. 물건이란 제대로 만들어야지, 깎다가 놓치면 되나.”

결국 밤늦게 집에 와서 방망이를 내놨더니 아내는 예쁘게 깎았다고 야단이다.
라는 글에서 보통 개발자들은 보통 이 수필속 노인이 됩니다.
견고한 아키텍처를 만들고 싶지만 현실은 최소기능제품(Minimum Viable Product, MVP) 형태로 서비스를 만들어야 할 때가 많고,
스트레스도 받고, 그렇게 개발하고 싶어하지 않습니다.

돈도 시간도 인적자원도 다 부족한 탓일 겁니다.

이제는 이 빚을 어떻게 안만들까를 고민하기보다, 어떻게 빚을 갚을지를 고민해야할 시간이라고 생각합니다.
돈을 빌리면 갚아야 하고, 원금을 갚을 수 없다면 이자라도 갚는 것이 현실이라 생각합니다.

주기적인 이자 상한

기술 부채를 상환해본다고 했을 때, 당장은 급해 죽겠으니까 이자부터라도 갚는 것을 생각해볼 수 있습니다.

Refactoring: 소프트웨어 코드의 구조나 설계를 개선하여 유지보수 및 확장성을 향상시키는 작업입니다.
주기적인 Refactoring은 기술부채를 줄이고 코드 품질을 높이는데 도움이 됩니다.
또한 코드의 복잡성을 낮춰 개발자들이 코드를 이해하기 쉽게 만들어주기도 합니다.
주기적으로 Refactoring을 수행하면 코드의 유지보수와 확장성을 개선할 수 있습니다.

Pair-programming: 두 명의 개발자가 하나의 컴퓨터로 협력하여 코드를 작성하는 방법입니다.
주기적인 Pair-programming은 코드 품질을 향상시키고 기술 부채를 줄이는 데 도움이 됩니다.
또한 개발자들이 서로 경험을 공유하고 서로의 능력을 향상시키는 데도 도움이 됩니다.
주기적으로 Pair-programming을 수행하면 개발자들 간의 커뮤니케이션도 개선됩니다.

  • 보통 코드를 작성한 인원이 해당 코드의 유지보수까지 맡게 됩니다.
  • 그 인원이 휴가, 퇴사, 입원과 같은 이유로 자리를 비운다면 이 코드는 바로 방치가 될 것이고, dead code가 될 가능성이 높습니다.
  • 한명은 프로덕트 코드를, 한명은 테스트 코드를 작성하는 등의 페어프로그래밍이 이를 방지할 수 있다.

Risk management: 프로젝트에서 발생할 수 있는 위험을 파악하고 그에 따른 대응책을 수립하는 작업입니다.
주기적인 Risk management는 프로젝트의 위험을 예측하고 방지할 수 있도록 도와줍니다.
또한 위험 대응책을 만들어두면 프로젝트가 진행되는 동안 예기치 않은 문제가 발생했을 때 대처할 수 있습니다.
주기적으로 Risk management를 수행하면 프로젝트의 안정성을 높일 수 있습니다.

Testcase: 소프트웨어의 기능을 검증하기 위한 테스트 케이스를 작성하는 작업입니다.
주기적인 Testcase 작성은 코드의 품질을 높이고 기술 부채를 줄이는 데 도움이 됩니다.
또한 테스트 케이스를 작성함으로써 코드의 동작을 확인하고 오류를 발견할 수 있습니다.
주기적으로 Testcase를 작성하면 소프트웨어의 품질을 향상시킬 수 있습니다.

  • 로그는 100% 재현이 불가능합니다.
  • 따라서 사후 처리를 위해서는 디버그 범위를 줄이는 것이 도움이 된다. 테스트 케이스 작성하기가 효과적인 방법이다.

여유(돈)가 있다면 원금 상한

Restructuring: 기존의 코드를 개선하여 유지보수와 확장성을 향상시키는 작업입니다.
코드의 복잡성을 줄이고 개발자가 이해하기 쉬운 구조로 변경함으로써 기술 부채를 해결할 수 있습니다.
이를 위해 코드 리팩토링 작업을 수행하거나, 디자인 패턴을 도입하는 등의 방법을 사용할 수 있습니다.
(외부의 전문가들을 데려와서 노하우를 배우는 등의 방법도 필요에 따라 좋습니다.)

Dead code detection: 프로젝트에서 사용되지 않는 코드를 제거하는 작업입니다.
사용되지 않는 코드는 유지보수 비용만 불필요하게 증가시키고, 코드를 이해하기 어렵게 만들어 기술 부채를 증가시킵니다.
Dead code detection을 수행하여 불필요한 코드를 제거함으로써 기술 부채를 해결할 수 있습니다.

  • static analyzing tool
  • Naver Deview 2일차의 런타임 데드 코드 분석 도구 Scavenger - 당신의 코드는 생각보다 많이 죽어있다. 이 내용도 도움이 될 거 같습니다.

Continuous migration: 기술 부채를 해결하기 위해서는 최신 기술과 도구를 적극적으로 도입해야 합니다.
Continuous migration은 이전 시스템을 새로운 시스템으로 지속적으로 이전시켜가는 작업입니다.
이를 통해 기존 시스템에서 발생하는 기술 부채를 줄이고, 새로운 기술과 도구를 적극적으로 도입하여 기술 부채를 해결할 수 있습니다.

  • 오래된 시스템(legacy)을 마이그레이션 해봅시다.

Risk management: 프로젝트에서 발생할 수 있는 위험을 파악하고 그에 따른 대응책을 수립하는 작업입니다.
예측치 못한 위험이 발생했을 때 대처하기 쉬워지므로 비용과 시간을 절약할 수 있습니다.

Risk management은 프로젝트에서 발생할 수 있는 위험 요소를 파악하고 그 위험을 최소화하기 위한 일련의 절차를 수행하는 활동입니다.
이는 프로젝트에서 발생할 수 있는 모든 위험을 파악하고, 위험의 가능성과 영향을 평가하며, 위험을 감소시키기 위한 계획을 수립하고 실행하는 과정을 포함합니다.

Risk management는 다음과 같은 단계를 거쳐 수행됩니다.

  1. Risk identification: 프로젝트에서 발생할 수 있는 모든 위험을 파악하고 문서화합니다. 이를 위해, 이전 프로젝트나 유사한 프로젝트의 위험을 분석하거나, 프로젝트 팀의 경험을 활용하는 등의 방법을 사용합니다.
  2. Risk analysis: 파악한 위험에 대해 가능성과 영향을 평가합니다. 이를 위해, 각각의 위험에 대해 확률과 영향의 크기를 평가하여 위험의 우선순위를 결정합니다.
  3. Risk response planning: 각각의 위험에 대해 대응책을 수립합니다. 이를 위해, 위험을 회피, 전이, 완화, 수용하는 등의 방법으로 대응책을 마련합니다.
  4. Risk monitoring and control: 대응책을 수행하며 위험을 감시하고, 위험 상황이 발생했을 때 즉각적으로 대처합니다. 이를 위해, 위험 상황을 모니터링하고, 위험 상황 발생 시 팀원들에게 통보하며, 위험 관리 계획을 업데이트합니다.

Risk management는 프로젝트의 성공을 위해 중요한 활동입니다. 위험을 사전에 파악하고 대응책을 마련하여 위험을 감소시키면 프로젝트의 성공 가능성이 높아지며, 기술 부채를 해결하는데에도 큰 도움이 됩니다.

후불코딩

부채를 해결하는 방법은 기술부채를 후불코딩으로 생각하는 마인드 변화가 필요합니다.

  1. Static Analysis (정적 분석)
    정적 분석은 코드를 실행하지 않고 코드의 문법, 구조, 규칙, 패턴 등을 검사하는 방법입니다. 이를 통해 버그나 코드의 품질을 향상시키는 데 도움이 됩니다. 부채 정리를 스마트하게 하기 위해서는 정적 분석을 통해 코드의 품질을 높이고 잠재적인 버그를 사전에 발견할 수 있도록 하는 것이 중요합니다.
  2. Test code (테스트 코드)
    테스트 코드는 코드를 실행해보면서 코드의 동작을 검증하는 것입니다. 테스트 코드를 작성하면 코드를 수정할 때마다 자동으로 검증할 수 있어서 코드의 안정성과 신뢰성을 높일 수 있습니다. 부채 정리를 스마트하게 하기 위해서는 테스트 코드를 작성하여 코드를 검증하고 변경 사항이 있을 때마다 자동으로 실행하도록 구성하는 것이 중요합니다.
  3. CI/CD (지속적 통합/배포)
    CI/CD는 코드를 빌드하고 테스트하고 배포하는 프로세스를 자동화하는 방법입니다. CI/CD를 구성하면 코드 변경 사항을 즉시 테스트하고 배포할 수 있어서 빠른 개발과 안정적인 배포를 동시에 할 수 있습니다. 부채 정리를 스마트하게 하기 위해서는 CI/CD를 구성하여 코드 변경 사항이 발생하면 자동으로 테스트하고 배포하도록 하는 것이 중요합니다.
  4. Communication (의사 소통)
    부채 정리는 여러 사람이 함께 작업해야 합니다. 이때 각각의 역할과 책임을 명확하게 하고 의사 소통을 잘하는 것이 중요합니다. 부채 정리를 스마트하게 하기 위해서는 팀원들과 의견을 공유하고 문제점을 해결하는 데에 적극적으로 참여하는 것이 중요합니다.