2026년 6월 21일 · 배포계획 · OPEN GRID
OPEN GRID 1.0.0에서 가장 크게 달라지는 건 딱 하나예요 — “내 마음대로 바꾸기(커스터마이징)”를 퍼스트 클래스로 만든 것. 쉽게 말하면, 예전엔 빙 둘러서 겨우 바꾸던 걸 이제는 대놓고 정식으로 바꿀 수 있게 됐다는 뜻이에요.
이 글은 세 가지를 이야기해요. (1) 바꾸는 방법이 0.4.0에서 1.0.0으로 어떻게 달라지는지, (2) 왜 바꾸는지, (3) 이 결정을 어떤 과정(STD)으로 내렸는지.
먼저, ‘오버라이드’가 뭐예요? (제일 쉽게)
‘오버라이드(override)’는 우리말로 ‘덮어쓰기’예요. OPEN GRID는 표(데이터를 줄과 칸으로 보여주는 도구)를 만들어 주는 프로그램인데, 그 안엔 이미 여러 기능이 들어 있어요 — 데이터 넣기, 정렬하기, 화면에 보여주기처럼요.
그런데 가끔 “이 기능을 내 방식으로 조금 바꾸고 싶다”는 순간이 와요. 이때 기능을 직접 뜯어고치면 위험해요(고장 나기 쉽죠). 그래서 원래 건 그대로 두고, 그 위에 내 동작을 살짝 덧씌우는 게 바로 오버라이드예요.
💡 휴대폰 케이스를 떠올리면 딱 맞아요.
- 휴대폰(= 원래 기능)은 그대로 둬요. 분해하지 않아요.
- 내 마음에 드는 케이스(= 내가 원하는 동작)를 위에 씌워요.
- 마음에 안 들면 케이스만 벗기면 원래대로 돌아와요. (코드로는
restore) - 케이스를 씌운 채로도 휴대폰 기능은 그대로 써요. (코드에선
orig, 즉 ‘원래 것’을 부르면 원래 하던 일을 그대로 해줘요.)
한마디로 — 안 망가뜨리고 · 덧씌우고 · 언제든 벗기고 · 원래 것도 그대로 쓴다. 이게 오버라이드예요.
1. 바꾸는 방법, 이렇게 달라져요 (v0.4.0 ▶ v1.0.0)
아래 그림을 누르면 크게 볼 수 있어요.
▲ 바꾸는 방법의 변화 — 그림을 누르면 크게 볼 수 있어요.
예전(0.4.0)엔 그리드한테 “하지 마”라고 막거나, 무슨 일이 일어났는지 구경만 할 수 있었어요. 새 버전(1.0.0)에선 “이건 이렇게 해줘”라고 직접 바꿔 줄 수 있어요. 코드로 보면 이런 차이예요. (코드가 어렵게 느껴지면 그냥 넘어가도 괜찮아요. 아래 글 설명만 읽어도 돼요.)
// 예전(v0.4.0) — 막거나 구경만 grid.addTrigger('before:writeCell', ctx => { if (이상하면) ctx.cancel(); }); // "하지 마" grid.on('cellClick', e => { /* 클릭됐네, 구경만 */ }); // 새 버전(v1.0.0) — 직접 바꾸기 grid.override('getDisplayValue', (orig, ri, f) => orig(ri, f).toUpperCase()); // 보여줄 때 대문자로 grid.override('undo', () => 내히스토리.undo()); // 비어있던 '되돌리기' 채워넣기 grid.restore('getDisplayValue'); // 다시 원래대로 (케이스 벗기기)
핵심만 다시 쉽게 정리하면:
- 바꾸는 방법은 두 가지 — ① 기능 하나를 통째로 감싸기(
grid.override(이름, 함수)), ② ‘정렬하는 방식’처럼 속에 든 계산법만 쏙 바꿔 끼우기(grid.override.strategy(슬롯, 함수)). - 원래 것도 그대로 — 내가 만든 함수의 첫 자리(
orig)가 ‘원래 기능’이에요. 부르면 원래대로, 안 부르면 완전히 새 동작으로. - 안전장치는 기본 내장 — 여러 개 씌워도 차곡차곡 순서대로 쌓이고, 빙글빙글 무한반복에 안 빠지게 막아주고, 표를 닫으면 씌운 걸 알아서 모두 벗겨요.
2. 왜 바꾸나요? (변경 이유)
예전(0.4.0)에 그리드 동작을 바꾸는 방법은 사실 세 가지뿐이었어요.
- ① 처음 만들 때 옵션으로 정해두기 — 만든 뒤엔 못 바꿔요.
- ② 이벤트 — 무슨 일이 일어났는지 ‘구경’만 해요.
- ③ 트리거 — 정해진 9가지 작업에 한해서 ‘하지 마’라고 막기만 해요.
셋 다 옆에서 지켜보거나 막는 도구일 뿐이었어요. 그리드가 실제로 무엇을 보여주고 어떻게 계산하는지는 손댈 수 없었죠.
그래서 이런 걸 하고 싶을 때 자주 막혔어요 — “숫자를 내가 원하는 모양으로 보여주기”, “한글 이름을 가나다순으로 제대로 정렬하기”, “검색을 더 똑똑하게 바꾸기”, “엑셀로 내보낼 때 모양 바꾸기”, “되돌리기(undo) 기능 직접 넣기”. 0.4.0에선 이걸 하려면 “프로그램 전체를 복사해서 통째로 뜯어고쳐라”는 답뿐이었어요. 너무 번거롭죠.
▲ override를 넣기 전과 후 — ‘막고 구경하기’에서 ‘직접 바꾸기’로. 그림을 누르면 크게 볼 수 있어요.
grid.override()는 바로 이 답답함을 풀어줘요. 그러면서도 두 가지 약속을 지켜요. 첫째, 원래 코드는 한 줄도 안 고쳐요(위에 덧씌우기만 해요). 둘째, 기존 도구(이벤트·트리거)와 역할이 안 겹치게 나눠서 사이좋게 같이 써요.
솔직하게 하나 덧붙이면 — 속 계산법을 바꾸는 ‘strategy’는 100% 그냥은 안 되고, 도구 안쪽에 아주 작은 연결고리(딱 한 줄)를 미리 심어둬야 작동해요. 그래서 우리는 ‘아무것도 안 고쳐도 되는 것(✅)‘과 ‘딱 한 줄만 미리 심는 것(🔧)‘을 솔직하게 구분해서 표시했어요. “다 그냥 된다”고 속이지 않으려고요.
3. 무엇을 바꿀 수 있나요? (요약)
- 가장 많이 원했던 것(검토자 11명 모두 똑같이 꼽음): 화면에 보여주는 값, 값을 고칠 때의 검사, 데이터 통째로 넣기.
- 속 계산법 바꿔 끼우기: 정렬 방법, 검색(필터) 방법, 숫자 표시 방법, 엑셀 내보내기 방법 등.
- 비어 있던 기능 채워 넣기: 되돌리기(undo)·다시하기(redo)처럼 자리만 있고 아직 안 만든 기능 12개.
- 가장 먼저 내놓을 것(약 20개)은 “원래 코드를 안 고쳐도 되고 + 위험이 낮은” 것들로 골랐어요.
4. 배포 계획
- 버전: 1.0.0 — 기능을 더하기만 해요. 기존에 쓰던 게 깨지지 않아요(호환성 유지).
- 순서: 1단계(가장 안전한 ‘덧씌우기’부터) → 2단계(작은 연결고리 심기) → 3단계(React·Vue·jQuery·Angular 같은 프레임워크 연결) → 4단계(비어 있던 기능 채우기).
부록. 이 결정은 어떻게 내렸나 — 의사결정 상태전이도(STD)
(여기부터는 개발자·실무자를 위한 심화 내용이에요. 핵심은 위 본문에 다 있으니, 더 깊이 보고 싶은 분만 읽으셔도 돼요.)
아래 그림이 이번 결정의 상태전이도(STD, State Transition Diagram)예요. 의사결정 과정의 5단계를 ‘상태’로, 통과해야 다음으로 넘어가는 조건을 ‘게이트 [ ]’로, 검증에서 문제가 나오면 되돌아가는 흐름을 피드백 화살표(↺)로 그렸습니다. 한 사람의 직관이 아니라 다관점 패널 협의 → 정량 제안 수집 → 통합·등급화 → 적대적 검증 → 종합·확정의 절차를 따랐어요.
▲ 의사결정 과정 상태전이도(STD) — 5단계 · 게이트 · 검증 피드백 루프. 클릭하면 확대됩니다.
1) 의사결정 프로세스 (5단계 · 각 단계 = 입력 / 활동 / 산출 / 게이트)
- 다관점 패널 협의
입력: 기능 브리핑(진실 기준 문서)·실제 소스 코드. 활동: 6개 코어 도메인 관점(메커니즘·아키텍처, 렌더링·표시, 데이터·정렬·필터, 내보내기·직렬화, 에디터, 상호운용) + 5개 프레임워크 관점(React·Vue·jQuery·Angular·Vanilla)이 각자 독립적으로 확장 지점 제안. 산출: 관점별 제안 묶음(11개 패널). 게이트: 코어·프레임워크 관점이 모두 참여했는가, 각 패널이 브리핑·실소스를 근거로 삼았는가. - 정량 제안 수집
입력: 11개 패널의 제안. 활동: 패널당 약 300건 규모로 (대상지점 + override 종류 + 시그니처)를 행 단위로 구조화. 산출: 원시 제안 총 3,320행. 게이트: 추상 의견이 아니라 표로 정리 가능한 정량 형태인가. - QA 통합·중복제거·등급화
입력: 원시 3,320행. 활동: (대상지점 + 종류) 기준 중복 제거, 본문 무수정(C1) 준수 여부와 기술적 타당성 검증, 가치/위험/합의도로 등급화. 산출: 고유 243건(메서드 래핑 168 / 알고리즘 슬롯 61 / 스텁 14), Tier P0 34 · P1 96 · P2 113. 게이트: 모든 항목이 합의도·Tier·C1 검증 라벨을 갖는가. - 적대적 검증(크리틱)
입력: 통합 243항목 + 메커니즘 설계. 활동: “기본 의심” 입장에서 오라벨·누락(은폐)·Tier 과대평가·메커니즘 결함·사실오류를 적출. 산출: 판정 GO-WITH-FIXES + 필수 수정 4건(머지 차단 조건). 게이트: 통합본이 적대적 공격을 견뎠는가. 필수 수정 반영 전엔 “확정” 진행 불가. - 종합·확정
입력: 통합본 + 메커니즘 + 구현계획 + 크리틱 판정. 활동: 필수 수정 4건을 모두 반영해 권위 최종본 작성, 확정 API·안전 규칙·버전 확정. 산출: 최종 종합본·확정 API·단계적 출시 계획. 게이트: 4개 수정이 전부 반영되고 출시 단위(additive·no breaking change)가 명시되었는가.
2) 핵심 의사결정 기록 (ADR · 12건)
| # | 결정사항 | 결론 (근거·합의도) |
|---|---|---|
| 1 | 확장 API 구조 | 이중 API — 공개 메서드 래핑 override(name, fn) + 내부 알고리즘 슬롯 override.strategy(slot, fn) |
| 2 | 함수 시그니처 | (orig, ...args) => result — 11/11 패널 만장일치. orig는 super처럼 항상 호출 가능 |
| 3 | override 종류 표현 | 별도 enum 없음 — orig를 호출하는지/언제 호출하는지로 전처리·후처리·완전교체를 자연 표현 |
| 4 | 다중 override 합성 순서 | FIFO(등록순) — 먼저 등록=안쪽, 나중=바깥. 구현은 reduce 좌측 폴드(크리틱 F2 반영) |
| 5 | 적용 범위 | per-instance 기본 + 정적 전역 옵트인(OpenGrid.defaults). 인스턴스가 전역을 가림(shadowing) |
| 6 | 재진입 안전 | same-name 차단 폐기 → 깊이 제한 + 호출경로 사이클 감지 + reentrant 옵트인(크리틱 F3) |
| 7 | 에러 처리 기본값 | strict(예외 전파) 기본. 폴백은 멱등 보장 시에만, 롤백 불가 명문화(크리틱 F4) |
| 8 | 트리거/이벤트와의 관계 | 역할 분리 — 취소·관찰(트리거) vs 읽기(이벤트) vs 반환·알고리즘 교체(override). orig 호출 시 기존 트리거 자동 발동 |
| 9 | C1 라벨링 | ✅ 순수 래핑(소스 0줄) / 🔧 슬롯(매니저 본문 1줄 훅포인트 선행) 이원화(크리틱 F1) |
| 10 | P0 Tier 재조정 | P0 34 → ~20으로 재정의. 위험 높은 스텁·🔧 슬롯은 P1로 강등(가치는 유지) |
| 11 | 정적 기본값 적용 시점 | 생성자 말미 1회 적용으로 고정 → 첫 렌더 깜빡임 방지 |
| 12 | destroy 누수 방지 | 커널이 생성 시점에 destroy의 최외곽 래퍼로 자기등록 → 원복·정리 보장 |
3) 제약 원칙 (C1~C4)
- C1 — 본문 무수정(런타임 래핑): 현재 메서드 본문을 수정하지 않는다. 단 검증으로 이원화 — 순수 래핑은 ✅(소스 0줄), 알고리즘 슬롯은 🔧(매니저 1줄 선행 필요).
- C2 — 타입 안전·역할 명확: 메서드별 시그니처를 제네릭 맵으로 강제(
override<K extends keyof …>), 트리거/이벤트와 역할 중복 없음. - C3 — 원본 호출(super-like):
orig은 항상this에 바운드된 원본 메서드.(orig, ...args) => orig(...args)가 안전 동작. - C4 — 런타임 일관성·정리 안전: 재진입/무한루프 방지, 데이터 변경 메서드 교체 시 화면 동기화 가드, destroy 시 자동 원복으로 리스너·옵저버 누수 차단.
4) 품질 게이트 — 출시 전 필수 수정 4건 (모두 반영)
- F1. C1 라벨 정합 — strategy 슬롯의 ✅를 🔧로 재표기(“런타임만으로 가능”이라는 거짓 안심 제거).
- F2. 합성 정합 —
reduceRight(방향 반대 버그) →reduce. 레이어 순서 회귀 테스트. - F3. 재진입 가드 재설계 — same-name 차단 폐기 → 깊이제한 + 사이클 감지 + 옵트인.
- F4. 에러격리 — “경고 후 재실행” 기본 폐기 → strict(예외 전파) 기본.
추가 출시 기준 — 버전은 additive(호환성 깨짐 없음), 단계적 출시(Phase 1~4), 미검증 주장은 “추정”으로 명시, pushData 등이 setData를 경유하지 않는 함정 명문화.
5) 재사용 가능한 표준으로
이 STD의 핵심은 “제안의 양 → 통합의 질 → 적대적 검증 → 반영 확정”이라는 흐름과, 각 단계 사이에 명시적 게이트를 두어 검증 없이 다음으로 넘어가지 못하게 한 점입니다. 다른 기능을 설계할 때도 똑같이 적용할 수 있어요 — (1) 관점이 충분히 다양한가, (2) 제안이 정량화되어 중복 제거가 가능한가, (3) 모든 항목에 합의도·우선순위·제약 라벨이 붙었는가, (4) 작성과 검증이 분리되었고 적대적 검증을 통과했는가, (5) 필수 수정이 전부 반영된 권위 최종본이 있는가.
가장 중요한 차별점은 — 통합 결과를 그대로 신뢰하지 않고, “기본 의심” 입장의 적대적 검증을 별도 패스로 거친다는 점입니다. 작성(통합·설계)과 검증(크리틱)을 분리해 자기 승인을 막고, 검증에서 나온 필수 수정은 머지 차단 조건으로 다뤄 반영 전에는 “확정”을 선언하지 않습니다.
OPEN GRID는 누구나 무료로 쓸 수 있는 오픈소스(MIT)예요. · 라이브 데모 보러가기