Skip to content
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

[Feature]: latin1 인코딩의 옛한글을 핸들링할 수 있는 기능이 있으면 좋을 것 같습니다. #252

Open
hsh2001 opened this issue Sep 18, 2024 · 9 comments · May be fixed by #310
Assignees

Comments

@hsh2001
Copy link

hsh2001 commented Sep 18, 2024

Description

NestJS를 통해 파일을 업로드하는 기능을 제작중에 있는데, 파일의 이름이 latin1로 인코딩 되는 많은 OS 에서는 옛한글로 저장되기에 자소분리가 되는 경우가 잦습니다. 맥의 파일을 윈도우로 전달했더니 자소가 분리되는 경험을 하신 분들이 많은 것으로 알고 있는데, 옛한글 인코딩으로 저장된 한글을 현대 UTF8 인코딩으로 잘 해석하는 기능이 있으면 좋을 것 같아요.

https://ko.wikipedia.org/wiki/%EC%98%9B%ED%95%9C%EA%B8%80

Possible Solution

No response

etc.

No response

@hsh2001
Copy link
Author

hsh2001 commented Oct 7, 2024

괜찮다면 저를 담당자로 지정해주셔서 제가 이 기능을 개발해봐도 될까요? @okinawaa

@okinawaa
Copy link
Member

okinawaa commented Oct 7, 2024

@hsh2001 네 너무 좋아요!
세세한 구현은 언제든 바뀔 수 있으니, 생각하시는 인터페이스 정도 공유해주시면 좋을 것 같아요 !!

@hsh2001
Copy link
Author

hsh2001 commented Oct 24, 2024

생각해보니 옛한글에서는 존재했지만 이제는 사라진 많은 자음과 모음이 조합된 글자는 현대 한글로 변환할 수가 없네요.. 또, 옛한글을 현대한글로 변환할 수 있는 사례(예를 들면 아래아를 ㅏ로 변환)가 몇몇 있다보니 조사가 방대하게 필요할 것 같습니다...

일단은 다음과 같은 인터페이스를 제안드릴 수 있을 것 같아요! (네이밍은 일단 보류..)

// 입력으로 받은 문제열에 옛한글이 포함되어 있는가?
include옛한글(str: string): boolean;

// 옛한글이 포함된 문자열이라면, 포함된 모든 문자열이 현대한글로 변환될 수 있는가?
canBeReplace엣한글to현대한글(str: string): boolean;

// 대체할 수 없는 옛한글을 현대 한글로 변환하려 할 때 내는 에러
class Irreplaceable옛한글Error extends Error;

// 옛한글을 현대한글로 변환
// @throws Irreplaceable옛한글Error
replace옛한글to현대한글(str: string): string;

(사실 요즘 옛한글을 실질적으로 사용하는 사례는 적고, 말씀드린 파일 이름과 같은 예시가 대부분이긴 합니다..)

@hsh2001
Copy link
Author

hsh2001 commented Jan 2, 2025

@okinawaa 제가 조금 조사를 해보았는데요!

https://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EB%93%B1%EA%B0%80%EC%84%B1

https://www.unicode.org/charts/PDF/U1100.pdf

이슈에서 말한 파일이름이 바뀌는 현상은 OS에서 한글을 저장할 때 NFD로 저장되어 있냐 NFC로 저장되어 있냐가 문제인 것 같습니다. latin1 은 범인이 아니었네요..!

/**
 * str 에 NFD(조합형) 한글이 포함되어 있는가?
 */
function includeNFDHangul(str: string): boolean;


/**
 * str 에 현대에는 사용하지 않는 한글이 포함되어 있는가?
 */
function includeOldHangul(str: string): boolean;

class IrreplaceableOldHangulError extends Error;

/**
 * NFD 한글을 NFC 한글로 변환한다.
 *
 * @throws {IrreplaceableOldHangulError} 현대에는 사용하지 않는 한글이 포함되어 있는 경우.
 */
export function replaceNFDHangulToNFCHangul(str: string): string

이렇게 변경할 수 있을 것 같습니다! 간단하게 코드도 작성해봤는데, 인터페이스가 괜찮은 것 같다고 생각하신다면 레포지토리 포크 따서 PR 작성해보겠습니다 :)

https://github.com/hsh2001/yethangul/blob/main/src/index.ts

@hsh2001
Copy link
Author

hsh2001 commented Jan 2, 2025

