파서 결합자 개념
작은 파서를 조합해 더 큰 파서를 만듭니다.
파서 결합자 개념은(는) CoddyKit의 무료 TypeScript Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 TypeScript Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
파서란 무엇인가
파서는 입력(대개 문자열)을 읽고 구조화된 출력을 생성하거나 실패합니다. 같은 아이디어를 타입 시스템으로 옮기기 전에 먼저 값 수준에서 시작해 직관을 쌓습니다.
type Parser<T> = (input: string) => { value: T; rest: string } | null;
// Consumes part of the input, returns a value and the leftover아주 작은 파서
가장 단순한 파서는 리터럴 접두사를 찾습니다. 입력이 예상한 텍스트로 시작하면 성공하고 남은 문자열을 반환하며, 그렇지 않으면 null을 반환합니다.
function literal(prefix: string): Parser<string> {
return input =>
input.startsWith(prefix)
? { value: prefix, rest: input.slice(prefix.length) }
: null;
}
console.log(literal("ab")("abc"));조합자
조합자는 작은 파서를 받아 더 큰 파서를 만듭니다. 이처럼 조합하는 방식 때문에 간단하고 재사용 가능한 부분을 조립해 복잡한 파서를 만드는 접근법을 파서 조합자라고 부릅니다.
// Small parsers: digit, letter, literal
// Combinators: sequence, choice, many
// Compose them into: number, identifier, expression순차 실행
순차 조합자는 한 파서를 실행한 다음 남은 입력에 다른 파서를 실행하고, 그 결과를 쌍으로 묶습니다. 순서 전체가 성공하려면 두 파서가 모두 성공해야 합니다.
function seq<A, B>(pa: Parser<A>, pb: Parser<B>): Parser<[A, B]> {
return input => {
const ra = pa(input);
if (!ra) return null;
const rb = pb(ra.rest);
if (!rb) return null;
return { value: [ra.value, rb.value], rest: rb.rest };
};
}시퀀스 사용
두 리터럴을 결합하여 순서대로 파싱합니다. 결과에는 일치한 두 부분과 남은 입력이 모두 포함됩니다.
const ab = seq(literal("a"), literal("b"));
const r = ab("abc");
console.log(r); // { value: ["a","b"], rest: "c" }선택
선택 조합자는 첫 번째 파서를 시도하고, 실패하면 두 번째 파서를 시도합니다. 이를 통해 "숫자 또는 문자"와 같은 대안을 표현할 수 있습니다.
function alt<T>(p1: Parser<T>, p2: Parser<T>): Parser<T> {
return input => p1(input) ?? p2(input);
}반복
many 조합자는 파서가 실패할 때까지 파서를 반복해서 적용하고, 모든 결과를 수집합니다. 이를 사용하면 목록, digit 연속 또는 공백을 파싱할 수 있습니다.
function many<T>(p: Parser<T>): Parser<T[]> {
return input => {
const out: T[] = [];
let rest = input;
let r = p(rest);
while (r) { out.push(r.value); rest = r.rest; r = p(rest); }
return { value: out, rest };
};
}결과 매핑
map 조합자는 파서가 소비하는 내용을 바꾸지 않고 파서 결과를 변환합니다. 예를 들어 일치한 숫자 문자를 숫자로 바꿀 수 있습니다.
function map<A, B>(p: Parser<A>, f: (a: A) => B): Parser<B> {
return input => {
const r = p(input);
return r ? { value: f(r.value), rest: r.rest } : null;
};
}확장해 나가기
이 몇 가지 조합자(리터럴, 시퀀스, 대안, 반복, 매핑)만으로도 숫자, 식별자, 심지어 작은 표현식 언어와 같은 실제 문법을 파싱할 수 있습니다. 각 계층은 바로 아래 계층을 조합합니다.
const digit = alt(literal("0"), literal("1")); // toy digit
const digits = many(digit);
console.log(digits("0110x"));값에서 타입으로
핵심적인 통찰은 동일한 조합 구조가 타입 수준에서도 작동한다는 것입니다. 여기서 "입력"은 문자열 리터럴 타입이고, 파서는 템플릿 리터럴 추론을 사용하는 조건부 타입입니다. 이제 그 단계로 넘어가겠습니다.
// Value level: (input: string) => { value, rest } | null
// Type level: conditional types over string literal types타입 수준 파싱을 사용하는 이유
타입 수준 파서를 사용하면 컴파일러가 문자열 리터럴의 구조를 이해할 수 있습니다. 경로, 형식 문자열, 쿼리 키 등이 그 예입니다. 여기서 익힌 조합자에 대한 직관은 이 과정의 나머지 부분에서 다룰 타입 수준 기법에 그대로 적용됩니다.
// Goal: parse "users/:id" into { id: string } at compile time빠른 확인
파서 조합자에 대한 이해도를 테스트해 보십시오.
복습
값 수준에서 파서에 대한 직관을 익혔습니다.
- 파서는 입력을 소비하고 남은 부분과 함께 값을 반환하거나 실패합니다.
- 조합자(시퀀스, 대안, 반복, 매핑)는 작은 파서를 조합하여 큰 파서를 만듭니다.
- 동일한 구조가 타입 수준에도 적용됩니다.
다음 주제: 타입 시스템에서 문자열 분할하기
자주 묻는 질문
“파서 결합자 개념” 강의는 무료인가요?
네 — “파서 결합자 개념” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 TypeScript Academy 강의 전체를 잠금 해제할 수 있습니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“파서 결합자 개념”에서 뭘 배우나요?
작은 파서를 조합해 더 큰 파서를 만듭니다. 브라우저에서 직접 실행하는 실습 코드로 TypeScript Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
TypeScript Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 TypeScript Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“파서 결합자 개념” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 TypeScript Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 TypeScript Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.