k-skill/docs/features/korean-character-count.md
Jeffrey (Dongkyu) Kim 1180f41b82 Keep published Korean count examples aligned with the shipped helper
The korean-character-count feature guide drifted from the verified NEIS helper output, so this follow-up adds a docs regression that executes the live command and corrects the stale byte example in the feature doc.

Constraint: The skill promises deterministic exact counts in both docs and CLI output
Rejected: Hardcode a separate doc-only expected value in tests | would still allow the published example to drift from the helper
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When docs publish exact count values, keep them pinned to live helper output rather than a copied constant
Tested: node --test scripts/skill-docs.test.js scripts/test_korean_character_count.js
Tested: node scripts/korean_character_count.js --text '가나다' --format json
Tested: node scripts/korean_character_count.js --file <tmpfile> --profile neis --format text
Tested: printf '한\r\n나' | node scripts/korean_character_count.js --stdin --format json
Tested: npm test
Tested: npm run ci
Not-tested: none
2026-04-08 23:57:31 +09:00

3.7 KiB

한국어 글자 수 세기 가이드

이 기능으로 할 수 있는 일

  • 한국어 텍스트의 글자 수를 Intl.Segmenter 기반 grapheme contract로 계산
  • 줄 수를 CRLF/LF/CR/U+2028/U+2029 기준으로 계산
  • UTF-8 byte 수를 실제 인코딩 길이로 계산
  • neis 호환 byte 프로필로 다시 계산
  • 텍스트 직접 입력, 파일 입력, stdin 파이프 입력 처리

왜 별도 스킬이 필요한가

  • 자기소개서/지원서 폼은 1자 차이도 민감하다.
  • LLM이 글자 수를 대충 추정하면 같은 입력에서 결과가 흔들릴 수 있다.
  • 이 저장소의 목적은 계산 계약을 고정한 helper 를 제공하는 것이다.

기본 계약

default profile

  • characters: Intl.Segmenter 기반 Unicode extended grapheme clusters
  • bytes: Buffer.byteLength(text, "utf8")
  • lines:
    • 빈 문자열은 0
    • 비어 있지 않으면 줄바꿈 시퀀스 수 + 1
    • CRLF 는 줄바꿈 1회

이 계약은 입력을 임의로 trim 하거나 정규화하지 않는다. 공백, 개행, emoji, 조합형 자모도 원문 그대로 센다.

neis profile

  • characters: default 와 동일
  • lines: default 와 동일
  • bytes:
    • 한글 grapheme 3B
    • ASCII grapheme 1B
    • Enter/줄바꿈 시퀀스 2B
    • 나머지는 UTF-8 byte fallback

neisbyte 계산만 한국 교육행정 호환 규칙으로 바꾼 compatibility profile이다.

CLI 사용 예시

기본 JSON 출력

node scripts/korean_character_count.js --text "가나다"

예상 출력:

{
  "profile": "default",
  "contract": {
    "characters": "Unicode extended grapheme clusters via Intl.Segmenter",
    "bytes": "Actual UTF-8 encoded byte length",
    "lines": "Empty string => 0 lines; otherwise count CRLF, LF, CR, U+2028, U+2029 as one line break each and add 1"
  },
  "counts": {
    "characters": 3,
    "characters_without_whitespace": 3,
    "code_points": 3,
    "utf16_code_units": 3,
    "lines": 1,
    "bytes": 9,
    "bytes_utf8": 9,
    "bytes_neis": 9
  }
}

줄바꿈 + 호환 byte 프로필

node scripts/korean_character_count.js --text $'첫 줄\n둘째 줄🙂' --profile neis --format text

예상 출력:

profile: neis
characters: 9
lines: 2
bytes: 23

파일 입력

node scripts/korean_character_count.js --file ./essay.txt

stdin 입력

cat essay.txt | node scripts/korean_character_count.js --profile neis

구현 메모

  • Intl.SegmenterCRLF 를 grapheme cluster 하나로 다뤄 Windows 줄바꿈에서도 과한 이중 카운트를 피한다.
  • UTF-8 byte 수는 문자 종류를 암산하지 않고 실제 인코딩 길이를 쓴다.
  • neis 는 byte 규칙만 바꾸는 compatibility layer라서, characters/lines 계약은 기본값과 동일하다.
  • 제출처가 별도 계약을 문서로 명시하지 않으면 default 를 기본값으로 쓴다.

라이브 검증 메모

2026-04-08 기준으로 아래 로컬 smoke run을 확인했다.

  • node scripts/korean_character_count.js --text "가\r\n나"characters=3, lines=2, bytes=8을 반환한다.
  • node scripts/korean_character_count.js --text $'첫 줄\n둘째 줄🙂' --profile neis --format textbytes=23을 반환한다.
  • cat essay.txt | node scripts/korean_character_count.js 경로도 JSON 출력이 동작한다.

참고 표면