HOME INFO PROJECT BLOG ESSAY
Article Projects Lab
한국어 English
article |

Spec-kit 써볼까요?

개요

요즘 AI 툴이 굉장히 많이 등장하고 있는데 Github에서 Spec-kit 이라는 툴이 꽤나(?) 유행이어서 사용해봤습니다.

소개 문구를 보면..

Build high-quality software faster.

An open source toolkit that allows you to focus on product scenarios and predictable outcomes instead of vibe coding every piece from scratch.

라고 되어있는데, 대충 번역을 해보면 모든 코드를 처음부터 직접 작성하는 대신, 제품 시나리오와 예측 결과에 집중할 수 있도록 지원하는 툴킷이라고 하네요.

Spec이 뭔가요

Spec이 뭐냐고 물었을 때 아직 일반적인 정의는 없는 것 같습니다.

그럼에도 정의해본다면..

Spec(사양)은 소프트웨어 기능을 표현하고 AI 코딩 에이전트에게 지침 역할을 하는 자연어로 작성된 구조화된 동작 지향 아티팩트(또는 관련 아티팩트들의 집합)입니다. 스펙 기반 개발의 각 변형은 스펙의 구조, 세부 수준, 그리고 프로젝트 내에서 이러한 아티팩트가 구성되는 방식에 대한 접근 방식을 정의합니다.

여기서 Spec과 일반적인 컨텍스트 문서 사이에는 차이가 있는데, Spec이 좀 더 상위 수준(우선 순위가 높다고 하는게 맞을런지..)의 컨텍스트라는 것 입니다.

Cline 같은 에이전트에서는 이런 상위 수준의 컨텍스트를 메모리 뱅크라고 부릅니다.

이렇게 코드 작성 전에 명세서(spec)를 먼저 작성하여 접근하여 개발하는 방식을 Spec-Driven-Development(SDD) 라고 부릅니다.

Spec-kit

Spec-kit은 Github가 SDD 방식으로 개발하는 것을 도와주는 도구입니다.

사실 Spec-kit 이전에 Kiro라는 툴이 먼저 이 방식을 도입했다고 하는데, 저는 대기열에 넣어놨다가 잊어버려서 어쩌다보니 Spec-kit을 먼저 써보게 되었네요.

한 번 설치해봅시다.

## Persistent Installation (Recommended)
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git

## One-time Usage
uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME>

공식 문서에서는 영구 설치를 권장하는데, 저는 일회용으로 설치했습니다.

작업하고 있는 디렉토리에 진입하고 터미널에 스크립트를 입력하면 다음과 같은 화면을 볼 수 있습니다.

원래 지원하는 AI 에이전트가 별로 없었는데, 주기적인 업데이트를 통해서 거의 모든 에이전트가 추가되었네요.

저는 Codex CLI를 선택했습니다.

설치를 하고나면 보안을 위한 유의 사항과 다음 단계를 알려줍니다.

.codex 디렉토리가 생성되는데 거기에 로그 및 세션 관리 파일같은게 남더라구요. 보안을 고려해서 .gitignore에 꼭 포함시켜 줍니다.

다음에는 환경 변수 설정을 위한 설정을 설명합니다.

Codex는 기본적으로 ~/.codex/를 참조하지만, 프로젝트별로 .codex 폴더가 존재할 경우 이렇게 경로를 직접 지정해줘야 프로젝트 로컬 명령을 인식합니다.

지정을 안하면 Spec-kit 커맨드 라인이 나타나지 않습니다. (경험담)

이렇게 커맨드 라인이 나타납니다.

Constitution

/speckit.constitution …

Spec-kit을 설치하고 나면 가장 먼저 작성해야 할 것은 constitution 입니다.

직역하면 ‘헌법’인데 “불변”하고 모든 변경 사항에 항상 적용되어야 하는 상위 수준의 원칙을 담고 있습니다.

실제로 국가의 헌법도 한 국가의 최고 법규이지 않습니까? 비슷한 이치입니다.

이 프로젝트가 constitution를 잘 이행하고 있는지는 진행해보면서 알아봐야 될 것 같습니다. 아직 어떤 내용을 constitution으로 지정해야될지 갈피가 안잡히기도 하구요.

실행해보면 뭔가 열심히 만들고 있긴 합니다. 저같은 경우 테스트 기준, 성능 요구 사항 정도만 요청했습니다.

Specify

/speckit.specify …

다음은 사양인데요 여기에는 기술 스택이 아니라 ‘무엇’ 과 ’ 왜’ 에 집중하여 기술해야합니다.

