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]: josa 함수 처리에서 누락된 조사를 추가해주세요. #119

Open
RanolP opened this issue Jun 9, 2024 · 7 comments

Comments

@RanolP
Copy link

RanolP commented Jun 9, 2024

Description

josa 함수에서 누락된 조사 처리가 있습니다.
아래 목록은 참고를 위해 한국어 단어 데이터베이스 쿼리를 통해 구한 목록이며, 모든 한국어 조사를 포함하지는 않을 수도 있습니다.

목록:

  • ⚪ 구어체적이어서 지원할 필요가 없는 것: ㄴ(은/는), ㄴ커녕(은커녕/는커녕), ㄹ(을/를)
  • ✅ 이미 처리하고 있는 것: 이/가, 와/과, (이)나, 은/는, 은/는 + 커녕, (이)랑, (이)란, (으)로, (으)로부터, (으)로서, (으)로써, 을/를, 을/를 + 랑, 을/를 + 랑은, 아/야, 이에요/예요
  • ⚪ 받침에 따라 바뀌지 않는 것: 같이, 곧**, 까지, 게, 게로, 게서, 깨나, 께, 께서, 께압서*, 께오서*, 께옵서, 끄정*, 다가, 대로, 더러, 도, 도고*, 두*, 들, 따라, 마냥*, 마다, 마따나, 마저, 마치*, 마콤*, 만, 만치, 만큼, 밖에, 버덤*, 보고, 보다, 부터, 뿐, 새려*, 새로에, 서, 서껀, 서부터, 서야, 설라믄*, 설랑은, 안테로*, 에, 에게, 에게다, 에게로, 에게서, 에는, 에다, 에다가, 에로, 에를, 에서, 에서부터, 에서야, 에야, 에의, 엔, 엘, 의, 조차, 처럼, 치고, 치고는, 치고서, 카냥*, 커녕, 토록, 하고, 하며, 한테, 한테로, 한테서, 할래*, 헌테*
  • ❌ 처리하지 않고 있는 것: (이)고, (이)나마, (이)니, (이)다, 서술격 조사 (이)다, (이)든, (이)든가, (이)든지, (이)라, (이)라고, (이)라도, (이)라든가, (이)라든지, (이)라서, (이)라야, (이)라야만, (이)며, (이)면, (이)시여, (이)야, (이)야말로, (이)여, (이)요, 인들/ㄴ들, 인즉/ㄴ즉, 인즉슨/ㄴ즉슨, 일랑/ㄹ랑, 일랑은/ㄹ랑은
    • ⚪ 규범 표기가 아닌 것: 사말로*, 이나따나*
  • ⚪ 명사에 붙지 않는 것: -다 + 거나, -군/-구먼 등 + 그래, -하세/-ㅂ시다 + 그려, -다 + 마는, 손
  • ❔ 규칙이 까다로운 것: 다가, 이랴

*: 규범 표기가 아님
**: 예스러운 표현

모든 조사를 꼭 지원할 필요는 없지만 몇몇 조사는 종종 쓰이는 경우가 있을 것 같아요. 가령 RPG 웹 게임에서 대사를 만든다든지요.

// 황혼검이야말로 대장장이 지크가 만든 최고 역작이지
// 핏빛 도끼야말로 대장장이 톰슨이 만든 최고 역작이지
show(`${josa(item, '이야말로/야말로')} 대장장이 ${josa(npcSmith.name, '이/가')} 만든 최고 역작이지.`)
const [strong1, strong2] = shuffled(strongEnemies)
// 오우거며 용아병이며 불꽃 도끼를 상대론 이길 수 없었지
show(`${josa(strong1.name, '이며/며')} ${josa(strong2.name, '이며/며')} ${josa(item, '을/를')} 상대론 이길 수 없었지.`)

혹은 조건 나열에도 쓰일 법은 한데, 해당 케이스에는 아마 문장을 통으로 쓸 것 같아서 잘 쓰이진 않을 수도 있겠네요.

const reason: '이미 가입 중' | '만 19세 이하' | ... = ...;
`${josa(reason, '이라서/라서')} 가입할 수 없어요`

Possible Solution

전제 조건

  1. 서술격 조사 이다의 경우 활용형이 너무 많아서 타입으로 잡는 데에 한계가 있고(심지어 코드베이스에 존재하는 '이에요/예요' 처럼 축약형까지 고려하면 일반화가 꽤나 까다롭습니다)
    • 축약형은 고려하지 말아봅시다...
  2. 처리하지 않고 있는 대부분의 조사는 '이'가 생략되는 형태입니다.

