You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Semantic-Cpp는 완전히 재설계된 현대적인 C++ 스트림 처리 라이브러리로, **"다중 헤더 파일, 제로 외부 의존성"**의 모듈식 아키텍처를 채택하고 있습니다. 각 헤더 파일은 명확한 책임을 가지며 독립적으로 테스트 가능하여, 함께 완전한 스트림 처리 생태계를 구성합니다.
본 라이브러리는 다양한 프로그래밍 패러다임의 정수를 창의적으로 융합했습니다:
JavaScript Generator의 지연성과 유연성: 지연 계산, 필요할 때 생성, 메모리 친화적 🌱
데이터베이스 인덱스의 효율성과 정렬성: 지능형 정렬, 인덱스 기반, 시계열 데이터 처리의 강력한 도구 ⏱️
컨테이너를 요소로 하는 배치 처리 철학: 벡터, 연결 리스트, 맵... 모든 컨테이너가 스트림의 일급 시민으로 자유롭게 흐름 📦
💡 도입 배경
손수 for 루프를 작성해 vector를 순회하고, 다시 if로 필터링한 후, 또 다른 컨테이너에 수동으로 push_back하는 데 지치셨나요? 😩
역방향 순회 시 "뒤에서 세 번째" 요소를 가져오려다 인덱스가 한 칸 어긋나는 버그를 밤늦게 디버깅한 적이 있으신가요? 😵💫
데이터베이스를 다루듯 인덱스로 정밀하게 찾고, 윈도우 슬라이딩으로 분석하며, 단 한 줄의 체인 호출로 데이터부터 통계까지 완벽한 여정을 완성하고 싶지 않으신가요? 🤔
Semantic-Cpp는 바로 이를 위해 탄생했습니다. 🔧
데이터 처리를 **"요소"**와 그 **"논리적 위치(인덱스)"**에 대한 작업으로 추상화합니다. 마치 데이터베이스의 "행"과 "기본 키"처럼, 데이터 자체를 건드리지 않고도 인덱스를 자유롭게 재배열, 오프셋, 반전시킬 수 있으며, 어떤 컨테이너(vector, map, array...)든 스트림 내에서 분할할 수 없는 하나의 전체로 전달했다가 언제든지 다시 요소 수준으로 **"언패킹"**할 수 있습니다. 이처럼 두 가지 입도(granularity)를 자유롭게 전환하는 능력은 기존 스트림 프레임워크에는 없는 특징입니다. 🎯
🏗️ 프로젝트 아키텍처: 7계층 모듈식 설계
Semantic-Cpp는 7개의 핵심 헤더 파일로 구성되며, 계층별로 점진적으로 발전합니다. 5개의 네임스페이스가 각자의 역할을 수행하며 데이터 소스부터 최종 결과까지 완전한 파이프라인을 함께 구성합니다:
┌─────────────────────────────────────────────────┐
│ 🌊 semantics.h │
│ 네임스페이스: semantic │
│ 스트림 빌더 팩토리: 숫자 범위, 컨테이너, 텍스트, 유니코드 │
├─────────────────────────────────────────────────┤
│ 📦 semantic.h │
│ 네임스페이스: semantic / collectable │
│ 스트림 중간 연산, Collectable 체계, 컨테이너 확장 지원 │
├─────────────────────────────────────────────────┤
│ ⚙️ collector.h │
│ 네임스페이스: collector │
│ 컬렉터 프레임워크 + 팩토리: 매칭, 검색, 집계, 통계, DFT/FFT│
├─────────────────────────────────────────────────┤
│ 🔤 charsequence.h │
│ 네임스페이스: charsequence │
│ 유니코드 문자 시퀀스, 다중 인코딩 변환, Builder, Buffer │
├─────────────────────────────────────────────────┤
│ 🧵 pool.h │
│ 네임스페이스: pool │
│ 전역 스레드 풀: 작업 제출, 긴급 종료, 예외 전파 │
├─────────────────────────────────────────────────┤
│ 📄 function.h │
│ 네임스페이스: function │
│ 타입 정의: Generator, Supplier, Consumer 등 별칭 │
├─────────────────────────────────────────────────┤
│ 🔐 hash.h / less.h │
│ 네임스페이스: std (확장) │
│ 표준 라이브러리 컨테이너 해시 및 비교 특수화, 임의 중첩 지원 │
└─────────────────────────────────────────────────┘
🧩 의존성 관계
의존성 체인은 정교하게 설계된 회로도처럼 명확합니다. 전류가 가장 아래층의 타입 정의에서 시작하여 단계별로 위로 올라가며, 각 계층은 자신의 아래 계층에만 의존합니다. 최종적으로 모든 회선이 semantic.h와 semantics.h로 모여 완전한 스트림 처리 능력을 형성합니다.
function.h ← 의존성 없음, 타입 기초석
pool.h ← function.h에 의존
charsequence.h ← 독립 모듈, 유니코드 처리
collector.h ← function.h, pool.h에 의존
hash.h / less.h ← 독립 모듈, 표준 라이브러리 확장
semantic.h ← 위의 모든 것에 의존
semantics.h ← semantic.h에 의존
🌍 네임스페이스 파노라마
Semantic-Cpp는 5개의 네임스페이스를 정교하게 설계했으며, 각각은 마치 독립된 "부서"처럼 각자의 임무를 수행하면서도 긴밀하게 협력합니다:
네임스페이스
소속 파일
책임
핵심 타입/함수
function
function.h
타입 시스템 기초석
Timestamp, Module, Generator, Supplier, Consumer, Predicate 등
charset, Meta, Point, Charsequence, Builder, Buffer 등
collector
collector.h
최종 수집 실행
Collector<E,A,R>, Identity, Accumulator<A,E> 등
collectable
semantic.h
구체화된 데이터 컨테이너
Collectable, OrderedCollectable, UnorderedCollectable 등
semantic
semantic.h
semantics.h
스트림 빌드 및 중간 연산
Semantic, useRange(), useFrom() 등
🔁 네임스페이스 협업 흐름
네임스페이스 간 데이터 흐름은 마치 공장의 조립 라인과 같습니다. 원자재는 semantic으로 들어와 여러 단계의 가공을 거쳐 최종적으로 collector에서 포장되어 출하됩니다. 각 단계마다 명확한 책임 경계가 있습니다:
semantic::useRange(0, 100) // ← semantic 네임스페이스: 스트림 생성
.map(int x { return x * 2; }) // ← semantic 네임스페이스: 중간 변환
.filter(int x { return x > 50; }) // ← semantic 네임스페이스: 중간 필터
.toUnordered() // ← collectable 네임스페이스로 변환
.toVector(); // ← collector 네임스페이스의 컬렉터 호출
📦 제1계층: function.h — 타입 기초
function.h는 전체 프레임워크의 타입 시스템을 정의하며, 모든 모듈의 공통 기초석입니다. 🔑
namespacefunction {
using Timestamp = longlong; // 인덱스 타입, 스트림 내 데이터의 "타임스탬프"using Module = unsignedlonglong; // 모듈/카운트 타입template <typename T>
using Generator = std::function<void(
std::function<void(T, Timestamp)>, // accept — 요소 하나를 받음
std::function<bool(T, Timestamp)> // interrupt — 중단할까?
)>;
}
Generator는 전체 스트림 시스템의 핵심 추상화입니다. 🌀 데이터를 반환하지 않고, 대신 두 개의 콜백을 받습니다—accept("준비됐어, 이 요소를 받아줘")와 interrupt("멈춰야 할까?").
이러한 제어 반전(Inversion of Control) 설계 덕분에 데이터 생산자는 소비자가 누군지 전혀 알 필요 없이, 적절한 시점에 데이터를 "푸시"하기만 하면 됩니다. 이것이 바로 **지연 평가(lazy evaluation)**의 정수입니다. 데이터는 accept가 호출될 때만 실제로 "흐르며", 그 전까지 모든 것은 단지 설명일 뿐입니다.
pool.h는 전역 스레드 풀 pool::pool을 제공하며, 전체 프레임워크의 동시성 엔진입니다. 🚀
선언적 병렬 처리(declarative parallelism) 설계를 채택했습니다. .parallel(4)라고 작성했을 때, 즉시 4개의 스레드가 시작되어 처리를 시작하지 않습니다. 이 코드 줄은 단지 "선언"일 뿐입니다. 프레임워크에게 "4개의 스레드로 병렬 처리할 계획입니다"라고 알려주는 것입니다.
실제 병렬 실행은 최종 연산이 호출될 때—즉, toVector(), findFirst(), count()와 같은 수집 메서드를 호출하는 순간에 발생합니다.
기능
설명
선언적 병렬
.parallel(4)는 단지 "스레드 4개로 병렬 처리하겠다"는 선언이며, 즉시 시작하지 않음
긴급 종료
내장 emergencyShutdown() 및 std::set_terminate 핸들러
예외 전파
submit()은 std::future를 반환하며, 예외를 안전하게 주 스레드로 전파
🔤 제3계층: charsequence.h — 유니코드 문자 시퀀스
charsequence.h는 완전한 유니코드 처리 모듈로, 문자 시퀀스의 생성, 변환 및 조작 기능을 제공합니다. 🌍
UTF-8, UTF-16(LE/BE), UTF-32(LE/BE), ASCII, Latin1 등 다양한 인코딩을 지원하며, 서로게이트 페어(surrogate pair)를 올바르게 감지하고 처리하며, 유효하지 않은 코드 포인트에 대해 표준 U+FFFD 대체 문자를 반환합니다.
모든 표준 라이브러리 컨테이너(중첩 컨테이너 포함), pair, tuple, optional, variant, chrono 시간 타입, complex 복소수 등에 대해 완전한 해시 및 비교 지원을 제공합니다. 이제 임의의 깊이와 조합의 중첩 컨테이너도 unordered_set의 키나 set의 요소로 사용할 수 있습니다. 🌉
🚀 성능 최적화 팁
적합한 컨테이너 선택: 순서가 중요하지 않다면 toUnordered(), 정렬이 필요하다면 toOrdered() 또는 sort()
병렬 처리 활용: 데이터 양이 많을 때 parallel() 사용
연산 순서 최적화: 가능한 빨리 filter하고, 신중하게 sort할 것
지연 평가 활용: takeWhile과 limit으로 조기 종료 가능
Semantic-Cpp — 현대적인 C++로 효율적이고 명확한 데이터 처리 파이프라인을 구축하세요. 🚀🎯✨