예를 들어서 사진을 정리하는 애플리케이션을 구축한다고 하면 ‘사진을 별도의 앨범으로 정리할 수 있는 애플리케이션을 구축해야한다.’, ‘각 앨범 내에서 사진은 타일 형태의 인터페이스로 미리 볼 수 있어야한다.’ 이런 내용이 포함되어야 합니다.

Plan

/speckit.plan …

plan은 개발자들이 좋아하는 기술적인 부분을 기술하는 파트입니다.

백엔드는 Java, Spring을 쓰고, DB는 Mysql 어쩌구.. 이런 내용이 되겠지요.

권장 사항은 원하는 스택, 아키텍처, 제약 조건을 제공하면 코딩 에이전트가 포괄적인 기술 계획을 생성해준다고 합니다.

Task

/speckit.tasks

tasks는 구현 계획에서 실행 가능한 작업 목록을 만드는 데 사용합니다.

예전에 나왔던 Taskmaster라는 툴과 유사한 작업을 하는 것 같습니다.

예를 들어 “빌드 인증”과 같이 이렇게 간단하게가 아니라, “이메일 형식을 검증하는 사용자 등록 엔드포인트 생성”과 같은 구체적인 작업을 지정해준다고 합니다.

Implement

/speckit.implement

이제 작성한 spec을 통해서 드디어 구현을 시작합니다. 에이전트는 작업을 하나씩 (또는 필요한 경우 병렬로) 처리하게 되지요.

Spec-kit에서 말하기로는 개발자는 수천 줄의 코드 덤프를 검토하는 대신, 특정 문제를 해결하는 변경 사항을 집중적으로 검토하는 쪽이라면, 코딩 에이전트는 명세에 따라 무엇을 만들어야 하는지 알고, 계획에 따라 어떻게 만들어야 하는지 알고, 작업에 따라 무엇을 해야 하는지 정확히 알고 있다고 합니다.

사실 말로는 그럴 듯한데 에이전트가 spec대로 얼마나 잘 이행하고 규칙을 잘 준수하는지는 지켜봐야겠네요.

지금까지 쓰면서 느낀 점

지금까지 쓰면서 느낀 점은 ‘0 to 1’ 작업에는 꽤나 괜찮은 툴이라고 생각합니다.

다만 spec이나 plan 같은 걸 작성하는데 시간이 꽤 걸릴 뿐더러 맘대로 브랜치를 만들지를 않나(다소 빡침), 이런 부분은 컨트롤이 필요해보입니다. (저만 그런게 아니더군요 Github Discussion: Evolving specs)

이건 Spec-kit 특성 상 기능의 수명이 아니라, Spec 자체를 살아있는 아티팩트로 봐서 그런 듯 합니다.

Spec-kit의 의도대로라면 이 Spec이라는게 한 번 쓰이고 마는게 아니라 살아 있는 문서처럼 관리해야 하는데, 이런 부분이 꽤 피로감있게 다가올 수도 있을 것 같습니다.

Spec 자체를 버전 관리 대상에 포함시켜서 관리한다면 꽤나 괜찮은 SDD가 가능하지 않을런지..

하지만 무엇보다 이걸 초기 템플릿으로 삼아 각자 자기에 입맞에 맞는 Spec-kit를 만들어본다면 베스트일 것 같네요

맺음

다음에는 Spec-kit으로 작업하면서 느낀 좋은점, 개선점을 적어보겠습니다.

읽어주셔서 감사합니다.

출처

article |

압축 알고리즘의 변천사에 대해 알아보자

개요

오랜만에 돌아온 origin series 입니다.

이번 글의 주제는 ‘압축 알고리즘’인데요, 갑자기 압축이라는 주제에 꽂히게 된 이유는 ‘압축 알고리즘의 르네상스’라는 글을 너무 재밌게 봐서 압축 알고리즘은 어떻게 변해왔는지 궁금증이 생겼기 때문입니다.

사실 컴퓨터 과학을 공부하기 이전에도 사진 파일들을 압축하면서 ‘그냥 데이터 덩어리일 뿐인데 어떤 방식으로 용량이 작아지는 거지?‘라는 의문을 가진 적이 있었는데 드디어 이 의문에 대해 마주하게 되었네요.

글의 독자는 다음과 같습니다.

  • 초기 압축의 기초가 되는 알고리즘이 궁금해요.
  • 압축 알고리즘이 왜 중요해지고 있는지 알고 싶어요.

손실 압축(lossy compression)과 무손실 압축(lossless compression)

먼저 데이터 압축의 사전적 의미는 무엇일까요? 위키에 따르면 다음과 같습니다.

데이터를 더 적은 저장 공간에 효율적으로 기록하기 위한 기술, 또는 그 기술의 실제 적용을 가리킨다.

