-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 숫자를 한글로 바꾸는 함수 추가 #254
Changes from all commits
e5986c0
28516a4
1a6b168
a9d3a27
7b45ebe
1b279ef
24a43d3
56f7659
0e9d916
665c3d2
b7cd571
b048189
9654c8f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"es-hangul": minor | ||
--- | ||
|
||
feat: 숫자를 한글로 바꾸는 함수 추가 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
title: numberToHangul | ||
--- | ||
|
||
import { Sandpack } from '@/components/Sandpack'; | ||
|
||
# numberToHangul | ||
|
||
Converts the given number into a Korean numeral expression using Sino-Korean numbers. | ||
It supports spacing for “man(萬)” units to accommodate various requirements. | ||
|
||
```typescript | ||
function numberToHangul(input: number, options?: { spacing?: boolean }): string; | ||
``` | ||
|
||
## Examples | ||
|
||
```tsx | ||
numberToHangul(210_000); // '이십일만'; | ||
numberToHangul(12_345); // '일만이천삼백사십오'; | ||
numberToHangul(123_456_780); // '일억이천삼백사십오만육천칠백팔십'; | ||
numberToHangul(123_456_780, { spacing: true }); // '일억 이천삼백사십오만 육천칠백팔십'; | ||
``` | ||
|
||
## 사용해보기 | ||
|
||
<br /> | ||
|
||
<Sandpack> | ||
|
||
```ts index.ts | ||
import { numberToHangul } from 'es-hangul'; | ||
|
||
console.log(numberToHangul(123_456_780)); | ||
console.log(numberToHangul(123_456_780, { spacing: true })); | ||
``` | ||
|
||
</Sandpack> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
title: numberToHangul | ||
--- | ||
|
||
import { Sandpack } from '@/components/Sandpack'; | ||
|
||
# numberToHangul | ||
|
||
주어진 숫자를 한자어 수사로 바꿔줍니다. | ||
다양한 요구사항에 대응하도록 '만(萬)' 단위로 띄어쓰기를 지원합니다. | ||
|
||
```typescript | ||
function numberToHangul(input: number, options?: { spacing?: boolean }): string; | ||
``` | ||
|
||
## Examples | ||
|
||
```tsx | ||
numberToHangul(210_000); // '이십일만'; | ||
numberToHangul(12_345); // '일만이천삼백사십오'; | ||
numberToHangul(123_456_780); // '일억이천삼백사십오만육천칠백팔십'; | ||
numberToHangul(123_456_780, { spacing: true }); // '일억 이천삼백사십오만 육천칠백팔십'; | ||
``` | ||
|
||
## 사용해보기 | ||
|
||
<br /> | ||
|
||
<Sandpack> | ||
|
||
```ts index.ts | ||
import { numberToHangul } from 'es-hangul'; | ||
|
||
console.log(numberToHangul(123_456_780)); | ||
console.log(numberToHangul(123_456_780, { spacing: true })); | ||
``` | ||
|
||
</Sandpack> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
title: numberToHangulMixed | ||
--- | ||
|
||
import { Sandpack } from '@/components/Sandpack'; | ||
|
||
# numberToHangulMixed | ||
|
||
Attaches the Korean number units that change every 4 digits to the given number. | ||
It supports spacing for “man(萬)” units to accommodate various requirements. | ||
|
||
```typescript | ||
function numberToHangulMixed(input: number, options?: { spacing?: boolean }): string; | ||
``` | ||
|
||
## Examples | ||
|
||
```tsx | ||
numberToHangulMixed(210_000); // '21만'; | ||
numberToHangulMixed(12_345); // '1만2,345'; | ||
numberToHangulMixed(123_456_780); // '1억2,345만6,780'; | ||
numberToHangulMixed(123_456_780, { spacing: true }); // '1억 2,345만 6,780'; | ||
``` | ||
|
||
## 사용해보기 | ||
|
||
<br /> | ||
|
||
<Sandpack> | ||
|
||
```ts index.ts | ||
import { numberToHangulMixed } from 'es-hangul'; | ||
|
||
console.log(numberToHangulMixed(1_2345_6780)); | ||
console.log(numberToHangulMixed(1_2345_6780, { spacing: true })); | ||
``` | ||
|
||
</Sandpack> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
title: numberToHangulMixed | ||
--- | ||
|
||
import { Sandpack } from '@/components/Sandpack'; | ||
|
||
# numberToHangulMixed | ||
|
||
주어진 숫자에 **4자리 마다 바뀌는 한글의 숫자 단위**를 붙여줍니다. | ||
다양한 요구사항에 대응하도록 '만(萬)' 단위로 띄어쓰기를 지원합니다. | ||
|
||
```typescript | ||
function numberToHangulMixed(input: number, options?: { spacing?: boolean }): string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 함수명의 맥락을 고려할 때, numberToHangulMixed는 “숫자를 한글로 변환하고, 그 결과가 섞인 형태로 나타난다”는 순서와 흐름을 더 잘 설명하는 반면, numberToMixedHangul은 “숫자와 한글이 섞인 형태로 변환한다”는 점을 먼저 강조하고 �있는 것 같은데요. 고민을 해봤는데, 숫자를 한글로 변환하는게 메인 기능이므로 진행해주신 numberToHangulMixed 가 더 적절해보이네요 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네 저도 함수명에 고민이 많았는데 공감대가 형성되어 기쁘네요! 이외의 명명 기준은 다음과 같습니다.
|
||
``` | ||
|
||
## Examples | ||
|
||
```tsx | ||
numberToHangulMixed(210_000); // '21만'; | ||
numberToHangulMixed(12_345); // '1만2,345'; | ||
numberToHangulMixed(123_456_780); // '1억2,345만6,780'; | ||
numberToHangulMixed(123_456_780, { spacing: true }); // '1억 2,345만 6,780'; | ||
``` | ||
|
||
## 사용해보기 | ||
|
||
<br /> | ||
|
||
<Sandpack> | ||
|
||
```ts index.ts | ||
import { numberToHangulMixed } from 'es-hangul'; | ||
|
||
console.log(numberToHangulMixed(123_456_780)); | ||
console.log(numberToHangulMixed(123_456_780, { spacing: true })); | ||
``` | ||
|
||
</Sandpack> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,14 @@ | ||
export const HANGUL_DIGITS = [ | ||
'', | ||
'만', | ||
'억', | ||
'조', | ||
'경', | ||
'해', | ||
'자', | ||
'양', | ||
'구', | ||
'간', | ||
'정', | ||
'재', | ||
'극', | ||
'항하사', | ||
'아승기', | ||
'나유타', | ||
'불가사의', | ||
'무량대수', | ||
'겁', | ||
'업', | ||
]; | ||
export const HANGUL_DIGITS_MAX = HANGUL_DIGITS.length * 4; | ||
export const HANGUL_NUMBERS = ['', '일', '이', '삼', '사', '오', '육', '칠', '팔', '구']; | ||
export const HANGUL_NUMBERS_FOR_DECIMAL = ['영', '일', '이', '삼', '사', '오', '육', '칠', '팔', '구']; | ||
export const HANGUL_CARDINAL = ['', '십', '백', '천']; | ||
|
||
import { | ||
HANGUL_DIGITS_MAX, | ||
HANGUL_NUMBERS_FOR_DECIMAL, | ||
HANGUL_NUMBERS, | ||
HANGUL_DIGITS, | ||
HANGUL_CARDINAL, | ||
} from '@/_internal/constants'; | ||
|
||
/** | ||
* @deprecated 더 유연하게 사용 가능한 `numberToHangul`을 이용해 주세요 | ||
*/ | ||
export function amountToHangul(amount: string | number) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. amountToHangul은 다음 메이저 버전 업데이트 때 제거 될 것 같은데, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네 저도 이 부분 함께 논의해보고 싶었습니다. docs: deprecated amountToHangul에 반영했어요! |
||
const [rawIntegerPart, rawDecimalPart] = String(amount) | ||
.replace(/[^\d.]+/g, '') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './numberToHangul'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { numberToHangul } from './numberToHangul'; | ||
|
||
describe('numberToHangul', () => { | ||
test('기본 변환', () => { | ||
expect(numberToHangul(210_000)).toBe('이십일만'); | ||
expect(numberToHangul(12_345)).toBe('일만이천삼백사십오'); | ||
expect(numberToHangul(123_456_780)).toBe('일억이천삼백사십오만육천칠백팔십'); | ||
}); | ||
|
||
test('공백 포함 변환', () => { | ||
expect(numberToHangul(210_000, { spacing: true })).toBe('이십일만'); | ||
expect(numberToHangul(12_345, { spacing: true })).toBe('일만 이천삼백사십오'); | ||
expect(numberToHangul(123_456_780, { spacing: true })).toBe('일억 이천삼백사십오만 육천칠백팔십'); | ||
}); | ||
|
||
test('0과 10,000보다 작은 경우', () => { | ||
expect(numberToHangul(0)).toBe('영'); | ||
expect(numberToHangul(1)).toBe('일'); | ||
expect(numberToHangul(2)).toBe('이'); | ||
expect(numberToHangul(3)).toBe('삼'); | ||
expect(numberToHangul(4)).toBe('사'); | ||
expect(numberToHangul(5)).toBe('오'); | ||
expect(numberToHangul(6)).toBe('육'); | ||
expect(numberToHangul(7)).toBe('칠'); | ||
expect(numberToHangul(8)).toBe('팔'); | ||
expect(numberToHangul(9)).toBe('구'); | ||
expect(numberToHangul(10)).toBe('십'); | ||
expect(numberToHangul(11)).toBe('십일'); | ||
expect(numberToHangul(20)).toBe('이십'); | ||
expect(numberToHangul(30)).toBe('삼십'); | ||
expect(numberToHangul(100)).toBe('백'); | ||
expect(numberToHangul(101)).toBe('백일'); | ||
expect(numberToHangul(110)).toBe('백십'); | ||
expect(numberToHangul(200)).toBe('이백'); | ||
expect(numberToHangul(300)).toBe('삼백'); | ||
expect(numberToHangul(1_000)).toBe('천'); | ||
expect(numberToHangul(1_001)).toBe('천일'); | ||
expect(numberToHangul(1_100)).toBe('천백'); | ||
expect(numberToHangul(1_200)).toBe('천이백'); | ||
expect(numberToHangul(1_234)).toBe('천이백삼십사'); | ||
expect(numberToHangul(9_999)).toBe('구천구백구십구'); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { HANGUL_CARDINAL, HANGUL_DIGITS, HANGUL_NUMBERS } from '@/_internal/constants'; | ||
|
||
export function numberToHangul(input: number, options?: { spacing?: boolean }): string { | ||
if (input === 0) { | ||
return '영'; | ||
} | ||
|
||
const koreanParts: string[] = []; | ||
let remainingDigits = input.toString(); | ||
let placeIndex = 0; | ||
|
||
while (remainingDigits.length > 0) { | ||
const currentPart = remainingDigits.slice(-4); | ||
|
||
koreanParts.unshift(`${numberToKoreanUpToThousand(Number(currentPart))}${HANGUL_DIGITS[placeIndex]}`); | ||
|
||
remainingDigits = remainingDigits.slice(0, -4); | ||
placeIndex++; | ||
} | ||
|
||
if (options?.spacing) { | ||
return koreanParts | ||
.filter(part => part !== '') | ||
.join(' ') | ||
.trim(); | ||
} | ||
|
||
return koreanParts.join(''); | ||
} | ||
|
||
function numberToKoreanUpToThousand(num: number): string { | ||
if (num < 0 || num > 9999) { | ||
throw new Error('0 이상 9999 이하의 숫자만 입력 가능합니다.'); | ||
} | ||
|
||
const koreanDigits = num | ||
.toString() | ||
.split('') | ||
.reverse() | ||
.map((digit, index) => (digit === '0' ? '' : HANGUL_NUMBERS[Number(digit)] + HANGUL_CARDINAL[index])) | ||
.reverse() | ||
.join(''); | ||
|
||
return koreanDigits.replace(/일천/, '천').replace(/일백/, '백').replace(/일십/, '십') || ''; | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './numberToHangulMixed'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { numberToHangulMixed } from './numberToHangulMixed'; | ||
|
||
describe('numberToHangulMixed', () => { | ||
test('기본 변환', () => { | ||
expect(numberToHangulMixed(210_000)).toBe('21만'); | ||
expect(numberToHangulMixed(12_345)).toBe('1만2,345'); | ||
expect(numberToHangulMixed(123_456_780)).toBe('1억2,345만6,780'); | ||
}); | ||
|
||
test('공백 포함 변환', () => { | ||
expect(numberToHangulMixed(210_000, { spacing: true })).toBe('21만'); | ||
expect(numberToHangulMixed(12_345, { spacing: true })).toBe('1만 2,345'); | ||
expect(numberToHangulMixed(123_456_780, { spacing: true })).toBe('1억 2,345만 6,780'); | ||
}); | ||
|
||
test('0과 10,000보다 작은 경우', () => { | ||
expect(numberToHangulMixed(0)).toBe('0'); | ||
expect(numberToHangulMixed(1)).toBe('1'); | ||
expect(numberToHangulMixed(2)).toBe('2'); | ||
expect(numberToHangulMixed(3)).toBe('3'); | ||
expect(numberToHangulMixed(4)).toBe('4'); | ||
expect(numberToHangulMixed(5)).toBe('5'); | ||
expect(numberToHangulMixed(6)).toBe('6'); | ||
expect(numberToHangulMixed(7)).toBe('7'); | ||
expect(numberToHangulMixed(8)).toBe('8'); | ||
expect(numberToHangulMixed(9)).toBe('9'); | ||
expect(numberToHangulMixed(10)).toBe('10'); | ||
expect(numberToHangulMixed(11)).toBe('11'); | ||
expect(numberToHangulMixed(20)).toBe('20'); | ||
expect(numberToHangulMixed(30)).toBe('30'); | ||
expect(numberToHangulMixed(100)).toBe('100'); | ||
expect(numberToHangulMixed(101)).toBe('101'); | ||
expect(numberToHangulMixed(110)).toBe('110'); | ||
expect(numberToHangulMixed(200)).toBe('200'); | ||
expect(numberToHangulMixed(300)).toBe('300'); | ||
expect(numberToHangulMixed(1_000)).toBe('1,000'); | ||
expect(numberToHangulMixed(1_001)).toBe('1,001'); | ||
expect(numberToHangulMixed(1_100)).toBe('1,100'); | ||
expect(numberToHangulMixed(1_200)).toBe('1,200'); | ||
expect(numberToHangulMixed(1_234)).toBe('1,234'); | ||
expect(numberToHangulMixed(9_999)).toBe('9,999'); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
input에 '133314' 처럼 string이 들어오지 않기로 하신 이유가 있나요? 저도 number만 받는게 좋을 것 같다고 생각해요!
숫자를 한글 단위로 변환
하는 것이 핵심이라서, 단일 책임만 가졌으면 하기 때문입니다There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 저도 동일한 의견입니다.
es-hangul
에서 제공하는 api들은 최소한의 기능과 책임을 가졌으면 좋겠어요.numberToHangul
의 경우에도string
이 들어가면서 복잡해지는 것보다는numberToHangul
을 사용하는 곳에서 형변환해서 넣어주는 것이 어렵지도 않고 함수가 가벼워질 것이라고 생각했습니다.앞으로도 api를 제공할 때 사용하는 곳에서 유용하게 사용할 수 있는가? 도 함수의 책임과 함께 고민되면 좋을 것 같습니다!