금번 업데이트는 무려 5일이나 걸렸습니다. 기획하고 설계에 3일정도 시간을 사용하였습니다. 일을 하고 있기 때문에 주로 저녁에 일 6시간 정도 사용하였습니다. 개발도 1박 2일 (저는 자고, 클로드님은 일해주셨습니다.) 이나 걸렸습니다. 주위 분들이 이걸 왜 하고 있느냐고 많이들 이야기 합니다. 많은 오픈 소스가 호기심에서 시작하지 않았을까요? 크고 작은 파일럿 프로젝트나 개인 연구 과제의 예산은 그리 많지 않습니다. 필요한게 있으면 직접 GIT에서 원본 소스를 내려 받고, 친구같은 AI님께 부탁해서 수정해도 부담 없는 그런 그리드를 만들고 싶었습니다.
개인적인 욕망으로는, 처음부터 끝까지 바이브로만 작업을 하는 것이었습니다. 저도 잘 모르는 코드를 감히 빠삭하게 알고 계신 AI님께 이래라저래라 할 능력은 안되고요. 코딩은 일임하되, 코딩 앞에 있어야 하는 것들 즉 보고 옮길 수 있는 명세서를 만드는 것에, 또 명세서가 나올 수 있는 근거가 되는 요구사항에 대해 그리고 요구사항이 나올 수 있는 니즈의 수집, 니즈가 생겨난 동기 그것을 만들어 내는 것에 집중 하였습니다. 그 과정이 비었다거나, 오류를 범했을 땐 폐기하고 다시 처음부터 시작하였고 그런 것들을 룰로 만들어갔습니다. 결국 AI와 사용자 간의 합이 잘 맞을 때까지 함께 해보는 것이 중요 했습니다.
OPEN GRID의 코드에 직접적으로 손을 댄 것은 없습니다. 50대 꼰대개발자의 곤조로 클로드님과 함께 만들어갔습니다. 설계도 클로드님을 통해 하였고 다만, 나이가 있어 글자를 읽기 힘드니, PLANT UML을 사용하여, 이미지로 찍어내는 일을 시켜서 큰 그림만 확인 하였습니다. 이렇게 몇 줄 쓰고, 관람만해도 제품을 만들 수 있는 +_+;;; 이런 날이 오다니, (최근 일자리가 없어서 3개월 실업급여도 받아보았습니다.)
이미 아시겠지만 거의 모든 글은 클로드님께 게시해달라고 합니다. 오늘 만큼은 서두에 몇 줄 직접 적고 싶어서 써 넣어 봅니다. 왜냐면, 아래 이야기 기록 삼아 넣어두는 거지, 크게 분석하지는 않거든요. 다이어그램은 해석하는 사람에 따라 다르기 때문에 저는 한 줄 한 줄 남기는 것을 좋아합니다.
기능은 이제 꽤 많이 좋아 진 것 같습니다. 앞으로는 그리드 내에 표현할 수 있는 것에 집중해 보려 합니다. (편히 사용하세요. 별거 없습니다. 가지고 계신 컴퓨터로 AI에게 NPM 설치명령어 ” npm i open-grid ” 주시고 OPEN GRID 다운 받아서 예제 만들어줘 해보세요)- 이하는 클로드님이 작성하셨습니다.
클로드에게는 바이브 코딩이 어울리지 않습니다.
요즘 “바이브 코딩(vibe coding)”이라는 말이 유행합니다. 떠오르는 대로, 느낌 가는 대로 코드를 뽑아내는 방식이지요. 재미있고 빠릅니다. 그런데 우리는 이번 OPEN GRID 1.1.1을 그렇게 만들지 않았습니다. 클로드를 통해 제대로 설계하고 검증한 엔지니어링이었고, 출시까지 이룬 Vibe Shipping이었습니다.
릴리스노트 — 1.0.0에서 1.1.1까지의 여정
이번 1.1.1을 이해하려면, 왜 이런 순서로 여기까지 왔는지를 보는 편이 빠릅니다. 각 버전은 “앞 버전이 남긴 문제”를 풀려고 생겨났습니다.
v1.0.0 — 기반을 세우다
첫 번째 질문은 “그리드가 제대로 동작하는가”였습니다. 그래서 1.0.0은 그리드 코어와, 본문 소스를 한 줄도 고치지 않고 동작을 갈아끼우는 grid.override() 커스터마이징 시스템을 확립했습니다. 여기서 중요한 설계 하나가 자리 잡습니다. 커스터마이징은 “코어를 편집하는 일”이 아니라 “코어 위에 얹는 일”이어야 한다는 원칙입니다.
v1.1.0 — 업무에 필요한 4대 기능
다음 질문은 “실제 업무 그리드가 필요로 하는 것은 무엇인가”였습니다. 답으로 네 가지가 들어왔습니다.
- 범위 선택 + 채우기 — 셀을 드래그로 묶고, 값을 아래로 채웁니다(스프레드시트처럼).
- 마스터·디테일 — 한 행을 펼치면 그 안에 하위 표가 열립니다.
- 수식 셀 — 셀에
=A1+B1같은 수식을 쓰고, 참조가 바뀌면 다시 계산합니다. - 통합 차트 — 그리드 데이터를 그대로 차트로 그립니다. 대용량은 정직하게 줄여서(다운샘플) 보여줍니다.
그런데 이 네 기능을 붙이면서 앞의 God object 문제가 더 뚜렷해졌습니다. 기능이 늘수록 큰 클래스가 더 커졌으니까요. 그래서 다음 버전의 진짜 숙제가 정해졌습니다. “다음 기능이 싸게 들어오게 하려면 이 덩어리를 풀어야 한다.”
v1.1.1 (이번) — 스킨 · 아이콘 · 버튼 아이콘
1.1.1의 눈에 보이는 주인공은 외관입니다. 하지만 그 외관을 “싸고 안전하게” 넣을 수 있었던 것은 바로 위에서 말한 코어 정리 덕분입니다.
- 스킨(형태 축) 7종. 여기서 핵심은 색과 형태를 분리했다는 점입니다. 색 테마(theme)는 색만 담당하고, 스킨(skin)은 모서리·선 두께·선 모양·여백 같은 형태만 담당합니다. 두 축이 직교(독립)하므로 자유롭게 조합됩니다. 기본 스킨에 더해
sharp(각진) ·rounded(둥근) ·stitch(박음질) ·flat(평면) ·high-contrast(고대비) ·material을 제공합니다. 예를 들어 크림슨 테마 + 스티치 스킨이면 크림슨 “색”에 실땀 같은 대시(dashed) “선”이 함께 나옵니다. 예전에는 이 둘이 한 덩어리로 붙어 있어 조합이 불가능했지요. - 정직한 제외. 유행하는 뉴모피즘(neumorph)은 기본 카탈로그에서 뺐습니다. 같은 배경 위에 옅은 그림자로 구조를 표현하는 방식이라, 명암 대비(접근성) 기준과 구조적으로 충돌합니다. 멋있다고 넣지 않았습니다. 이런 판단이 우리가 말하는 “바이브가 아니다”의 한 예입니다.
- 아이콘 역할(role) 64종. Bootstrap Icons(MIT 라이선스)를 채택하되, 기능이 특정 그림을 직접 지목하지 않고 역할 이름으로 요청합니다(예: 정렬·삭제·다음). API는
renderIcon/setIcon/defineIconSet. 셀이든 버튼이든 어디서나 같은 방식으로 씁니다. - 버튼 아이콘. 버튼 렌더러에 아이콘을 얹을 수 있습니다:
renderer:{ type:'button', icon, label, iconPos }. 아이콘만, 라벨만, 혹은 둘 다 원하는 위치에 놓습니다. - 보더 토큰화. 선 모양을
--og-border-style토큰으로 승격해, 스킨이 “선”을 제어할 수 있게 했습니다. 기본값은solid라서 기존 화면은 그대로입니다. 스킨을 켜야 비로소 대시·헤어라인·굵은 선이 나타납니다.
새 커스터마이징도 같은 원칙 위에 섰습니다. setSkin / defineSkin은 형태 토큰만 받습니다. 스킨 정의에 색값을 넣으면 거부됩니다. “색은 테마, 형태는 스킨”이라는 계약을 도구가 강제합니다.
UML 설계 산책 — God object에서 조립까지
이제 우리가 코드를 만지기 전에 그린 그림들을 순서대로 걸어보겠습니다. 하나의 이야기입니다. 문제를 보고 → 관심사를 나누고 → 목표를 정하고 → 조립 방법을 정하고 → 확장·외관을 얹고 → 안전한 순서로 옮긴다.
1. 문제 제기 — 하나에 다 얽힌 덩어리
첫 그림은 고치기 전의 모습입니다. 공개 API 정면, 조립 담당, 이벤트 버스, 렌더 루프, 수식 조율, 크로스그리드까지 열 가지가 넘는 역할이 한 클래스에 모여 있습니다. 한 곳을 건드리면 다른 곳이 흔들리는 이유가 눈에 보입니다. 이 그림이 있어야 “왜 풀어야 하는가”에 모두가 동의할 수 있습니다.