이 압축은 ‘데이터의 손실 유무’에 따라서 손실 압축무손실 압축으로 나뉘는데요:

먼저 손실 압축은 특정 정보, 특히 중복 정보를 영구적으로 제거하여 파일의 용량을 줄이는 방법입니다.

사람은 지구 상의 모든 색상을 포토샵처럼 상세하게 색을 구별하거나(마비노기 유저들은 가능할 것 같지만), 절대 음감이라고 해서 모든 주파수를 들을 수 없습니다.

그 부분을 이용해 음악이나 영상과 같은 매체에서 구별하기 어려운 색차나 주파수를 손실시켜서 용량을 줄이는 압축 방식입니다.

이러한 특성때문에 압축을 반복하게 되면 손실이 누적되어 원본과는 큰 차이가 발생하게 되죠.

반면 무손실 압축은 명칭 그대로 손실이 없는 압축 방식입니다. 원본 그대로를 저장하지 않는데 용량을 어떤 식으로 줄이는 걸까요?

뒤에 다른 알고리즘을 소개하겠지만 ‘런 렝스 부호화(Run-length encoding, RLE)‘를 예시로 무손실 압축의 원리를 알아보겠습니다.

런 렝스 부호화는 데이터에서 같은 값이 연속해서 나타나는 것을 그 개수와 반복되는 값만으로 표현하는 방법입니다.

WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW

위와 같은 문자열이 있다고 해봅시다. 위를 런 렝스 부호화를 적용하면 다음과 같이 압축할 수 있습니다.

12WB12W3B24WB14W

‘12개의 W, (한 개의) B, 12개의 W, 3개의 B, 24개의 W, (한 개의) B, 14개의 W’로 해석되는 것이죠.

압축 전에는 67글자였지만, 압축 후에는 단지 16글자만으로 표현할 수 있게 되었습니다.

이때 데이터의 크기는 ‘67바이트’에서 ‘16바이트’로 줄었으므로 압축률은 약 4.18이 되는 것이죠!

압축 과정에서 데이터 손실이 없었기 때문에 다시 디코딩해도 원본의 손실없이 데이터를 다시 불러올 수 있습니다.

각 압축 방식에 대해 정답은 없지만 성격에 따라 다음과 같은 점을 고려할 수는 있겠죠.

특정 웹사이트는 손실 압축을 통해 파일 크기를 크게 줄여 저장 공간을 절약함으로써 사이트 성능과 사용자 경험을 향상시킬 수 있는 반면, 고품질 사진이 필요한 웹사이트는 무손실 압축을 사용하는 것이 더 적합할 것 입니다.

초기 압축 알고리즘의 태동

섀넌의 정보 이론

클로드 섀넌은 디지털 시대의 아버지로 불릴 정도로 여러 업적을 세웠는데요, 데이터의 효율적인 전송과 저장에 대한 수학적 모델을 제공하고, 오늘날의 통신 시스템이나 데이터 압축과 같은 기초를 형성했습니다.

당시 전화, 전신 등 통신 시스템이 점점 복잡해지면서 신호의 효율적 전송과 오류 없는 정보 전달이 중요한 과제로 대두되었습니다.

섀넌의 혁신은 “정보”를 의미(meaning)와 분리하여, 오직 ‘신호의 선택 가능성’과 ‘불확실성 감소’라는 관점에서 수학적으로 정의했다는 점입니다.

여기서 정보를 “불확실성을 줄이는 정도”로 보고, 이를 엔트로피(Entropy)라는 개념으로 정량화했습니다.

예를 들어, 동전 던지기(앞/뒤 확률 50%)의 엔트로피는 1bit이며, 이는 정보를 전달하는 데 필요한 최소 비트 수를 의미합니다.

이전에는 의사소통이 단순한 메시지 전달로 여겨졌지만, 섀넌은 정보를 측정, 정량화, 최적화할 수 있다는 개념을 제시한 것이죠.

섀넌-파노 부호화(Shannon-Fano coding)

섀넌과 로버트 파노가 공동 개발한 이 부호화 기술은 정보 이론의 엔트로피 개념을 실용화한 사례입니다.

코드의 알고리즘 원리를 알아보면 다음과 같습니다. • 섀넌 방식: 각 심볼의 등장 확률에 따라 코드워드의 길이를 미리 정하고, 누적 확률의 이진 표현을 이용해 코드를 할당 • 파노 방식: 심볼을 등장 빈도 순으로 정렬한 뒤, 전체 확률이 비슷하도록 두 집합으로 나누고, 각각 0과 1을 할당하며 재귀적으로 분할. 이 과정을 반복해 각 심볼에 고유한 이진 코드를 부여

이를 정말 쉽게 설명해보자면 “자주 나오는 글자는 짧게, 드물게 나오는 글자는 길게 코딩하는 방법” 이라고 정의할 수 있을 것 같습니다.

한 번 예시를 통해 알아보겠습니다.

정보량 = -log₂(확률)

그렇게 되면 확률에 따른 정보량은 다음과 같습니다.

확률 50% → 1비트 필요 확률 25% → 2비트 필요 확률 12.5% → 3비트 필요

이는 “희귀할수록 더 많은 정보를 담고 있다”는 것을 의미합니다.

여기서 파노의 방법을 예시와 함께 알아보겠습니다.

심볼: A(40%) B(30%) C(20%) D(10%) 1단계: A(40%) vs BCD(60%) → A=0, BCD=1 2단계: B(30%) vs CD(30%) → B=10, CD=11 3단계: C(20%) vs D(10%) → C=110, D=111

위 파노 방식의 설명을 간단하게 정리해봤는데요, 다음과 같이 구분할 수 있을 것 같습니다.

정렬: 확률 높은 순으로 줄세우기 분할: 전체를 반반(비슷하게) 나누기 코딩: 한쪽은 ‘0’, 다른쪽은 ‘1’ 붙이기 반복: 각 그룹을 또 반반 나누기

그렇게 되면 최종 결과는 A=0, B=10, C=110, D=111라는 심볼이 완성되죠.

섀넌-파노 부호화는 효율적인 가변 길이 코드를 생성하지만, 동일 확률 분할 시 발생하는 비최적화 문제로 인해 항상 최적의 코드를 보장하지는 않습니다.

하지만 무손실 압축의 시조로써 현대 정보 이론의 출발점이라는 의의가 있습니다.

허프만 부호화(Huffman Coding)

1952년 미국 MIT 대학의 박사 과정을 밟고 있던 데이비드 허프만은 《A Method for the Construction of Minimum-Redundancy Codes》라는 논문을 발표합니다.

허프만은 문자별 빈도를 고려해 평균 코드 길이를 최소화하는 최적의 부호화 방식을 고안했고, 이는 기존의 고정 길이 부호 방식(예: 아스키 코드)보다 훨씬 효율적이었습니다.

허프만의 알고리즘을 텍스트로 보자면 다음과 같습니다:

  1. 초기화 : 모든 기호를 출현 빈도수에 따라 나열
  2. 단 한 가지 기호가 남을 때까지 아래 단계를 반복 3. 목록으로부터 가장 빈도가 낮은 것을 2개 고른다. 4. 그 다음 허프먼이 두가지 기호를 부모 노드를 가지는 부트리를 구성하고 자식노드를 생성한다. 부모 노드 단 기호들의 빈도수를 더하여 주 노드에 할당하고 목록의 순서에 맞도록 목록에 삽입한다. 5. 목록에서 부모노드에 포함된 기호를 제거한다.

설명만으로는 잘 와닿지 않으니 예시를 한 번 살펴보겠습니다.

먼저 다음과 같은 데이터가 주어진다고 가정해봅시다.

빈도 순으로 정렬한 데이터에서 가장 작은 2개 합칩니다. -> A(5) + B(9) = 14

그렇게 되면 현재 목록은 C(12) - D(13) - AB(14) - E(16) - F(45) 이와 같습니다.

이걸 트리로 구성해보겠습니다.

        100(루트)
       /       \
    F(45)      55
             /    \
          CD(25)  ABE(30)
          /   \    /     \
       C(12) D(13) AB(14) E(16)
                   /  \
                A(5) B(9)

이제 bit를 할당해보겠습니다.

        100(루트)
       /          \
     0/            \1
   F(45)          55
                 /    \
               0/      \1
            CD(25)   ABE(30)
            /   \      /     \
          0/     \1  0/       \1
        C(12)  D(13) AB(14)  E(16)
                     /  \
                   0/    \1
                 A(5)   B(9)

자주 나오는 F는 1비트를 드물게 나오는 A,B는 4비트 할당하게 됩니다.

허프만 부호화의 핵심은 문자나 심볼의 등장 빈도에 따라 자주 등장하는 심볼에는 짧은 이진 코드를, 드물게 등장하는 심볼에는 긴 이진 코드를 할당하는 것입니다.

허프만 부호화가 가지는 의의는 엔트로피 부호화(Entropy Encoding)로써, 데이터의 통계적 중복성을 효과적으로 제거하여 평균 부호 길이를 이론적 한계(엔트로피)에 가깝게 줄였다는 점입니다.

상용 압축 기술과 특허 시대

LZW와 GIF의 상업화

1980년대 후반, 컴퓨터 그래픽과 인터넷의 확산과 함께 효율적인 이미지 압축 기술이 필요해졌습니다.

이 시기 개발된 GIF(Graphics Interchange Format)LZW(Lempel-Ziv-Welch) 무손실 압축 알고리즘을 채택해 이미지 파일 크기를 크게 줄일 수 있었고, 곧 인터넷과 소프트웨어 산업에서 표준 포맷으로 자리잡았습니다.

당시 LZW 알고리즘은 공개 논문과 기사로 널리 알려져 있었기 때문에, 많은 개발자와 기업들은 이를 자유롭게 사용할 수 있다고 생각했습니다.

Unisys 특허 사건

하지만 LZW 알고리즘은 Unisys과 IBM이 특허를 보유하고 있었고, 1990년대 중반이 되어서야 이 사실이 널리 알려졌습니다.

Unisys와 CompuServe는 GIF 포맷에 대한 라이선스 계약을 체결하고, 상업적 소프트웨어와 웹 서비스에 LZW 사용료를 부과하기 시작했습니다.

이로 인해 개발자들 및 커뮤니티에서는 강한 반발이 일어났고, “Burn All GIFs Day”와 같은 캠페인이 등장했습니다.

특허 논란은 GIF와 LZW의 자유로운 사용을 막았고, 특허 만료(2003~2004년) 전까지 특허료 부담이 지속되었습니다.

이 사건은 소프트웨어 특허의 복잡성과, 공개 표준에 대한 특허 적용이 산업과 인터넷 생태계에 미치는 영향을 대표적으로 보여주는 사례가 되었습니다.

Deflate의 탄생

이러한 특허 논란과 상업적 제약에 대응하기 위해, 1993년 필 캐츠(Phil Katz)는 특허에 구애받지 않는 새로운 압축 알고리즘인 Deflate를 개발했습니다.

Deflate는 LZ77과 허프만 코딩을 결합해 높은 압축률과 빠른 속도를 제공하면서도, 특허 문제 없이 누구나 자유롭게 사용할 수 있도록 설계되었습니다.

무엇보다 웹의 시대가 도래하면서 전송 속도와 대역폭 용량 개선을 위해 HTTP 압축이라는 기술의 필요성이 생겼는데 이 알고리즘 방식이 채택되기도 했죠.

ZIP, Gzip, PNG 등 다양한 파일 포맷과 인터넷 표준에서 널리 채택되었고, 특허 이슈로부터 자유로운 오픈 포맷의 대표적 성공 사례가 되었습니다.

Gzip

gzip은 ZIP과 같이 DEFLATE 알고리즘을 따르지만, 여러 파일을 하나의 파일로 압축하는 옵션이 없다는 점에서 차이가 납니다.

웹 서버로 리소스를 요청할 때 Request Header의 accept-encoding을 볼 수 있습니다.

브라우저에서 호환되는 압축 정보를 실어 함께 요청하면, 해당하는 압축 방식을 지원하는지 확인하고, 지원한다면 리소스를 압축하여 리소스를 전달하게 됩니다.

Gzip 방식으로 HTTP 리소스를 압축하여 기본 용량보다 70~80% 리소스 사이즈를 줄일 수 있게 되었습니다.

이후에는 구글의 Brotli와 Facebook의 Zstandard도 이어서 등장하면서, Gzip보다 더 높은 압축률과 빠른 속도를 제공하며, 현대 웹과 시스템 환경에서 점점 더 많이 사용되고 있습니다.

이들은 효율적인 데이터 전송을 위한 차세대 압축 알고리즘으로 자리 잡아가고 있습니다.

맺음

앞으로 미래 압축기술은 어떨까요?

최근에는 AI, 특히 딥러닝을 활용한 압축 기술이 주목받고 있는데요, 기존 압축 알고리즘은 주로 데이터 내 반복 패턴이나 통계적 특성을 분석해 효율적으로 인코딩했지만, AI 기반 압축은 대규모 데이터셋에서 패턴을 직접 학습하여 더 높은 압축률과 품질을 달성하고 있다고 합니다.

샤논 한계에 따르면 데이터를 아무리 효율적으로 압축해도 그 데이터가 가진 엔트로피(불확실성, 정보량) 이하로는 압축할 수 없다는 한계가 있는데, 양자 컴퓨터의 발전이 이를 해결해줄수도 있지 않을지 생각해봅니다. (전문가가 아니라 하하..)

역사를 다루는 글은 언제나 재밌네요. 이번에도 읽어주셔서 감사합니다.

출처