{"id":48981624,"url":"https://github.com/hsl0/tjosa","last_synced_at":"2026-04-18T11:19:51.683Z","repository":{"id":344447111,"uuid":"1181853773","full_name":"hsl0/tjosa","owner":"hsl0","description":"t-string을 지원하는 Python 한국어 조사 처리 라이브러리","archived":false,"fork":false,"pushed_at":"2026-03-22T07:24:29.000Z","size":81,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-22T22:11:04.981Z","etag":null,"topics":["josa","korean","python","t-string"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/tjosa/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hsl0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-14T18:01:35.000Z","updated_at":"2026-03-22T07:24:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hsl0/tjosa","commit_stats":null,"previous_names":["hsl0/tjosa"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/hsl0/tjosa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hsl0%2Ftjosa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hsl0%2Ftjosa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hsl0%2Ftjosa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hsl0%2Ftjosa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hsl0","download_url":"https://codeload.github.com/hsl0/tjosa/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hsl0%2Ftjosa/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31966338,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["josa","korean","python","t-string"],"created_at":"2026-04-18T11:19:51.128Z","updated_at":"2026-04-18T11:19:51.672Z","avatar_url":"https://github.com/hsl0.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tjosa\n\n한국어 조사를 어간에 맞게 자동으로 맞춰주는 라이브러리입니다. t-string을 통해 삽입한 값의 조사를 자동으로 인식해 변환하는 기능을 지원합니다.\n\n## 요구 사항 (Requirements)\n\n- Python 3.12+\n  - t-string을 기반한 `josa()` 함수는 Python 3.14 이상 버전 필요\n  - Python 3.14 미만 버전에서는 `josa_only()` 함수만 사용 가능\n\n## 설치 방법 (Installation)\n\n```bash\npip install tjosa\n```\n\n## 지원 조사\n\n- [은](https://stdict.korean.go.kr/search/searchView.do?word_no=467516\u0026searchKeywordTo=3)/[는](https://stdict.korean.go.kr/search/searchView.do?word_no=406525\u0026searchKeywordTo=3)\n- [이](https://stdict.korean.go.kr/search/searchView.do?word_no=471254\u0026searchKeywordTo=3)/[가](https://stdict.korean.go.kr/search/searchView.do?word_no=382734\u0026searchKeywordTo=3)\n- [을](https://stdict.korean.go.kr/search/searchView.do?word_no=469161\u0026searchKeywordTo=3)/[를](https://stdict.korean.go.kr/search/searchView.do?word_no=421993\u0026searchKeywordTo=3)\n- [과](https://stdict.korean.go.kr/search/searchView.do?word_no=398563\u0026searchKeywordTo=3)/[와](https://stdict.korean.go.kr/search/searchView.do?word_no=249573\u0026searchKeywordTo=3)\n- [으로](https://stdict.korean.go.kr/search/searchView.do?word_no=473314\u0026searchKeywordTo=3)/[로](https://stdict.korean.go.kr/search/searchView.do?word_no=421619\u0026searchKeywordTo=3)\n- [아](https://stdict.korean.go.kr/search/searchView.do?word_no=216454\u0026searchKeywordTo=3)/[야](https://stdict.korean.go.kr/search/searchView.do?word_no=220409\u0026searchKeywordTo=3)\n- [이](https://stdict.korean.go.kr/search/searchView.do?word_no=267418\u0026searchKeywordTo=3)/\n  - [이랑](https://stdict.korean.go.kr/search/searchView.do?word_no=469683\u0026searchKeywordTo=3)/[랑](https://stdict.korean.go.kr/search/searchView.do?word_no=100236\u0026searchKeywordTo=3)\n  - [이며](https://stdict.korean.go.kr/search/searchView.do?word_no=260127\u0026searchKeywordTo=3)/[며](https://stdict.korean.go.kr/search/searchView.do?word_no=425032\u0026searchKeywordTo=3)\n  - 이다/다\n  - 이가/가\n\n`이랑/랑`, `이며/며`, `이다/다`, `이가/가`는 `이/`를 통해 지원합니다.\n\n## 사용법 (Usage)\n\n### josa\n\n`josa(template: Template, *, conversion_rules: ConversionMap[str], fallback_formatter: FallbackFormatter[str]) -\u003e str`\n\nt-string 템플릿의 삽입값에 맞춰 뒤따르는 조사를 자동 변환합니다.\n\n**Python 3.14 이상 버전이 필요합니다.**\n\n`conversion_rules` 변수에 `ConversionRule` 클래스 기반의 변환 규칙들을 포함한 `ConversionMap`을 넣어 변환 규칙을 변경할 수 있습니다.\n\n`fallback_formatter` 변수에 `FallbackFormatter` 프로토콜을 따르는 함수를 넣어 조사 판별 불가 시 `이(가)`와 같이 대체되는 문자열의 형식을 바꿀 수 있습니다.\n\n예시:\n\n```python\nfrom tjosa import josa\n\nfood = \"사과\"\nprint(josa(t\"{food}는 맛있다\"))   # 사과는 맛있다\n\nfood = \"파인애플\"\nprint(josa(t\"{food}는 맛있다\"))   # 파인애플은 맛있다\n\n```\n\n### josa_only\n\n`josa_only(cheon: str, josa: BuiltinJosa | ConversionRule[str] | str, *, fallback_formatter: FallbackFormatter[F],conversion_rules: ConversionMap[str]) -\u003e str`\n\n체언과 조사를 입력하면, 체언에 맞는 적절한 조사를 반환합니다.\n\n`josa`에 입력할 수 있는 조사는 [지원 조사](#지원-조사) 문단을 참고해 주세요. 예를 들어, `은/는`을 사용할 경우 `은` 또는 `는` 중 하나를 선택해서 `josa` 인자에 입력하면 됩니다.\n\n단, `이/가`와 `이/`와 중복되는 조사 `이`의 경우, `이/`가 우선되므로 `이/가`를 구분하려는 경우에는 `가`를 사용해 주세요.\n\n`josa`에 `ConversionRule` 클래스를 사용한 사용자 지정 조사 변환 규칙 객체를 대신 사용할 수 있습니다.\n\n예시:\n\n- `josa_only(\"사과\", \"은\")` -\u003e `는`\n- `josa_only(\"집\", \"은\")` -\u003e `은`\n- `josa_only(\"학교\", \"으로\")` -\u003e `로`\n\n### 사용자 지정 조사 변환\n\ntjosa 패키지는 사용자 지정 조사 변환 규칙을 추가하거나 변경할 수 있습니다.\n\n예를 들어, 체언의 마지막 음절에 종성(받침)이 존재할 때 '이다', 존재하지 않을 때 '다' 조사를 붙인다면 다음과 같이 사용할 수 있습니다. ('이다/다'는 사용자 지정 규칙 없이도 '이/'를 통해 이미 지원합니다.)\n\n```py\nfrom tjosa import josa\nfrom tjosa.rules import JongsungRule\nfrom tjosa.mappings import create_conversion_map\nfrom tjosa.mappings.josa import josa_rules\n\ne_da = JongsungRule(\"이다\", \"다\")\n\ncustom_josa_map_exclusive = create_conversion_map([e_da])\ncustom_josa_map_extended = create_conversion_map([*josa_rules, e_da])\n\nword = '조사'\nprint(josa(t'{word}이다', conversion_rules=custom_josa_map_exclusive)) # 조사다\n\nword = '한글'\nprint(josa(t'{word}이다', conversion_rules=custom_josa_map_extended)) # 한글이다\n```\n\n#### tjosa.mappings 모듈\n\n사용자 지정 조사 쌍 매핑을 만들 수 있는 모듈입니다.\n\n##### ConversionMap\n\n사용 가능한 여러 조사 변환 규칙(`ConversionRule`)들을 묶는 객체입니다.\n\n##### create_conversion_map\n\n`create_conversion_map(rules: ConversionRule[str]) -\u003e ConversionMap[str]`\n\n`ConversionMap` 객체를 생성합니다. 중복된 조사를 등록할 경우, 뒤에 오는 규칙이 우선됩니다.\n\n##### tjosa.mappings.josa 모듈\n\n기본적으로 사용하는 `ConversionMap` 데이터가 있습니다. 사용자 지정 조사 규칙을 추가하거나 일부 규칙을 수정할 때 사용할 수 있습니다.\n\n- `BuiltinJosa`: 기본적으로 제공하는 조사의 리터럴 타입입니다. 타입 검사에서 기본 조사만을 받으려 할 때 사용할 수 있습니다.\n- `josa_rules`: 기본적으로 사용하는 조사들의 `ConversionRule` 규칙 객체들을 모아 놓은 리스트입니다. 이 리스트에서 일부 규칙을 수정하거나 사용자 지정 규칙을 추가한 뒤, `create_conversion_map`을 통해 사용자 지정 규칙을 만들 수 있습니다.\n- `josa_map`: 기본적으로 사용하는 조사들의 `ConversionMap` 객체입니다.\n\n#### tjosa.rules 모듈\n\n사용자 지정 조사 변환 규칙을 만들 수 있는 모듈입니다.\n\n##### ConversionRule\n\n사용자 지정 조사 변환 규칙을 만들 수 있는 클래스 프로토콜입니다.\n\n변환 규칙이 특수한 조사 쌍을 만들 때 이 프로토콜을 구현한 클래스를 만들 수 있습니다.\n\n`choose()` 메소드와 `get_candidates()` 메소드를 구현해야 합니다.\n\n###### choose\n\n`choose(self, word: str, *, fallback_formatter: FallbackFormatter[str]) -\u003e str`\n\n체언을 입력받아 적절한 조사를 반환합니다.\n\n적절한 조사를 찾지 못한 경우, `fallback_formatter`에 `FallbackFormatter` 인터페이스를 구현한 폴백 포맷터 함수를 이용해 모든 조사 후보를 대신 반환해야 합니다.\n\n###### get_candidates\n\n`get_candidates(self) -\u003e Iterable[str]`\n\n가능한 모든 조사의 후보를 반환합니다.\n\n##### JongsungRule\n\n체언의 마지막 음절에 종성(받침)이 존재하는 지 여부를 바탕으로 조사를 선택합니다.\n\n`JongsungRule(with_jongsung: str, without_jongsung: str)```\n\n`with_jongsung` 인자에 종성이 있을 때 사용할 조사를, `without_jongsung` 인자에 종성이 없을 때 사용할 조사를 입력합니다.\n\n##### JongsungExceptRieulRule\n\n`JongsungRule`과 유사하게 체언의 마지막 음절에 종성(받침)이 존재하는 지 여부를 바탕으로 조사를 선택하지만, 종성이 'ㄹ'일 경우는 예외적으로 종성이 없는 것으로 취급합니다.\n\n`JongsungExceptRieulRule(with_jongsung: str, without_jongsung: str)`\n\n`with_jongsung` 인자에 'ㄹ'이 아닌 종성이 있을 때 사용할 조사를, `without_jongsung` 인자에 종성이 없거나 'ㄹ' 받침이 있을 때 사용할 조사를 입력합니다.\n\n### 사용자 지정 포맷터\n\n한글이 아닌 등 조사를 판별할 수 없을 때 `이(가)` 또는 `(이)`와 같이 조사 중 하나를 괄호에 넣고 둘을 병기합니다. 하지만 `FallbackFormatter` 인터페이스를 구현한 폴백 포맷터 함수를 직접 만들고 `josa()` 함수나 `josa_only()` 함수의 `fallback_formatter` 인자에 넣어 형식을 바꿀 수 있습니다.\n\n```py\nfrom tjosa import josa\n\ndef custom_formatter(*candidates: str) -\u003e str:\n    return f'({candidates[0]}/{candidates[1]})'\n\nword = 'tjosa'\nprint(josa(t'{word}는 좋다.', fallback_formatter=custom_formatter)) # tjosa(은/는) 좋다.\n```\n\n#### tjosa.formatter 모듈\n\n##### FallbackFormatter\n\n`(*candidates: str) -\u003e str`\n\n사용자 지정 포맷터 함수를 만들 때 준수해야 하는 함수 프로토콜 입니다.\n\n`candidates` 인자에는 가능한 모든 조사 후보들이 들어있으며, 우선 순위별로 정렬되어 있습니다.\n\n이러한 후보들의 몇 개를 병기한 문자열을 반환해야 하며, `candidates`의 일부만 사용할 경우에는 앞에 있는 것을 우선 사용해야 합니다.\n\n##### format_fallback\n\n`format_fallback(*candidates: str) -\u003e str`\n\n한글이 아닌 등 조사를 판별할 수 없을 때 `이(가)` 또는 `(이)`와 같이 조사 중 하나를 괄호에 넣고 둘을 병기합니다. 기본적으로 사용되는 `FallbackFormatter` 함수입니다.\n\n한 가지 종류의 조사가 들어오면 그 조사를 괄호에 넣습니다. (예: `(이)`)\n\n두 가지 종류의 조사가 들어오면 첫번째 조사는 그대로 표시하고, 두번째 조사는 괄호에 넣어 병기합니다. (예: `이(가)`)\n\n만약 세 가지 이상의 조사가 들어오면 두 가지 종류의 조사가 들어올 때와 같이 표시되며, 세번째 이후의 조사는 무시됩니다.\n\n## 성능 비교 (Performance)\n\n`tjosa`는 한 단어 조사 선택(`josa_only`)과 문장 전체 문자열 변환(`josa`) 사용 방식 모두에서 유사 라이브러리 대비 빠른 성능을 보입니다.\n\n동일 환경에서 유사 라이브러리와 함께 벤치마크를 측정한 결과는 다음과 같습니다.\n\n- 한 단어 조사 선택\n  - hsl0/tjosa.josa_only: 평균 **11.6421μs**\n  - [kimsehwan96/pyjosa](https://github.com/kimsehwan96/pyjosa).get_josa: 평균 **27.6061μs**\n  - hsl0/tjosa.josa_only가 약 **57.83%** 더 빠름\n  - 95% 신뢰구간에서 hsl0/tjosa.josa_only가 통계적으로 유의하게 우세\n\n- 문장 전체 조사 변환\n  - hsl0/tjosa.josa: 평균 **33.7467μs**\n  - [myevan/pyjosa](https://github.com/myevan/pyjosa).replace_josa: 평균 **35.5697μs**\n  - hsl0/josa가 약 **5.13%** 더 빠름\n  - 95% 신뢰구간에서 hsl0/tjosa.josa가 통계적으로 유의하게 우세\n\n자세한 사항은 [docs/benchmark.md](https://github.com/docs/benchmark.md) 문서를 참고해 주세요.\n\n## 라이선스 (License)\n\n본 패키지는 MIT 라이선스로 배포됩니다.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhsl0%2Ftjosa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhsl0%2Ftjosa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhsl0%2Ftjosa/lists"}