2025. 4. 28. 20:47ㆍDart & Flutter
이번 포스트에서는 정규 표현식(Regex), XML, JSON, Tokenizer, Lexer, Parser, AST까지, 개발자라면 꼭 알아야 할 핵심 개념들을 한 번에 정리해보려 합니다.
이 개념들은 모두 ‘데이터를 표현하고 구조화하는 방법’ 혹은 '데이터를 분석하고 해석하는 과정’과 깊은 관련이 있습니다.
그럼 지금부터, 이 개념들이 어떤 역할을 하고 어떻게 연결되는지 Dart 코드 예시와 함께 살펴보며 차근차근 알아보도록 하겠습니다.
1. 정규 표현식(Regular Expression)
정규 표현식(Regex)은 문자열에서 특정한 패턴을 찾거나, 검사하거나, 치환할 때 사용하는 표현 방법입니다.
예를 들어, 이메일 주소를 검사하고 싶다면 단순히 “@“가 있는지 보는 것만으로는 부족하겠죠. 이때 정규 표현식을 사용하면 더 정확하게 조건을 설정할 수 있습니다.
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
console.log(emailRegex.test('example@email.com')); // true
console.log(emailRegex.test('hello-world')); // false
• ^ : 문자열의 시작
• [a-zA-Z0-9._%+-]+ : 영문자, 숫자, 일부 특수문자 허용
• @ : @ 기호 포함
• . : 도메인 구분
• $ : 문자열의 끝
요약: 문자열의 규칙을 검사하거나 찾는 기술
Dart에서 정규 표현식 사용하기
void main() {
String email = "test@example.com";
RegExp regex = RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$');
if (regex.hasMatch(email)) {
print("유효한 이메일입니다.");
} else {
print("유효하지 않은 이메일입니다.");
}
}
결과
유효한 이메일입니다.
✅ RegExp 클래스를 사용해서 정규 표현식을 다룰 수 있습니다.
2. XML(eXtensible Markup Language)
XML은 데이터를 구조화해서 표현할 수 있도록 만든 마크업 언어로, 데이터를 태그를 이용해서 표현하는 포멧입니다.
<person>
<name>조성은</name>
<age>23</age>
</person>
주로 데이터 저장이나 시스템 간 데이터 교환에 사용됩니다. 다만, 요즘은 무겁고 복잡하다는 이유로 JSON에 비해 덜 사용되는 추세입니다.
특징
• 사람이 읽을 수 있음
• 구조화된 데이터 표현
• 다소 무겁고 verbose(장황) 함
요약: 데이터를 태그로 구조화한 문서 형식
Flutter에서 XML 다루기
만약 Flutter에서 XML 데이터를 다뤄야 한다면, xml 패키지를 사용할 수 있어요.
dependencies:
xml: ^6.3.0
import 'package:xml/xml.dart';
void main() {
final document = XmlDocument.parse('''
<person>
<name>조성은</name>
<age>23</age>
</person>
''');
final name = document.findAllElements('name').single.text;
print('이름: $name');
}
결과
이름: 조성은
3. JSON(JavaScript Object Notation)
JSON은 JavaScript 문법을 기반으로 만든 가볍고 간단한 데이터 포맷입니다.
사람도 읽기 쉽고, 기계도 읽기 쉽습니다.
현재 Flutter에서는 서버 간 통신에서 가장 많이 쓰이는 데이터 포맷이에요.
{
"name": "조성은",
"age": 23
}
XML보다 훨씬 간결한 것을 확인할 수 있습니다.
특징
• 키-값 쌍으로 구성
• 대부분의 프로그래밍 언어에서 쉽게 읽고 쓸 수 있음
• 가볍고 빠름
요약: 가볍고 직관적인 데이터 교환 포맷
Flutter에서 JSON 다루기
import 'dart:convert';
void main() {
String jsonString = '{"name": "조성은", "age": 23}';
Map<String, dynamic> user = jsonDecode(jsonString);
print('이름: ${user['name']}');
}
결과
이름: 조성은
✅ Dart에서는 dart:convert 라이브러리를 사용해서 쉽게 jsonDecode와 jsonEncode를 사용할 수 있어요.
4. Tokenizer
Tokenizer는 긴 문자열을 토큰(Token) 이라는 작은 단위로 나누는 작업을 합니다.
예를 들어 이런 코드가 있을 때:
let x = 10;
Tokenizer는 다음처럼 쪼갤 수 있어요:
• let
• x
• =
• 10
• ;
이 조각들을 가지고 프로그래밍 언어가 “이건 변수 선언이구나”라고 이해할 수 있게 되는 것입니다.
Tokenizer 결과:
[ 'let', 'x', '=', '10', ';' ]
Tokenizer는 단순히 문장을 ‘자르기’만 합니다.
요약: 긴 문장을 의미 있는 조각으로 분해하는 첫 번째 단계
Dart로 간단한 Tokenizer 만들기
List<String> simpleTokenizer(String code) {
return code.split(RegExp(r'(\s+|;|=)')).where((token) => token.isNotEmpty).toList();
}
void main() {
String code = "let x = 10;";
List<String> tokens = simpleTokenizer(code);
print(tokens);
}
결과
[let, x, =, 10, ;]
5. Lexer
Lexer는 Tokenizer의 확장된 개념입니다
단순히 자르는 것뿐 아니라, 각 조각에 의미(토큰 타입) 를 부여합니다.
예를 들면:
| 토큰 | 타입 |
| let | 키워드 |
| x | 식별자 |
| = | 연산자 |
| 10 | 숫자 리터럴 |
| ; | 구분자 |
Lexer는 “이게 단순한 글자가 아니라 이런 의미를 가진 조각이야”라고 해석합니다.
요약: 조각에 ‘의미’까지 부여하는 과정
Dart로 간단한 Lexer 만들기
class Token {
final String type;
final String value;
Token(this.type, this.value);
@override
String toString() => '[$type: $value]';
}
List<Token> simpleLexer(String code) {
List<String> rawTokens = code.split(RegExp(r'(\s+|;|=)')).where((token) => token.isNotEmpty).toList();
return rawTokens.map((token) {
if (token == 'let') return Token('Keyword', token);
if (token == '=') return Token('Operator', token);
if (RegExp(r'^[0-9]+$').hasMatch(token)) return Token('Number', token);
return Token('Identifier', token);
}).toList();
}
void main() {
String code = "let x = 10;";
List<Token> tokens = simpleLexer(code);
print(tokens);
}
결과
[Keyword: let, Identifier: x, Operator: =, Number: 10, Identifier: ;]
6. Parser
Parser는 Lexer가 넘겨준 토큰들을 보고 전체 문법 구조를 분석하고, 이를 트리 형태로 구성합니다.
let x = 10;
이 코드가 “변수 x를 10으로 초기화하는 선언문이다”라는 구조를 이해하는 과정입니다.
Parser는 코드를 읽어 나가면서 규칙에 맞는지 검사하고, 코드의 계층적 구조(Tree 구조) 를 만들어냅니다.
요약: 토큰들을 보고 문법 구조를 이해하는 단계
Dart로 간단한 Parser 흐름 설명
void parse(List<Token> tokens) {
if (tokens.length >= 4 && tokens[0].value == 'let' && tokens[2].value == '=') {
print('변수 선언: ${tokens[1].value} = ${tokens[3].value}');
} else {
print('구문 오류!');
}
}
void main() {
String code = "let x = 10;";
List<Token> tokens = simpleLexer(code);
parse(tokens);
}
결과
변수 선언: x = 10
7. AST(Abstract Syntax Tree)
AST는 Parsing 결과로 만들어지는 트리(Tree) 구조입니다.
코드의 논리적 구조를 표현하는데 사용됩니다.
위 코드를 AST로 표현하면 이렇게 됩니다:
VariableDeclaration
├── Identifier (x)
└── NumericLiteral (10)
코드의 ‘뼈대’라고 볼 수 있어요. 이후 컴파일하거나 코드를 최적화할 때 이 트리를 기반으로 작업합니다.
이 그림은
• 변수 선언(VariableDeclaration)이 루트
• x라는 식별자(Identifier)가 하나 있고
• 10이라는 숫자 리터럴(NumericLiteral)로 초기화
한다는 걸 표현하고 있습니다.
요약: 코드의 구조를 트리 형태로 표현한 것
Dart로 간단한 AST 구조 나타내기
class ASTNode {
final String type;
final dynamic value;
final List<ASTNode> children;
ASTNode({required this.type, this.value, this.children = const []});
void printTree([int depth = 0]) {
print('${' ' * depth}$type: $value');
for (var child in children) {
child.printTree(depth + 1);
}
}
}
void main() {
ASTNode tree = ASTNode(
type: 'VariableDeclaration',
children: [
ASTNode(type: 'Identifier', value: 'x'),
ASTNode(type: 'NumericLiteral', value: 10),
],
);
tree.printTree();
}
결과
VariableDeclaration: null
Identifier: x
NumericLiteral: 10
마무리
| 개념 | 설명 |
| 정규 표현식 | 문자열 패턴을 다루는 도구 |
| XML | 태그로 데이터 구조화 |
| JSON | 간단한 데이터 포맷 |
| Tokenizer | 긴 문자열을 조각내기 |
| Lexer | 조각에 의미 부여히기 |
| Parser | 조각들을 문법적으로 해석하기 |
| AST | 해석 결과를 트리로 표현 |
전체 흐름 정리
소스 코드
↓
Tokenizer
(문자열 → 토큰 분리)
↓
Lexer
(토큰에 의미 부여)
↓
Parser
(문법 구조 분석)
↓
AST
(코드 구조를 트리로 표현)
• 정규 표현식은 문자열을 검사하는 기술
• XML/JSON은 데이터를 저장하고 교환하는 포맷
• Tokenizer → Lexer → Parser → AST는 코드를 읽어 이해하고 구조화하는 과정입니다.
정규 표현식, XML, JSON은 주로 데이터를 다루는 방법이고,
Tokenizer, Lexer, Parser, AST는 프로그래밍 언어를 이해하는 과정입니다.
위 개념들은 “문자열을 다루고”, “구조를 만들고”, “의미를 부여하는 것” 이라는 공통점으로 서로 자연스럽게 연결되어 있습니다.
'Dart & Flutter' 카테고리의 다른 글
| [Flutter] 객체지향 프로그래밍(OOP) (0) | 2025.05.14 |
|---|---|
| [Dart & Flutter] 개발자를 위한 프로세스 메모리 구조 이해 (0) | 2025.05.07 |
| [Flutter] 기초 CS 코드 풀이 #2 대기열 프로그램 (0) | 2025.04.18 |
| [Dart] 기본 문법 정리 (배열, 제너릭, 클래스, 자료구조 등) (0) | 2025.04.15 |
| [Flutter] 기초 CS 코드 풀이 #1 터미널 계산기 (0) | 2025.04.10 |