해결책

  1. 위 조건을 고려할 때, 아래*와 같은 코드로 처리가 가능할 수 있습니다.

    • 자동 완성이 필요하거나 예외 케이스(예요 등)가 필요하다면 JosaOption에 자주 쓰이는 조사를 미리 등록해두면 해결됩니다.

    아래*

    // Taken from type-fest. CC0-1.0.
    export type IsEqual<A, B> =
      (<G>() => G extends A ? 1 : 2) extends
      (<G>() => G extends B ? 1 : 2)
        ? true
        : false;
    
    type ISkip<T extends string> =
      T extends `이${infer L}/${infer R}`
      ? IsEqual<L, R> extends true
        ? T
        : never
      : never;
    
    type JosaOption =
      | '이/가'
      | '을/를'
      | '은/는'
      | '으로/로'
      | '와/과'
      | '아/야'
      | '이랑/랑'
      | '이에요/예요'
      | '으로서/로서'
      | '으로써/로써'
      | '으로부터/로부터';
    
    declare function josa<T extends string>(word: string, josa: JosaOption | ISkip<T>): string;
    
    josa('돈', '이야말로/야말로')
    josa('돈', '이나/나')
    // @ts-expect-error
    josa('돈', '이야말로/야말')
    // @ts-expect-error
    josa('돈', '이나/이나나')
  2. 특수한 조사 옵션 (이)를 만듭니다.

    • 이 경우 josa(str, '이나/나')josa(str, '(이)') + '나'처럼 쓰게 됩니다.
    • 또는, `(이)${string}` 타입을 허용해서 josa(str, '(이)나')처럼 처리할 수도 있습니다.
      • 런타임 코드에서는 startsWith('(이)')로 분기를 추가하게 되어 약간의 복잡도가 증가합니다.
      • 자동 완성이 필요하거나 예외 케이스(예요 등)가 필요하다면 JosaOption에 자주 쓰이는 조사를 미리 등록해두면 해결됩니다.
    • 개인적으로 작성했던 스크립트에서 해당 방식을 채택했는데, 모든 조사를 나열하지 않고 쉽게 정의해 구현이 편리했었습니다만, 현재 es-hangul의 구현 방식 및 라이브러리 사용자 측 DX를 고려할 때 유리한 점이 없을 수도 있을 것 같습니다.
    • 하위 호환성을 고려할 때 채택이 어려울 수도 있겠습니다.

etc.

No response

@RanolP
Copy link
Author

RanolP commented Jun 9, 2024

#82 와 일부 중복된 논의겠습니다만, 제시된 조사들도 받침 유무 로직으로 처리가 되다보니 타입으로 제약할 필요는 없어 보여요. 타입을 약간 수정해서 다양한 경우에 사용할 수 있도록 바꿀 수 있지 않을까요?

@crucifyer
Copy link
Contributor

동의합니다.
josa('돈', '이/') + '야말로'
식으로 하는편이 코드가 단순하고 좋을 것 같습니다.

@okinawaa
Copy link
Member

okinawaa commented Jul 3, 2024

늦게 코맨트 남겨 죄송합니다. 자세하게 남겨주셔서 감사합니다.

제가 이슈의 주제를 잘 이해하지 못했는데요,
누락된 조사가 있다는게 문제라면, 축약형 이외에 조사들을 추가해주면 되지 않나요?

@RanolP
Copy link
Author

RanolP commented Jul 3, 2024

언급한 이슈에서 결론지어진 방향성이 "그 유용성에 비해 자주 쓰이지 않기에 코드 복잡도 및 유지보수 부담을 줄이기 위해 추가하지 않는다"에 가깝다고 판단했고(제가 비약한 결론이라 아니라면 정정해주세요), 복잡도를 크게 증가시키지 않으면서 다양한 조사를 처리할 방법에 대한 제안이었습니다

@crucifyer
Copy link
Contributor

JosaOption 타입을 없애고 문자열로 다루면 간단해질거라 생각합니다.

JosaOption 을 유지하더라도
'이야말로/야말로' 를 '이/' + '야말로' 로 처리하면 대부분의 패턴은 해결될 것으로 보입니다.

@okinawaa
Copy link
Member

okinawaa commented Aug 9, 2024

josa옵션의 타입을 지정함으로써 josa 함수를 사용하는 타입스크립트 사용자의 자동완성적인 메리트가 너무 강력하여, string type으로 수정하는것은 어려울 것 같아요. ㅠ

타입은 유지하되, 추가가 필요한 조사들은 추가하는게 좋을 것 같습니다. 한번 추가해두면 유지보수에 크게 어려운 부분은 없을 것 같아요. 구현은 이미 되어있기 때문입니다.

규범인 것, 그리고 예스러운 표기가 아닌것 부터 우선 추가해보면 좋을 것 같다고 생각해요!

@crucifyer
Copy link
Contributor

(아까 썼던건 로_조사 에 대한 이해부족으로 삭제했습니다.)

조금 다른 내용이지만, 함께 생각해야 할 것 같아 여기에 적습니다.
https://ko.dict.naver.com/#/correct/korean/info?seq=1657
이에요/예요 는 같은말 입니다.
이에요/에요 가 원래의 구별이고, 이에요를 예요로 줄일 수 있는것입니다.

황혼검이에요
핏빛 도끼에요 (예요 x)
영수에요
영숙이이에요 -> 영숙이예요
type JosaOption =
  | '이어/'
  | '이에/'

const 에요_조사: JosaOption[] = ['이어/', '이에/'];

const isEndsWith이 = word[word.length - 1] === '이';
if(isEndsWith && 에요_조사.includes(josa)) {
 대충 이에->, 이어->  바꾸는 코드
}

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

No branches or pull requests

3 participants