2. 관심사 분리 — 어디까지가 어디의 일인가
다음은 “말이 바뀌는 선”을 따라 영역을 나눈 지도입니다. 행 모델, 화면 투영, 렌더, 선택·범위, 수식, 차트, 마스터·디테일, 외관…처럼 각자 자기 언어를 쓰는 구역(바운디드 컨텍스트)으로 경계를 그었습니다. 큰 도시를 구역으로 나눠 지도를 그리는 것과 같습니다. 경계가 있어야 다음 그림의 “협력자”들이 각자 어디에 살지 정할 수 있습니다.
3. 목표 모델 — 덩어리를 협력자들로
이 그림이 목표 상태입니다. 하나였던 큰 클래스가 얇은 정면(파사드)만 남고, 나머지 역할은 이름 붙은 협력자들에게 갑니다. 렌더는 렌더 담당에게, 데이터 변경은 변경 담당에게, 수식은 수식 담당에게. 한 사람이 하던 열 가지 일을 제대로 나눈 팀으로 바꾼 조직도라고 보면 됩니다. 각자 “바뀌는 이유가 하나뿐”이 되도록 잘랐습니다.
4. 조립 방법 — 만드는 일과 쓰는 일을 가른다
협력자를 나눴으면 “누가, 어떤 순서로 조립하는가”가 문제입니다. 예전에는 조립 순서가 주석으로만 지켜지고 있었고, 순서가 어긋나면 초기화 도중 실제로 크래시가 났습니다. 그래서 조립을 단계적 빌더(Phased Builder)로 바꿨습니다. 앞 단계 결과물이 있어야만 다음 단계 함수를 부를 수 있으니, 잘못된 순서는 아예 컴파일이 되지 않습니다. 요리에 비유하면 “재료 손질 → 볶기 → 담기”의 순서를 레시피가 강제하는 것입니다. “만드는 일(construction)”과 “쓰는 일(use)”을 이 지점에서 분리했습니다.
5. 확장점 레지스트리 — override를 정문으로
1.0.0의 override()는 강력하지만, “무엇을 바꿀 수 있는지”가 암묵적이었습니다. 그래서 커널(실행 엔진)은 한 줄도 건드리지 않고, 그 위에 타입이 붙은 확장점 카탈로그를 얹었습니다. 값·계산을 바꾸는 슬롯, 부품을 갈아끼우는 레지스트리, 수명주기 훅 — 세 범주로 정리했습니다. 이제 확장을 넓히는 일이 “코어에 게이트를 복붙”하는 게 아니라 “목록에 등록”하는 일이 됩니다. 콘센트 규격을 정해두면 새 기기를 꽂기만 하면 되는 것과 같습니다.
6. 외관 착지 — 스킨·아이콘이 앉는 자리
1.1.1의 스킨과 아이콘은 바로 이 확장점 카탈로그의 정식 시민으로 들어왔습니다. 핵심은 스타일 해결의 단일 초크포인트를 새로 판 것입니다. 예전에는 “이 선을 어떻게 그릴까”라는 결정이 렌더러 곳곳에 흩어져 있어서 스킨이 끼어들 자리가 없었습니다. 이제 렌더 층은 형태 값을 한 객체에게만 물어봅니다. 그 한 곳에서 스킨과 아이콘이 해결되고, 접근성 가드레일(포커스 링·상태 선·텍스처 금지 구역)도 그 자리에서 계약으로 강제됩니다. 스위치 하나로 온 집의 조명을 바꾸는 배전반을 만든 셈입니다.
7. 커밋 시퀀스 — 데이터가 화면이 되는 한 갈래
이 그림은 정적 구조가 아니라 움직임입니다. 데이터 변경 하나가 어떤 순서로 흘러 화면과 이벤트가 되는지를 따라갑니다. 예전에는 “값 바꾸고 → 다시 그리고 → 알림 쏘는” 꼬리가 서른 곳 가까이 복사돼 있었습니다. 이것을 단일 커밋 초크포인트 하나로 모았습니다. 입력 → 변환 → 출력이 한 깔때기를 지나가니, 순서와 배치(batch) 처리를 한 곳에서 보증합니다. 여러 지류가 하나의 강으로 모이는 그림이라고 생각하면 됩니다.
8. 리팩토링 로드맵 — 한 번에 하나씩
마지막 그림은 이 모든 것을 어떤 순서로 실제로 옮겼는가입니다. R0부터 R13까지, 각 단계는 작은 걸음이고 매 걸음마다 테스트가 초록불이어야 다음으로 갔습니다. 위험이 큰 조립 순서 봉인은 이르게, God object의 실제 추출은 안전하게 만질 수 있게 된 뒤에 — 이렇게 순서를 나눴습니다. 큰 다리를 한 번에 부수지 않고, 옆에 새 다리를 놓아가며 차량을 한 차선씩 옮기는 공사와 같습니다.
여덟 장의 그림을 한 줄로 잇는다면 이렇습니다. 얽힌 덩어리 → 구역 지도 → 협력자 팀 → 안전한 조립 → 확장의 정문 → 외관의 배전반 → 데이터의 강줄기 → 한 걸음씩의 공사. 어느 하나도 즉흥이 아니었습니다.
클로드는 손이 아닌 머리로서 역할을 하였습니다.
다시 처음으로 돌아갑니다. 우리는 이번 릴리스를 느낌으로 만들지 않았습니다. 끝장토론으로 요구를 수렴하고, UML로 목표를 먼저 그리고, 특성화 테스트로 지금 동작을 못 박고, 교살무화과 방식으로 무회귀 분해를 했습니다. 778 → 873 테스트 초록불, 회귀 0. 화려한 결과가 아니라 지루할 만큼 규율 있는 과정이었고, 그게 자랑입니다.
OPEN GRID는 MIT 라이선스입니다. 상용 프로젝트에서도 자유롭게 쓰실 수 있습니다. 설치는 다음과 같습니다.
npm install open-grid@1.1.1
빌드 없이 바로 써보려면 CDN(unpkg)에서 불러올 수도 있습니다.
<script src="https://unpkg.com/open-grid@1.1.1"></script>
새로워진 스킨과 아이콘은 데모의 스타일 & 테마 항목에서 직접 만져볼 수 있고, 개발 가이드에 스킨 정의(defineSkin)·아이콘 교체(setIcon)·버튼 아이콘 사용법을 정리해 두었습니다. 색과 형태를 따로 골라 조합해 보시길 권합니다. 우리가 왜 둘을 굳이 나눴는지, 직접 조합해 보면 손끝으로 이해되실 겁니다.