네이밍 컨벤션에 굳이 필요한 경우가 아니라면 Hangul 을 이름에 포함하지 않는다고 하였지만, NFD와 NFC는 한글만을 위한 기술이 아니기 때문에, "NFD로 정규화되어 있으면서 한글인 문자열을 다룬다"가 중요한 포인트 같아서 포함되는 편이 좋을 것 같아요!

@hsh2001
Copy link
Author

hsh2001 commented Jan 2, 2025

만약 이 인터페이스가 괜찮으시다면, 문서화할 때 IrreplaceableOldHangulError 를 별도의 페이지로 분리해야할까요 아니면 replaceNFDHangulToNFCHangul 와 같은 문서에 위치해야 할까요?

@po4tion
Copy link
Collaborator

po4tion commented Jan 3, 2025

@hsh2001 님 안녕하세요! 좋은 작업 해주셔서 정말 감사드립니다!
IrreplaceableOldHangulError에 대해서는 error를 반환해주는 게 적합한지 좀 더 고민해볼 필요가 있다고 생각해요.
해당 PR의 논의를 참고해보시면 좋을 것 같아요! #307 (comment)

@hsh2001
Copy link
Author

hsh2001 commented Jan 3, 2025

@po4tion 안녕하세요! 좋은 제안 감사합니다. 링크해주신 PR에서의 논의는 대체할 수 있는 대상이 있어서 에러를 내는 대신 다른 값으로 대체하여 응답한다는 결정이 가능한 것 같아요!

다만 이 함수는 NFC로 정규화된 옛한글이 존재하지 않기 때문에 대체할 수 있는 대상이 없습니다. 대신 기존의 NFD 정규화로 되어 있던 옛한글 부분은 그대로 유지하고, 대체 가능한 부분만 바꿔서 반환하는 것도 방법일 것 같습니다.

하나 더 고민되는 부분이, NFD 정규화 된 문자열은 es-hangul 의 많은 함수가 제대로 작동하지 않을 것이고, NFC 정규화 문자열과의 비교 연산에서 false 를 내기 때문에 개발자가 의도한 대로 작동하지 않을 가능성이 크다고 생각합니다. 단순히 기존의 문자열과 같은 결과로 반환해주는 것보다는 사용자에게 매핑을 할 수 있는 선택지를 주는 것은 어떨까 생각합니다. 만약 매핑을 하지 않았다면 에러를 내는거죠..!

추가로 해당 논의 자체가 결론을 짓기 전에 es-hangul 이 에러를 대하는 기조를 정하면 어떨까 생각합니다. 에러를 덜 내서 사용자의 경험을 중요하게 생각하는 것도 중요하지만, 에러를 덜 내기 위해 여러 예외 케이스를 모두 명시하면 오히려 라이브러리를 사용하기 위해 알아야 할 내용이 더 많아지고 복잡해질 수도 있을 것 같습니다. 그리고 단순히 에러를 내지 않기 위해 다른 행동을 한다면, 사용자가 예상하지 못한 다른 결과가 에러를 냄으로써 막히지 못하고 코드의 흐름을 계속 타고 가며 더 큰 에러나 불편을 겪을 수도 있지 않을까 생각합니다. 때때로는 잘못된 결과값을 보여주는 것보다는 에러를 내서 핸들링하지 못한 예외점에서 코드를 중단 시켜주는 역할도 필요할 것입니다.

결론적으로 다음과 같은 선택지가 있을 것 같습니다!

  1. 현안 유지 (throw IrreplaceableOldHangulError) : includeOldHangul(str) == true 인 경우에만 해당 에러를 내기 때문에 사용자에게 책임을 맡긴다.
  2. 대체 불가능한 부분은 NFD 정규화로 그대로 둔다.
  3. 옵션으로 대체 불가능한 한글을 매핑할 수 있는 콜백을 전달할 수 있게 한다.
function replaceNFDHangulToNFCHangul(str: string, options?: {
  oldHangulMapper?: (char: string) => string;
}): string;

@okinawaa
Copy link
Member

okinawaa commented Jan 6, 2025

@hsh2001 님 답변 늦어 죄송합니다.
본문과 여러 코맨트 내용이 다른 이야기를 하고 있는 것 같은데요.
혹시 코맨트 혹은 별도 이슈로 @hsh2001 님께서 해결하고자 하는 문제에 대해 명확히 작성해주실 수 있나요?
코맨트를 읽어보았는데, 해결 방법이 기술되어있고 해결하고자 하는 문제를 제가 잘 이해하지 못해서 질문드립니다! 🙇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants