RSCC 공통 Python 라이브러리 — 로깅, X-Trace-Id 전파, CommonResponse, ResultCode, 텍스트 유틸
Project description
rscc-common
RSCC 공통 Python 라이브러리 — 공통 로깅, X-Trace-Id 분산 트레이스 전파, CommonResponse
응답 봉투, ResultCode 에러 코드, 한글 초성 유틸. 기본 설치는 의존성 0 (표준 라이브러리만) —
FastAPI/pydantic 통합은 [fastapi] extra 로 opt-in 한다.
Java(com.rscc:rscc-common-*)·JS(@rscc/common-*) 와 같은 저장소에서 와이어 계약을
공유하는 폴리글랏 라이브러리다 — 응답 봉투/에러 코드/트레이스 헤더 규약의 단일 소스는
contracts/.
- 저장소: https://github.com/Jeonghyeon-Ryu/r-common
- 변경 이력: CHANGELOG.md
- 라이선스: MIT
설치
pip install rscc-common # 기본 — 의존성 0 (errors / logging / trace / text)
pip install "rscc-common[fastapi]" # + fastapi>=0.110, httpx>=0.27 (response 모듈 사용 가능)
PyPI 대신 git 태그로 직설치할 수도 있다 (pip 은 서브디렉토리 설치를 지원):
pip install "rscc-common[fastapi] @ git+https://github.com/Jeonghyeon-Ryu/r-common.git@py-v0.2.0#subdirectory=python/rscc-common"
# extra 불필요 시: "rscc-common @ git+https://...#subdirectory=python/rscc-common"
(py-v0.2.0 릴리스 후 유효 — 최신 태그는
CHANGELOG.md 참조.
py-v0.1.0 은 이 문서의 API 일부(reset_trace_id 등)가 없는 릴리스 인프라 도입 이전 태그 —
사용하지 말 것.)
개발(저장소 체크아웃 안, editable — --reload 에 즉시 반영):
pip install -e "python/rscc-common[fastapi]"
Python >= 3.11 (상한 없음). 타입 힌트 포함 (py.typed — 소비 측 mypy/pyright 가 읽음).
모듈
| 모듈 | 의존성 | 공개 API |
|---|---|---|
rscc_common (최상위) |
없음 | __version__ + 무의존 심볼 재노출 (ResultCode, configure_logging, get_trace_id, set_trace_id, reset_trace_id, new_trace_id, install_trace_middleware, trace_request_hook, async_trace_request_hook) |
rscc_common.errors |
없음 | ResultCode enum — 멤버별 .code(str, 와이어는 JSON 문자열) / .http_status(int) / .message(기본 한국어 메시지). contracts/error-codes.yaml 과 정확히 동기 (테스트로 강제) |
rscc_common.logging |
없음 | configure_logging(log_dir, level, app_name, *, noisy_loggers=..., quiet_uvicorn=...) — 콘솔 + 자정 롤링 파일(전날분 gzip, 30일 보관). 명시 호출형 (임포트 부작용 없음), 재호출 시 기존 핸들러 close 후 교체 |
rscc_common.trace |
없음 (순수 ASGI/덕타이핑) | contracts/trace.md 구현 — install_trace_middleware(app), get_trace_id(), set_trace_id(id) -> Token, reset_trace_id(token), new_trace_id(), httpx 발신 훅 trace_request_hook / async_trace_request_hook, 상수 TRACE_HEADER |
rscc_common.response |
[fastapi] extra 전용 (pydantic) | CommonResponse — 와이어 키 success/code/message/data, 팩토리 ok(data) / fail(result_code, message=None), to_wire() 가 data=None 키 생략을 강제 (contracts/common-response.schema.json) |
rscc_common.text.chosung |
없음 | of(s) — 한글 초성 변환 (예: "검색 엔진" → "ㄱㅅㅇㅈ"), is_chosung_query(s) — 초성 질의 여부. search-api Chosung.java / ai-core chosung.py 와 골든 벡터 파리티 |
사용 예
from fastapi import FastAPI
import httpx
from rscc_common import configure_logging, install_trace_middleware, trace_request_hook
from rscc_common.errors import ResultCode
from rscc_common.response import CommonResponse # [fastapi] extra 필요
configure_logging(log_dir="logs", app_name="ai-core",
noisy_loggers=("httpx", "httpcore", "urllib3"), quiet_uvicorn=True)
app = FastAPI()
install_trace_middleware(app) # X-Trace-Id 수신 재사용 → contextvar → 응답 에코
# 다운스트림 전파 (trace.md 4단계)
client = httpx.Client(event_hooks={"request": [trace_request_hook]})
@app.get("/thing")
def get_thing():
return CommonResponse.ok({"id": 1}).to_wire() # data 포함
@app.get("/missing")
def missing():
return CommonResponse.fail(ResultCode.NOT_FOUND).to_wire() # data 키 부재
요청 컨텍스트 밖(백그라운드 태스크 등)에서 traceId 를 수동 바인딩할 때:
from rscc_common import new_trace_id, reset_trace_id, set_trace_id
token = set_trace_id(new_trace_id()) # 또는 요청에서 캡처해 둔 traceId
try:
do_background_work() # 이 안의 로그·httpx 발신에 traceId 가 실린다
finally:
reset_trace_id(token) # 이전 값 복원 (권장) — 일회성 태스크는 set_trace_id(None) 도 가능
알려진 제약
- 트레이스 미들웨어는 미처리 예외의 500 응답에
X-Trace-Id를 에코하지 못한다 —app.add_middleware등록이 StarletteServerErrorMiddleware안쪽에서 실행되기 때문.HTTPException·검증 오류 등 예외 핸들러가 처리하는 경로(4xx 등)는 정상 에코된다. 상세·우회책은rscc_common.trace.install_trace_middlewaredocstring 참조. rscc_common.response는[fastapi]extra 설치 후에만 임포트 가능 — 기본 설치에서 임포트하면ModuleNotFoundError(pydantic 부재). 나머지 모듈은 기본 설치로 동작.- FastAPI 핸들러에서
CommonResponse모델을 직접 반환하지 말고 반드시.to_wire()를 반환할 것 — 직접 반환하면data: null이 와이어에 실려 "실패/무데이터 시 data 키 생략" 계약이 깨진다. configure_logging은 단일 프로세스(단일 uvicorn worker) 전제 — 멀티 worker 가 같은 로그 파일을 회전시키면 안전하지 않다.level기본값은logging.DEBUG— 프로덕션은logging.INFO권장.text.chosung.of()의 공백 스킵은 스페이스/탭만 (개행·전각 공백은 통과) — JavaChosung.java와의 파리티 제약.
테스트 (저장소 체크아웃에서)
cd python/rscc-common
python -m pytest -q # pyproject 의 pythonpath=["src"] 덕에 설치 없이 바로 동작
테스트 의존성은 pyproject 의 [dependency-groups] dev (pytest, pyyaml, fastapi>=0.110,
httpx>=0.27) — pip 25.1+ 는 pip install --group dev. tests/test_errors.py 는 저장소의
contracts/error-codes.yaml 과 enum 정합을 비교하며, 파일이 없는 환경(sdist 등)에서는 자동 skip 된다.
버전·릴리스
- 버전 단일 소스:
src/rscc_common/__init__.py의__version__—pyproject.toml은 dynamic version 으로 이 값을 읽는다 (릴리스 시 pyproject 수정 불필요). py-vX.Y.Z태그가 push 되면 GitHub Actions (release-python.yml) 이 태그↔__version__정합 검증 →python -m build→ PyPI Trusted Publishing (OIDC) 업로드 → GitHub Release 생성.- 절차 상세(runbook)·릴리스 이력: 루트 README · CHANGELOG.md
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rscc_common-0.3.0.tar.gz.
File metadata
- Download URL: rscc_common-0.3.0.tar.gz
- Upload date:
- Size: 146.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e9b900fa4bbd9089dcf9094da80855eaeb9b605e6ebc697e423596551d94d63
|
|
| MD5 |
09aee7f941481f1d6da54a7ef560d928
|
|
| BLAKE2b-256 |
99520aad07c905886fda232da7a7889ce7769c450fc700a75d4bdf25e27dbe00
|
Provenance
The following attestation bundles were made for rscc_common-0.3.0.tar.gz:
Publisher:
release-python.yml on Jeonghyeon-Ryu/r-common
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rscc_common-0.3.0.tar.gz -
Subject digest:
5e9b900fa4bbd9089dcf9094da80855eaeb9b605e6ebc697e423596551d94d63 - Sigstore transparency entry: 2191726545
- Sigstore integration time:
-
Permalink:
Jeonghyeon-Ryu/r-common@63ff2281e2b04f24dc820f88f888be69842b1a27 -
Branch / Tag:
refs/tags/py-v0.3.0 - Owner: https://github.com/Jeonghyeon-Ryu
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-python.yml@63ff2281e2b04f24dc820f88f888be69842b1a27 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rscc_common-0.3.0-py3-none-any.whl.
File metadata
- Download URL: rscc_common-0.3.0-py3-none-any.whl
- Upload date:
- Size: 113.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae271f9a947effd02e37fa7578859dd4eaba6d760867d62240c5c15e14a150da
|
|
| MD5 |
0e69f766541f425a3b2cae5e86894d7d
|
|
| BLAKE2b-256 |
d38b3a9445cc48948121931576cf40abd575f942aef5dcb94b7df931b1ef8175
|
Provenance
The following attestation bundles were made for rscc_common-0.3.0-py3-none-any.whl:
Publisher:
release-python.yml on Jeonghyeon-Ryu/r-common
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rscc_common-0.3.0-py3-none-any.whl -
Subject digest:
ae271f9a947effd02e37fa7578859dd4eaba6d760867d62240c5c15e14a150da - Sigstore transparency entry: 2191726551
- Sigstore integration time:
-
Permalink:
Jeonghyeon-Ryu/r-common@63ff2281e2b04f24dc820f88f888be69842b1a27 -
Branch / Tag:
refs/tags/py-v0.3.0 - Owner: https://github.com/Jeonghyeon-Ryu
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-python.yml@63ff2281e2b04f24dc820f88f888be69842b1a27 -
Trigger Event:
push
-
Statement type: