ํธ๋ฆฌ ์ํ๋ฅผ ์ํ ์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ํจํด ๋ง์คํฐํ๊ธฐ. ๋ ์ ์ฐํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ์ํด ์๊ณ ๋ฆฌ์ฆ์ ํธ๋ฆฌ ๊ตฌ์กฐ์์ ๋ถ๋ฆฌํ๋ ์ข ํฉ ๊ฐ์ด๋.
์ ์ฐํ ํธ๋ฆฌ ์ํ ์ ๊ธ ํด์ : ์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ํจํด ์ฌ์ธต ๋ถ์
์ํํธ์จ์ด ๊ณตํ์ ์ธ๊ณ์์ ์ฐ๋ฆฌ๋ ๊ณ์ธต์ , ํธ๋ฆฌ ํํ์ ๊ตฌ์กฐ๋ก ๊ตฌ์ฑ๋ ๋ฐ์ดํฐ๋ฅผ ์์ฃผ ๋ง์ฃผ์นฉ๋๋ค. ์ปดํ์ผ๋ฌ๊ฐ ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ์ถ์ ๊ตฌ๋ฌธ ํธ๋ฆฌ(AST)๋ถํฐ ์น์ ๊ตฌ๋ํ๋ ๋ฌธ์ ๊ฐ์ฒด ๋ชจ๋ธ(DOM), ๊ทธ๋ฆฌ๊ณ ๊ฐ๋จํ ํ์ผ ์์คํ ์ ์ด๋ฅด๊ธฐ๊น์ง ํธ๋ฆฌ๋ ์ด๋์๋ ์กด์ฌํฉ๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ ๋ค๋ฃฐ ๋ ๊ธฐ๋ณธ์ ์ธ ์์ ์ ๊ฐ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ์ฌ ์ด๋ค ์ฐ์ฐ์ ์ํํ๋ ์ํ์ ๋๋ค. ํ์ง๋ง ๋ฌธ์ ๋ ์ด๋ฅผ ๊น๋ํ๊ณ , ์ ์ง๋ณด์ ๊ฐ๋ฅํ๋ฉฐ, ํ์ฅ ๊ฐ๋ฅํ๊ฒ ์ํํ๋ ๊ฒ์ ๋๋ค.
์ ํต์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์ข ์ข ์ฐ์ฐ ๋ก์ง์ ๋ ธ๋ ํด๋์ค ๋ด์ ์ง์ ํฌํจ์ํต๋๋ค. ์ด๋ ํต์ฌ์ ์ธ ์ํํธ์จ์ด ์ค๊ณ ์์น์ ์๋ฐํ๋ ๋ชจ๋๋ฆฌ์์ ๊ฐํ๊ฒ ๊ฒฐํฉ๋ ์ฝ๋๋ก ์ด์ด์ง๋๋ค. ํ๋ฆฌํฐ ํ๋ฆฐํฐ๋ ์ ํจ์ฑ ๊ฒ์ฌ๊ธฐ์ ๊ฐ์ ์๋ก์ด ์ฐ์ฐ์ ์ถ๊ฐํ๋ ค๋ฉด ๋ชจ๋ ๋ ธ๋ ํด๋์ค๋ฅผ ์์ ํด์ผ ํ๋ฏ๋ก ์์คํ ์ด ์ทจ์ฝํด์ง๊ณ ์ ์ง๋ณด์๊ฐ ์ด๋ ค์์ง๋๋ค.
๊ณ ์ ์ ์ธ ๋ฐฉ๋ฌธ์ ๋์์ธ ํจํด์ ์๊ณ ๋ฆฌ์ฆ์ ๊ทธ๊ฒ์ด ์๋ํ๋ ๊ฐ์ฒด๋ก๋ถํฐ ๋ถ๋ฆฌํจ์ผ๋ก์จ ๊ฐ๋ ฅํ ํด๊ฒฐ์ฑ ์ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ณ ์ ์ ์ธ ํจํด์กฐ์ฐจ๋, ํนํ ํ์ฅ์ฑ ์ธก๋ฉด์์ ํ๊ณ๊ฐ ์์ต๋๋ค. ๋ฐ๋ก ์ด ์ง์ ์์ ์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ํจํด์ด, ํนํ ํธ๋ฆฌ ์ํ์ ์ ์ฉ๋ ๋, ์ง๊ฐ๋ฅผ ๋ฐํํฉ๋๋ค. ์ ๋ค๋ฆญ, ํ ํ๋ฆฟ, ๋ฒ ๋ฆฌ์ธํธ์ ๊ฐ์ ํ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ์ฐ๋ฆฌ๋ ๋ชจ๋ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ๋งค์ฐ ์ ์ฐํ๊ณ , ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉฐ, ๊ฐ๋ ฅํ ์์คํ ์ ๋ง๋ค ์ ์์ต๋๋ค.
์ด ์ฌ์ธต ๋ถ์์ ๊ณ ์ ์ ์ธ ๋ฐฉ๋ฌธ์ ํจํด์์ ์ ๊ตํ ์ ๋ค๋ฆญ ๊ตฌํ์ผ๋ก ๋์๊ฐ๋ ์ฌ์ ์ ์๋ดํ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๋ ๋ค์์ ํ๊ตฌํ ๊ฒ์ ๋๋ค:
- ๊ณ ์ ์ ์ธ ๋ฐฉ๋ฌธ์ ํจํด๊ณผ ๊ทธ ๋ด์ฌ๋ ๋ฌธ์ ์ ์ ๋ํ ๋ณต์ต.
- ์ฐ์ฐ์ ๋์ฑ ๋ถ๋ฆฌํ๋ ์ ๋ค๋ฆญ ์ ๊ทผ ๋ฐฉ์์ผ๋ก์ ์งํ.
- ์ ๋ค๋ฆญ ํธ๋ฆฌ ์ํ ๋ฐฉ๋ฌธ์์ ์์ธํ ๋จ๊ณ๋ณ ๊ตฌํ.
- ์ํ ๋ก์ง๊ณผ ์ฐ์ฐ ๋ก์ง์ ๋ถ๋ฆฌํ๋ ๊ฒ์ ์ฌ์คํ ์ด์ .
- ์ด ํจํด์ด ์์ฒญ๋ ๊ฐ์น๋ฅผ ์ ๊ณตํ๋ ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์ฌ๋ก.
์ปดํ์ผ๋ฌ, ์ ์ ๋ถ์ ๋๊ตฌ, UI ํ๋ ์์ํฌ ๋๋ ๋ณต์กํ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์์กดํ๋ ๋ชจ๋ ์์คํ ์ ๊ตฌ์ถํ๊ณ ์๋ค๋ฉด, ์ด ํจํด์ ๋ง์คํฐํ๋ ๊ฒ์ ์ฌ๋ฌ๋ถ์ ์ํคํ ์ฒ์ ์ฌ๊ณ ์ ์ฝ๋์ ํ์ง์ ํ ๋จ๊ณ ๋์ด์ฌ๋ฆด ๊ฒ์ ๋๋ค.
๊ณ ์ ์ ์ธ ๋ฐฉ๋ฌธ์ ํจํด ๋ค์ ๋ณด๊ธฐ
์ ๋ค๋ฆญ ์งํ๋ฅผ ์ดํดํ๊ธฐ ์ ์, ๊ทธ ๊ธฐ๋ฐ์ ํ์คํ ๋ค์ ธ์ผ ํฉ๋๋ค. "Gang of Four(GoF)"๊ฐ ๊ทธ๋ค์ ๊ธฐ๋ ๋น์ ์ธ ์ ์ Design Patterns: Elements of Reusable Object-Oriented Software์์ ์ค๋ช ํ ๋ฐฉ๋ฌธ์ ํจํด์, ๊ธฐ์กด ๊ฐ์ฒด ๊ตฌ์กฐ๋ฅผ ์์ ํ์ง ์๊ณ ๋ ์๋ก์ด ์ฐ์ฐ์ ์ถ๊ฐํ ์ ์๊ฒ ํด์ฃผ๋ ํ๋ ํจํด์ ๋๋ค.
ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์
NumberNode(๋ฆฌํฐ๋ด ๊ฐ)์ AdditionNode(๋ ํ์ ํํ์์ ๋ง์ ์ ๋ํ๋)์ ๊ฐ์ ๋ค์ํ ๋ ธ๋ ์ ํ์ผ๋ก ๊ตฌ์ฑ๋ ๊ฐ๋จํ ์ฐ์ ํํ์ ํธ๋ฆฌ๊ฐ ์๋ค๊ณ ์์ํด ๋ด ์๋ค. ์ด ํธ๋ฆฌ์ ๋ํด ์ฌ๋ฌ ๊ฐ์ง ๋ค๋ฅธ ์ฐ์ฐ์ ์ํํ๊ณ ์ถ์ ์ ์์ต๋๋ค:
- ํ๊ฐ(Evaluation): ํํ์์ ์ต์ข ์ซ์ ๊ฒฐ๊ณผ๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- ํ๋ฆฌํฐ ํ๋ฆฐํ (Pretty Printing): "(5 + 3)"๊ณผ ๊ฐ์ด ์ฌ๋์ด ์ฝ๊ธฐ ์ฌ์ด ๋ฌธ์์ด ํํ์ ์์ฑํฉ๋๋ค.
- ํ์ ๊ฒ์ฌ(Type Checking): ๊ด๋ จ๋ ํ์ ์ ๋ํด ์ฐ์ฐ์ด ์ ํจํ์ง ํ์ธํฉ๋๋ค.
์์งํ ์ ๊ทผ ๋ฐฉ์์ `evaluate()`, `print()`, `typeCheck()`์ ๊ฐ์ ๋ฉ์๋๋ฅผ ๊ธฐ๋ณธ `Node` ํด๋์ค์ ์ถ๊ฐํ๊ณ ๊ฐ ๊ตฌ์ฒด์ ์ธ ๋ ธ๋ ํด๋์ค์์ ์ด๋ฅผ ์ฌ์ ์ํ๋ ๊ฒ์ ๋๋ค. ์ด๋ ๋ ธ๋ ํด๋์ค๋ฅผ ๊ด๋ จ ์๋ ๋ก์ง์ผ๋ก ๋น๋ํ๊ฒ ๋ง๋ญ๋๋ค. ์๋ก์ด ์ฐ์ฐ์ ๋ง๋ค ๋๋ง๋ค ๊ณ์ธต ๊ตฌ์กฐ์ ๋ชจ๋ ๋จ์ผ ๋ ธ๋ ํด๋์ค๋ฅผ ๊ฑด๋๋ ค์ผ ํฉ๋๋ค. ์ด๋ ์ํํธ์จ์ด ๊ฐ์ฒด๋ ํ์ฅ์ ๋ํด์๋ ์ด๋ ค ์์ด์ผ ํ์ง๋ง ์์ ์ ๋ํด์๋ ๋ซํ ์์ด์ผ ํ๋ค๋ ๊ฐ๋ฐฉ-ํ์ ์์น(Open/Closed Principle)์ ์๋ฐํฉ๋๋ค.
๊ณ ์ ์ ์ธ ํด๊ฒฐ์ฑ : ์ด์ค ๋์คํจ์น(Double Dispatch)
๋ฐฉ๋ฌธ์ ํจํด์ Visitor ๊ณ์ธต๊ณผ Element ๊ณ์ธต(์ฐ๋ฆฌ์ ๋ ธ๋)์ด๋ผ๋ ๋ ๊ฐ์ ์๋ก์ด ๊ณ์ธต์ ๋์ ํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๋ง๋ฒ์ ์ด์ค ๋์คํจ์น๋ผ๊ณ ๋ถ๋ฆฌ๋ ๊ธฐ์ ์ ์์ต๋๋ค.
ํต์ฌ ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- Element ์ธํฐํ์ด์ค (์: `Node`): `accept(Visitor v)` ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค.
- ๊ตฌ์ฒด์ ์ธ Element (์: `NumberNode`, `AdditionNode`): `accept` ๋ฉ์๋๋ฅผ ๊ตฌํํฉ๋๋ค. ๊ตฌํ์ ๊ฐ๋จํฉ๋๋ค: `visitor.visit(this);`.
- Visitor ์ธํฐํ์ด์ค: ๊ฐ๊ฐ์ ๊ตฌ์ฒด์ ์ธ element ์ ํ์ ๋ํด ์ค๋ฒ๋ก๋๋ `visit` ๋ฉ์๋๋ฅผ ์ ์ธํฉ๋๋ค. ์๋ฅผ ๋ค์ด, `visit(NumberNode n)`์ `visit(AdditionNode n)`.
- ๊ตฌ์ฒด์ ์ธ Visitor (์: `EvaluationVisitor`, `PrintVisitor`): ํน์ ์ฐ์ฐ์ ์ํํ๊ธฐ ์ํด `visit` ๋ฉ์๋๋ค์ ๊ตฌํํฉ๋๋ค.
์๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค: `node.accept(myVisitor)`๋ฅผ ํธ์ถํฉ๋๋ค. `accept` ๋ด๋ถ์์, ๋ ธ๋๋ `myVisitor.visit(this)`๋ฅผ ํธ์ถํฉ๋๋ค. ์ด ์์ ์์ ์ปดํ์ผ๋ฌ๋ `this`์ ๊ตฌ์ฒด์ ์ธ ํ์ (์: `AdditionNode`)๊ณผ `myVisitor`์ ๊ตฌ์ฒด์ ์ธ ํ์ (์: `EvaluationVisitor`)์ ์๊ณ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ฌ๋ฐ๋ฅธ `visit` ๋ฉ์๋์ธ `EvaluationVisitor::visit(AdditionNode*)`๋ก ๋์คํจ์นํ ์ ์์ต๋๋ค. ์ด ๋ ๋จ๊ณ์ ํธ์ถ์ ๋จ์ผ ๊ฐ์ ํจ์ ํธ์ถ๋ก๋ ํ ์ ์๋ ๊ฒ, ์ฆ ๋ ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฐํ์ ํ์ ์ ๊ธฐ๋ฐํ์ฌ ์ฌ๋ฐ๋ฅธ ๋ฉ์๋๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ ๋ฌ์ฑํฉ๋๋ค.
๊ณ ์ ์ ์ธ ํจํด์ ํ๊ณ
์ฐ์ํ์ง๋ง, ๊ณ ์ ์ ์ธ ๋ฐฉ๋ฌธ์ ํจํด์ ์งํํ๋ ์์คํ ์์์ ์ฌ์ฉ์ ๋ฐฉํดํ๋ ์ค์ํ ๋จ์ ์ ๊ฐ์ง๊ณ ์์ต๋๋ค: element ๊ณ์ธต์ ๊ฒฝ์ง์ฑ์ ๋๋ค.
`Visitor` ์ธํฐํ์ด์ค๋ ๋ชจ๋ `ConcreteElement` ํ์ ์ ๋ํ `visit` ๋ฉ์๋๋ฅผ ํฌํจํฉ๋๋ค. ๋ง์ฝ `MultiplicationNode`์ ๊ฐ์ ์๋ก์ด ๋ ธ๋ ํ์ ์ ์ถ๊ฐํ๊ณ ์ถ๋ค๋ฉด, ๊ธฐ๋ณธ `Visitor` ์ธํฐํ์ด์ค์ ์๋ก์ด `visit(MultiplicationNode n)` ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค. ์ด๋ก ์ธํด ์์คํ ์ ์กด์ฌํ๋ ๋ชจ๋ ๋จ์ผ ๊ตฌ์ฒด์ ์ธ visitor ํด๋์ค๋ฅผ ์ ๋ฐ์ดํธํ์ฌ ์ด ์๋ก์ด ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค. ์๋ก์ด ์ฐ์ฐ์ ์ถ๊ฐํ ๋ ํด๊ฒฐํ๋ ๋ฐ๋ก ๊ทธ ๋ฌธ์ ๊ฐ ์๋ก์ด element ํ์ ์ ์ถ๊ฐํ ๋ ๋ค์ ๋ํ๋ฉ๋๋ค. ์์คํ ์ ์ฐ์ฐ ์ธก๋ฉด์์๋ ์์ ์ ๋ซํ ์์ง๋ง, element ์ธก๋ฉด์์๋ ํ์ง ์ด๋ ค ์์ต๋๋ค.
element ๊ณ์ธต๊ณผ visitor ๊ณ์ธต ์ฌ์ด์ ์ด๋ฌํ ์ํ ์์กด์ฑ์ ๋ ์ ์ฐํ๊ณ ์ ๋ค๋ฆญํ ํด๊ฒฐ์ฑ ์ ์ฐพ๊ฒ ํ๋ ์ฃผ๋ ๋๊ธฐ์ ๋๋ค.
์ ๋ค๋ฆญ ์งํ: ๋ ์ ์ฐํ ์ ๊ทผ ๋ฐฉ์
๊ณ ์ ์ ์ธ ํจํด์ ํต์ฌ ํ๊ณ๋ visitor ์ธํฐํ์ด์ค์ ๊ตฌ์ฒด์ ์ธ element ํ์ ๊ฐ์ ์ ์ , ์ปดํ์ผ ํ์ ๊ฒฐํฉ์ ๋๋ค. ์ ๋ค๋ฆญ ์ ๊ทผ ๋ฐฉ์์ ์ด ๊ฒฐํฉ์ ๋์ผ๋ ค๊ณ ํฉ๋๋ค. ํต์ฌ ์์ด๋์ด๋ ์ฌ๋ฐ๋ฅธ ์ฒ๋ฆฌ ๋ก์ง์ผ๋ก ๋์คํจ์นํ๋ ์ฑ ์์ ์ค๋ฒ๋ก๋๋ ๋ฉ์๋๋ค์ ๊ฒฝ์ง๋ ์ธํฐํ์ด์ค์์ ๋ฒ์ด๋๊ฒ ํ๋ ๊ฒ์ ๋๋ค.
๊ฐ๋ ฅํ ํ ํ๋ฆฟ ๋ฉํํ๋ก๊ทธ๋๋ฐ๊ณผ `std::variant`์ ๊ฐ์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ธฐ๋ฅ์ ๊ฐ์ถ ํ๋ C++๋ ์ด๋ฅผ ๊ตฌํํ๋ ๋งค์ฐ ๊น๋ํ๊ณ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. C#์ด๋ Java์ ๊ฐ์ ์ธ์ด์์๋ ๋ฆฌํ๋ ์ ์ด๋ ์ ๋ค๋ฆญ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฌํ ์ ๊ทผ ๋ฐฉ์์ ๋ฌ์ฑํ ์ ์์ง๋ง, ์ ์ฌ์ ์ธ ์ฑ๋ฅ ์ ํ๊ฐ ์์ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ์ ๋ชฉํ๋ ๋ค์๊ณผ ๊ฐ์ ์์คํ ์ ๊ตฌ์ถํ๋ ๊ฒ์ ๋๋ค:
- ์๋ก์ด ๋ ธ๋ ํ์ ์ ์ถ๊ฐํ๋ ๊ฒ์ด ๊ตญ์ํ๋๊ณ ๋ชจ๋ ๊ธฐ์กด visitor ๊ตฌํ์ ๊ฑธ์ณ ์ฐ์์ ์ธ ๋ณ๊ฒฝ์ ์๊ตฌํ์ง ์์ต๋๋ค.
- ์๋ก์ด ์ฐ์ฐ์ ์ถ๊ฐํ๋ ๊ฒ์ด ๋ฐฉ๋ฌธ์ ํจํด์ ์๋ ๋ชฉํ์ ์ผ์นํ๊ฒ ๊ฐ๋จํ๊ฒ ์ ์ง๋ฉ๋๋ค.
- ์ํ ๋ก์ง ์์ฒด(์: ์ ์, ํ์ ์ํ)๊ฐ ์ ๋ค๋ฆญํ๊ฒ ์ ์๋์ด ์ด๋ค ์ฐ์ฐ์๋ ์ฌ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
์ด ์ธ ๋ฒ์งธ ์ ์ด ์ฐ๋ฆฌ์ "ํธ๋ฆฌ ์ํ ํ์ ๊ตฌํ"์ ํต์ฌ์ ๋๋ค. ์ฐ๋ฆฌ๋ ์ฐ์ฐ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์์ ๋ถ๋ฆฌํ ๋ฟ๋ง ์๋๋ผ, ์ํํ๋ ํ์์ ์ฐ์ฐํ๋ ํ์๋ ๋ถ๋ฆฌํ ๊ฒ์ ๋๋ค.
C++์์ ํธ๋ฆฌ ์ํ๋ฅผ ์ํ ์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ๊ตฌํํ๊ธฐ
์ฐ๋ฆฌ๋ ํ๋ C++(C++17 ์ด์)์ ์ฌ์ฉํ์ฌ ์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ํ๋ ์์ํฌ๋ฅผ ๊ตฌ์ถํ ๊ฒ์ ๋๋ค. `std::variant`, `std::unique_ptr`, ๊ทธ๋ฆฌ๊ณ ํ ํ๋ฆฟ์ ์กฐํฉ์ ํ์ ์์ ํ๊ณ , ํจ์จ์ ์ด๋ฉฐ, ๋งค์ฐ ํํ๋ ฅ์ด ํ๋ถํ ํด๊ฒฐ์ฑ ์ ์ ๊ณตํฉ๋๋ค.
1๋จ๊ณ: ํธ๋ฆฌ ๋ ธ๋ ๊ตฌ์กฐ ์ ์ํ๊ธฐ
๋จผ์ , ๋ ธ๋ ํ์ ์ ์ ์ํด ๋ด ์๋ค. ๊ฐ์ `accept` ๋ฉ์๋๋ฅผ ๊ฐ์ง ์ ํต์ ์ธ ์์ ๊ณ์ธต ๋์ , ์ฐ๋ฆฌ๋ ๋ ธ๋๋ฅผ ๊ฐ๋จํ ๊ตฌ์กฐ์ฒด๋ก ์ ์ํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฐ ๋ค์ `std::variant`๋ฅผ ์ฌ์ฉํ์ฌ ์ฐ๋ฆฌ์ ๋ ธ๋ ํ์ ์ค ์ด๋ ๊ฒ์ด๋ ๋ด์ ์ ์๋ ํฉ ํ์ (sum type)์ ๋ง๋ค ๊ฒ์ ๋๋ค.
์ฌ๊ท์ ์ธ ๊ตฌ์กฐ(๋ ธ๋๊ฐ ๋ค๋ฅธ ๋ ธ๋๋ฅผ ํฌํจํ๋ ํธ๋ฆฌ)๋ฅผ ํ์ฉํ๊ธฐ ์ํด, ๊ฐ์ ์ฐธ์กฐ ๊ณ์ธต์ด ํ์ํฉ๋๋ค. `Node` ๊ตฌ์กฐ์ฒด๋ variant๋ฅผ ๊ฐ์ธ๊ณ ์์ ๋ ธ๋๋ฅผ ์ํด `std::unique_ptr`๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค.
ํ์ผ: `Nodes.h`
#include <memory> #include <variant> #include <vector> // ๋ฉ์ธ Node ๋ํผ๋ฅผ ์ ๋ฐฉ ์ ์ธ struct Node; // ๊ตฌ์ฒด์ ์ธ ๋ ธ๋ ํ์ ์ ๊ฐ๋จํ ๋ฐ์ดํฐ ์งํฉ์ผ๋ก ์ ์ struct NumberNode { double value; }; struct BinaryOpNode { enum class Operator { Add, Subtract, Multiply, Divide }; Operator op; std::unique_ptr<Node> left; std::unique_ptr<Node> right; }; struct UnaryOpNode { enum class Operator { Negate }; Operator op; std::unique_ptr<Node> operand; }; // std::variant๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋ฅํ ๋ชจ๋ ๋ ธ๋ ํ์ ์ ํฉ ํ์ ์ ์์ฑ using NodeVariant = std::variant<NumberNode, BinaryOpNode, UnaryOpNode>; // variant๋ฅผ ๊ฐ์ธ๋ ๋ฉ์ธ Node ๊ตฌ์กฐ์ฒด struct Node { NodeVariant var; };
์ด ๊ตฌ์กฐ๋ ์ด๋ฏธ ํฐ ๊ฐ์ ์ ๋๋ค. ๋ ธ๋ ํ์ ์ ๊ฐ๋จํ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ฒด(plain old data structs)์ ๋๋ค. ๊ทธ๋ค์ ๋ฐฉ๋ฌธ์๋ ์ด๋ค ์ฐ์ฐ์ ๋ํด์๋ ์์ง ๋ชปํฉ๋๋ค. `FunctionCallNode`๋ฅผ ์ถ๊ฐํ๋ ค๋ฉด, ๋จ์ํ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํ๊ณ `NodeVariant` ๋ณ์นญ์ ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค. ์ด๊ฒ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ ์์ฒด์ ๋ํ ๋จ์ผ ์์ ์ง์ ์ ๋๋ค.
2๋จ๊ณ: `std::visit`๋ก ์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ๋ง๋ค๊ธฐ
`std::visit` ์ ํธ๋ฆฌํฐ๋ ์ด ํจํด์ ์ด์์ ๋๋ค. ์ด๊ฒ์ ํธ์ถ ๊ฐ๋ฅํ ๊ฐ์ฒด(ํจ์, ๋๋ค ๋๋ `operator()`๋ฅผ ๊ฐ์ง ๊ฐ์ฒด ๋ฑ)์ `std::variant`๋ฅผ ์ธ์๋ก ๋ฐ์, variant์์ ํ์ฌ ํ์ฑํ๋ ํ์ ์ ๋ฐ๋ผ ํธ์ถ ๊ฐ๋ฅํ ๊ฐ์ฒด์ ์ฌ๋ฐ๋ฅธ ์ค๋ฒ๋ก๋๋ฅผ ํธ์ถํฉ๋๋ค. ์ด๊ฒ์ด ์ฐ๋ฆฌ์ ํ์ ์์ ํ, ์ปดํ์ผ ํ์ ์ด์ค ๋์คํจ์น ๋ฉ์ปค๋์ฆ์ ๋๋ค.
์ด์ ๋ฐฉ๋ฌธ์๋ variant์ ๊ฐ ํ์ ์ ๋ํด ์ค๋ฒ๋ก๋๋ `operator()`๋ฅผ ๊ฐ์ง ๊ตฌ์กฐ์ฒด์ผ ๋ฟ์ ๋๋ค.
์ด๊ฒ์ด ์ค์ ๋ก ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ณด๊ธฐ ์ํด ๊ฐ๋จํ ํ๋ฆฌํฐ ํ๋ฆฐํฐ ๋ฐฉ๋ฌธ์๋ฅผ ๋ง๋ค์ด ๋ด ์๋ค.
ํ์ผ: `PrettyPrinter.h`
#include "Nodes.h" #include <string> #include <iostream> struct PrettyPrinter { // NumberNode์ ๋ํ ์ค๋ฒ๋ก๋ void operator()(const NumberNode& node) const { std::cout << node.value; } // UnaryOpNode์ ๋ํ ์ค๋ฒ๋ก๋ void operator()(const UnaryOpNode& node) const { std::cout << "(-"; std::visit(*this, node.operand->var); // ์ฌ๊ท์ ๋ฐฉ๋ฌธ std::cout << ")"; } // BinaryOpNode์ ๋ํ ์ค๋ฒ๋ก๋ void operator()(const BinaryOpNode& node) const { std::cout << "("; std::visit(*this, node.left->var); // ์ฌ๊ท์ ๋ฐฉ๋ฌธ switch (node.op) { case BinaryOpNode::Operator::Add: std::cout << " + "; break; case BinaryOpNode::Operator::Subtract: std::cout << " - "; break; case BinaryOpNode::Operator::Multiply: std::cout << " * "; break; case BinaryOpNode::Operator::Divide: std::cout << " / "; break; } std::visit(*this, node.right->var); // ์ฌ๊ท์ ๋ฐฉ๋ฌธ std::cout << ")"; } };
์ฌ๊ธฐ์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ฃผ๋ชฉํ์ญ์์ค. ์ํ ๋ก์ง(์์ ๋ฐฉ๋ฌธ)๊ณผ ์ฐ์ฐ ๋ก์ง(๊ดํธ์ ์ฐ์ฐ์ ์ถ๋ ฅ)์ด `PrettyPrinter` ๋ด๋ถ์ ํจ๊ป ์์ฌ ์์ต๋๋ค. ์ด๊ฒ์ ๊ธฐ๋ฅ์ ์ผ๋ก๋ ๋ฌธ์ ์์ง๋ง, ์ฐ๋ฆฌ๋ ๋ ์ํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋ฌด์์ ํ ๊ฒ์ธ๊ฐ์ ์ด๋ป๊ฒ ํ ๊ฒ์ธ๊ฐ๋ฅผ ๋ถ๋ฆฌํ ์ ์์ต๋๋ค.
3๋จ๊ณ: ์ฃผ์ธ๊ณต์ ๋ฑ์ฅ - ์ ๋ค๋ฆญ ํธ๋ฆฌ ์ํ ๋ฐฉ๋ฌธ์
์ด์ , ์ฐ๋ฆฌ๋ ํต์ฌ ๊ฐ๋ ์ ๋์ ํฉ๋๋ค: ์ํ ์ ๋ต์ ์บก์ํํ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ `TreeWalker`์ ๋๋ค. ์ด `TreeWalker`๋ ๊ทธ ์์ฒด๋ก ๋ฐฉ๋ฌธ์์ด์ง๋ง, ์ ์ผํ ์๋ฌด๋ ํธ๋ฆฌ๋ฅผ ์ํํ๋ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ์ํ ์ค ํน์ ์ง์ ์์ ์คํ๋๋ ๋ค๋ฅธ ํจ์๋ค(๋๋ค ๋๋ ํจ์ ๊ฐ์ฒด)์ ์ธ์๋ก ๋ฐ์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋ค๋ฅธ ์ ๋ต๋ค์ ์ง์ํ ์ ์์ง๋ง, ์ผ๋ฐ์ ์ด๊ณ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ ์ค ํ๋๋ "์ฌ์ ๋ฐฉ๋ฌธ(pre-visit)"(์์๋ค์ ๋ฐฉ๋ฌธํ๊ธฐ ์ )๊ณผ "์ฌํ ๋ฐฉ๋ฌธ(post-visit)"(์์๋ค์ ๋ฐฉ๋ฌธํ ํ)์ ์ํ ํ (hook)์ ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ์ ์(pre-order) ๋ฐ ํ์(post-order) ์ํ ์์ ์ ์ง์ ์ ์ผ๋ก ๋์๋ฉ๋๋ค.
ํ์ผ: `TreeWalker.h`
#include "Nodes.h" #include <functional> template <typename PreVisitAction, typename PostVisitAction> struct TreeWalker { PreVisitAction pre_visit; PostVisitAction post_visit; // ์์์ด ์๋ ๋ ธ๋(๋จ๋ง ๋ ธ๋)์ ๋ํ ๊ธฐ๋ณธ ์ผ์ด์ค void operator()(const NumberNode& node) { pre_visit(node); post_visit(node); } // ์์์ด ํ๋์ธ ๋ ธ๋์ ๋ํ ์ผ์ด์ค void operator()(const UnaryOpNode& node) { pre_visit(node); std::visit(*this, node.operand->var); // ์ฌ๊ท post_visit(node); } // ์์์ด ๋์ธ ๋ ธ๋์ ๋ํ ์ผ์ด์ค void operator()(const BinaryOpNode& node) { pre_visit(node); std::visit(*this, node.left->var); // ์ผ์ชฝ ์ฌ๊ท std::visit(*this, node.right->var); // ์ค๋ฅธ์ชฝ ์ฌ๊ท post_visit(node); } }; // ์์ปค ์์ฑ์ ๋ ์ฝ๊ฒ ๋ง๋ค์ด์ฃผ๋ ํฌํผ ํจ์ template <typename Pre, typename Post> auto make_tree_walker(Pre pre, Post post) { return TreeWalker<Pre, Post>{pre, post}; }
์ด `TreeWalker`๋ ๋ถ๋ฆฌ์ ๊ฑธ์์ ๋๋ค. ์ด๊ฒ์ ์ถ๋ ฅ, ํ๊ฐ, ๋๋ ํ์ ๊ฒ์ฌ์ ๋ํด ์๋ฌด๊ฒ๋ ๋ชจ๋ฆ ๋๋ค. ๊ทธ๊ฒ์ ์ ์ผํ ๋ชฉ์ ์ ํธ๋ฆฌ์ ๊น์ด ์ฐ์ ์ํ๋ฅผ ์ํํ๊ณ ์ ๊ณต๋ ํ ์ ํธ์ถํ๋ ๊ฒ์ ๋๋ค. `pre_visit` ์ก์ ์ ์ ์ ์์๋ก ์คํ๋๊ณ , `post_visit` ์ก์ ์ ํ์ ์์๋ก ์คํ๋ฉ๋๋ค. ์ฌ์ฉ์๋ ์ด๋ค ๋๋ค๋ฅผ ๊ตฌํํ ์ง ์ ํํจ์ผ๋ก์จ ๋ชจ๋ ์ข ๋ฅ์ ์ฐ์ฐ์ ์ํํ ์ ์์ต๋๋ค.
4๋จ๊ณ: ๊ฐ๋ ฅํ๊ณ ๋ถ๋ฆฌ๋ ์ฐ์ฐ์ ์ํด `TreeWalker` ์ฌ์ฉํ๊ธฐ
์ด์ , `PrettyPrinter`๋ฅผ ๋ฆฌํฉํ ๋งํ๊ณ ์๋ก์ด ์ ๋ค๋ฆญ `TreeWalker`๋ฅผ ์ฌ์ฉํ์ฌ `EvaluationVisitor`๋ฅผ ๋ง๋ค์ด ๋ด ์๋ค. ์ฐ์ฐ ๋ก์ง์ ์ด์ ๊ฐ๋จํ ๋๋ค๋ก ํํ๋ ๊ฒ์ ๋๋ค.
ํ๊ฐ ์คํ๊ณผ ๊ฐ์ ์ํ๋ฅผ ๋๋ค ํธ์ถ ๊ฐ์ ์ ๋ฌํ๊ธฐ ์ํด, ๋ณ์๋ฅผ ์ฐธ์กฐ๋ก ์บก์ฒํ ์ ์์ต๋๋ค.
ํ์ผ: `main.cpp`
#include "Nodes.h" #include "TreeWalker.h" #include <iostream> #include <string> #include <vector> // ๋ชจ๋ ๋ ธ๋ ํ์ ์ ์ฒ๋ฆฌํ ์ ์๋ ์ ๋ค๋ฆญ ๋๋ค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ํฌํผ template<class... Ts> struct Overloaded : Ts... { using Ts::operator()...; }; template<class... Ts> Overloaded(Ts...) -> Overloaded<Ts...>; int main() { // ํํ์ (5 + (10 * 2))์ ๋ํ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ถํด ๋ด ์๋ค auto num5 = std::make_unique<Node>(Node{NumberNode{5.0}}); auto num10 = std::make_unique<Node>(Node{NumberNode{10.0}}); auto num2 = std::make_unique<Node>(Node{NumberNode{2.0}}); auto mult = std::make_unique<Node>(Node{BinaryOpNode{ BinaryOpNode::Operator::Multiply, std::move(num10), std::move(num2) }}); auto root = std::make_unique<Node>(Node{BinaryOpNode{ BinaryOpNode::Operator::Add, std::move(num5), std::move(mult) }}); std::cout << "--- ํ๋ฆฌํฐ ํ๋ฆฐํ ์ฐ์ฐ ---\n"; auto printer_pre_visit = Overloaded { [](const NumberNode& node) { std::cout << node.value; }, [](const UnaryOpNode&) { std::cout << "(-"; }, [](const BinaryOpNode&) { std::cout << "("; } }; auto printer_post_visit = Overloaded { [](const NumberNode&) {}, // ์๋ฌด๊ฒ๋ ์ ํจ [](const UnaryOpNode&) { std::cout << ")"; }, [](const BinaryOpNode& node) { switch (node.op) { case BinaryOpNode::Operator::Add: std::cout << " + "; break; case BinaryOpNode::Operator::Subtract: std::cout << " - "; break; case BinaryOpNode::Operator::Multiply: std::cout << " * "; break; case BinaryOpNode::Operator::Divide: std::cout << " / "; break; } } }; // ์์ ๋ ธ๋๊ฐ ์ฌ์ ๋ฐฉ๋ฌธ๊ณผ ์ฌํ ๋ฐฉ๋ฌธ ์ฌ์ด์ ๋ฐฉ๋ฌธ๋๋ฏ๋ก ์ด ๋ฐฉ๋ฒ์ ์๋ํ์ง ์์ต๋๋ค. // ์ค์ ์ํ ์ถ๋ ฅ์ ์ํด ์์ปค๋ฅผ ๋ ์ ์ฐํ๊ฒ ๊ฐ์ ํด ๋ด ์๋ค. // ํ๋ฆฌํฐ ํ๋ฆฐํ ์ ์ํ ๋ ๋์ ์ ๊ทผ ๋ฐฉ์์ "์ค๊ฐ ๋ฐฉ๋ฌธ(in-visit)" ํ ์ ๋๋ ๊ฒ์ ๋๋ค. // ๋จ์ํ๋ฅผ ์ํด, ์ถ๋ ฅ ๋ก์ง์ ์ฝ๊ฐ ์ฌ๊ตฌ์ฑํด ๋ด ์๋ค. // ํน์ ๋ ์ข๊ฒ๋, ์ ์ฉ PrintWalker๋ฅผ ๋ง๋ญ์๋ค. ์ง๊ธ์ ์ฌ์ /์ฌํ ๋ฐฉ๋ฌธ ๋ฐฉ์์ ์ ์งํ๊ณ ๋ ์ ํฉํ ํ๊ฐ ์์ ๋ฅผ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค. std::cout << "\n--- ํ๊ฐ ์ฐ์ฐ ---\n"; std::vector<double> eval_stack; auto eval_pre_visit = [](const auto&){}; // ์ฌ์ ๋ฐฉ๋ฌธ ์ ์๋ฌด๊ฒ๋ ์ ํจ auto eval_post_visit = Overloaded { [&](const NumberNode& node) { eval_stack.push_back(node.value); }, [&](const UnaryOpNode& node) { double operand = eval_stack.back(); eval_stack.pop_back(); eval_stack.push_back(-operand); }, [&](const BinaryOpNode& node) { double right = eval_stack.back(); eval_stack.pop_back(); double left = eval_stack.back(); eval_stack.pop_back(); switch(node.op) { case BinaryOpNode::Operator::Add: eval_stack.push_back(left + right); break; case BinaryOpNode::Operator::Subtract: eval_stack.push_back(left - right); break; case BinaryOpNode::Operator::Multiply: eval_stack.push_back(left * right); break; case BinaryOpNode::Operator::Divide: eval_stack.push_back(left / right); break; } } }; auto evaluator = make_tree_walker(eval_pre_visit, eval_post_visit); std::visit(evaluator, root->var); std::cout << "ํ๊ฐ ๊ฒฐ๊ณผ: " << eval_stack.back() << std::endl; return 0; }
ํ๊ฐ ๋ก์ง์ ๋ณด์ญ์์ค. ํ์ ์ํ์ ์๋ฒฝํ๊ฒ ๋ค์ด๋ง์ต๋๋ค. ์ฐ๋ฆฌ๋ ์์ ๋ ธ๋๋ค์ ๊ฐ์ด ๊ณ์ฐ๋์ด ์คํ์ ํธ์๋ ํ์๋ง ์ฐ์ฐ์ ์ํํฉ๋๋ค. `eval_post_visit` ๋๋ค๋ `eval_stack`์ ์บก์ฒํ๊ณ ํ๊ฐ์ ๋ํ ๋ชจ๋ ๋ก์ง์ ํฌํจํฉ๋๋ค. ์ด ๋ก์ง์ ๋ ธ๋ ์ ์ ๋ฐ `TreeWalker`์ ์์ ํ ๋ถ๋ฆฌ๋์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ(๋ ธ๋), ์ํ ์๊ณ ๋ฆฌ์ฆ(`TreeWalker`), ๊ทธ๋ฆฌ๊ณ ์ฐ์ฐ ๋ก์ง(๋๋ค)์ด๋ผ๋ ์๋ฆ๋ค์ด 3๋ฐฉํฅ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ๋ฅผ ๋ฌ์ฑํ์ต๋๋ค.
์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ์ ๊ทผ ๋ฐฉ์์ ์ด์
์ด ๊ตฌํ ์ ๋ต์ ํนํ ๋๊ท๋ชจ, ์ฅ๊ธฐ ์ํํธ์จ์ด ํ๋ก์ ํธ์์ ์๋นํ ์ด์ ์ ์ ๊ณตํฉ๋๋ค.
๋น๊ตํ ์ ์๋ ์ ์ฐ์ฑ๊ณผ ํ์ฅ์ฑ
์ด๊ฒ์ด ์ฃผ๋ ์ด์ ์ ๋๋ค. ์๋ก์ด ์ฐ์ฐ์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ฐ๋จํฉ๋๋ค. ์๋ก์ด ๋๋ค ์ธํธ๋ฅผ ์์ฑํ๊ณ `TreeWalker`์ ์ ๋ฌํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ๊ธฐ์กด ์ฝ๋๋ ์ ํ ๊ฑด๋๋ฆฌ์ง ์์ต๋๋ค. ์ด๊ฒ์ ๊ฐ๋ฐฉ-ํ์ ์์น์ ์๋ฒฝํ๊ฒ ์ค์ํฉ๋๋ค. ์๋ก์ด ๋ ธ๋ ํ์ ์ ์ถ๊ฐํ๋ ค๋ฉด ๊ตฌ์กฐ์ฒด๋ฅผ ์ถ๊ฐํ๊ณ `std::variant` ๋ณ์นญ์ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค. ์ด๋ ๋จ์ผ์ ๊ตญ์์ ์ธ ๋ณ๊ฒฝ์ด๋ฉฐ, ๊ทธ ํ์ ์ด๋ฅผ ์ฒ๋ฆฌํด์ผ ํ๋ ๋ฐฉ๋ฌธ์๋ค์ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค. ์ปดํ์ผ๋ฌ๋ ์น์ ํ๊ฒ๋ ์ด๋ค ๋ฐฉ๋ฌธ์(์ค๋ฒ๋ก๋๋ ๋๋ค)์ ์ค๋ฒ๋ก๋๊ฐ ๋๋ฝ๋์๋์ง ์ ํํ ์๋ ค์ค ๊ฒ์ ๋๋ค.
๋ฐ์ด๋ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ
์ฐ๋ฆฌ๋ ์ธ ๊ฐ์ง ๋ค๋ฅธ ์ฑ ์์ ๋ถ๋ฆฌํ์ต๋๋ค:
- ๋ฐ์ดํฐ ํํ: `Node` ๊ตฌ์กฐ์ฒด๋ ๋จ์ํ๊ณ ๋นํ์ฑ์ธ ๋ฐ์ดํฐ ์ปจํ ์ด๋์ ๋๋ค.
- ์ํ ๋ฉ์ปค๋์ฆ: `TreeWalker` ํด๋์ค๋ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ํ์ํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ก์ง์ ๋ ์ ์ ์ผ๋ก ์์ ํฉ๋๋ค. ์์คํ ์ ๋ค๋ฅธ ๋ถ๋ถ์ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ `InOrderTreeWalker`๋ `BreadthFirstTreeWalker`๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
- ์ฐ์ฐ ๋ก์ง: ์์ปค์ ์ ๋ฌ๋ ๋๋ค๋ ์ฃผ์ด์ง ์์ (ํ๊ฐ, ์ถ๋ ฅ, ํ์ ๊ฒ์ฌ ๋ฑ)์ ๋ํ ํน์ ๋น์ฆ๋์ค ๋ก์ง์ ํฌํจํฉ๋๋ค.
์ด๋ฌํ ๋ถ๋ฆฌ๋ ์ฝ๋๋ฅผ ์ดํดํ๊ณ , ํ ์คํธํ๊ณ , ์ ์ง๋ณด์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค. ๊ฐ ๊ตฌ์ฑ ์์๋ ๋จ ํ๋์ ์ ์ ์๋ ์ฑ ์์ ๊ฐ์ง๋๋ค.
ํฅ์๋ ์ฌ์ฌ์ฉ์ฑ
`TreeWalker`๋ ๋ฌดํํ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค. ์ํ ๋ก์ง์ ํ ๋ฒ ์์ฑ๋๊ณ ๋ฌด์ ํ์ ์ฐ์ฐ์ ์ ์ฉ๋ ์ ์์ต๋๋ค. ์ด๋ ์ฝ๋ ์ค๋ณต๊ณผ ์๋ก์ด ๋ฐฉ๋ฌธ์๋ง๋ค ์ํ ๋ก์ง์ ๋ค์ ๊ตฌํํจ์ผ๋ก์จ ๋ฐ์ํ ์ ์๋ ๋ฒ๊ทธ์ ๊ฐ๋ฅ์ฑ์ ์ค์ ๋๋ค.
๊ฐ๊ฒฐํ๊ณ ํํ๋ ฅ ์๋ ์ฝ๋
ํ๋ C++ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ๊ฒฐ๊ณผ ์ฝ๋๋ ์ข ์ข ๊ณ ์ ์ ์ธ ๋ฐฉ๋ฌธ์ ๊ตฌํ๋ณด๋ค ๋ ๊ฐ๊ฒฐํฉ๋๋ค. ๋๋ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ์ฉ๋๋ ๊ณณ์์ ๋ฐ๋ก ์ฐ์ฐ ๋ก์ง์ ์ ์ํ ์ ์์ด ๊ฐ๋จํ๊ณ ๊ตญ์์ ์ธ ์ฐ์ฐ์ ๋ํ ๊ฐ๋ ์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ๋๋ค ์ธํธ๋ก๋ถํฐ ๋ฐฉ๋ฌธ์๋ฅผ ๋ง๋ค๊ธฐ ์ํ `Overloaded` ํฌํผ ๊ตฌ์กฐ์ฒด๋ ๋ฐฉ๋ฌธ์ ์ ์๋ฅผ ๊น๋ํ๊ฒ ์ ์งํ๋ ์ผ๋ฐ์ ์ด๊ณ ๊ฐ๋ ฅํ ๊ด์ฉ๊ตฌ์ ๋๋ค.
์ ์ฌ์ ์ธ ์ ์ถฉ์ ๊ณผ ๊ณ ๋ ค์ฌํญ
์ด๋ค ํจํด๋ ๋ง๋ฅ ํด๊ฒฐ์ฑ ์ ์๋๋๋ค. ๊ด๋ จ๋ ์ ์ถฉ์ ์ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
์ด๊ธฐ ์ค์ ์ ๋ณต์ก์ฑ
`std::variant`์ ์ ๋ค๋ฆญ `TreeWalker`๋ฅผ ์ฌ์ฉํ `Node` ๊ตฌ์กฐ์ ์ด๊ธฐ ์ค์ ์ ๊ฐ๋จํ ์ฌ๊ท ํจ์ ํธ์ถ๋ณด๋ค ๋ ๋ณต์กํ๊ฒ ๋๊ปด์ง ์ ์์ต๋๋ค. ์ด ํจํด์ ํธ๋ฆฌ ๊ตฌ์กฐ๋ ์์ ์ ์ด์ง๋ง ์ฐ์ฐ์ ์๊ฐ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ์ฆ๊ฐํ ๊ฒ์ผ๋ก ์์๋๋ ์์คํ ์์ ๊ฐ์ฅ ํฐ ์ด์ ์ ์ ๊ณตํฉ๋๋ค. ๋งค์ฐ ๊ฐ๋จํ ์ผํ์ฑ ํธ๋ฆฌ ์ฒ๋ฆฌ ์์ ์๋ ๊ณผํ ์ ์์ต๋๋ค.
์ฑ๋ฅ
C++์์ `std::visit`๋ฅผ ์ฌ์ฉํ๋ ์ด ํจํด์ ์ฑ๋ฅ์ ํ๋ฅญํฉ๋๋ค. `std::visit`๋ ์ผ๋ฐ์ ์ผ๋ก ์ปดํ์ผ๋ฌ์ ์ํด ๊ณ ๋๋ก ์ต์ ํ๋ ์ ํ ํ ์ด๋ธ์ ์ฌ์ฉํ์ฌ ๊ตฌํ๋๋ฏ๋ก ๋์คํจ์น๊ฐ ๋งค์ฐ ๋น ๋ฆ ๋๋ค. ์ข ์ข ๊ฐ์ ํจ์ ํธ์ถ๋ณด๋ค ๋น ๋ฆ ๋๋ค. ์ ์ฌํ ์ ๋ค๋ฆญ ๋์์ ๋ฌ์ฑํ๊ธฐ ์ํด ๋ฆฌํ๋ ์ ์ด๋ ๋์ ๋๋ฆฌ ๊ธฐ๋ฐ ํ์ ์กฐํ๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ์ธ์ด์์๋ ๊ณ ์ ์ ์ธ ์ ์ ๋์คํจ์น ๋ฐฉ๋ฌธ์์ ๋นํด ๋์ ๋๋ ์ฑ๋ฅ ์ค๋ฒํค๋๊ฐ ์์ ์ ์์ต๋๋ค.
์ธ์ด ์์กด์ฑ
์ด ํน์ ๊ตฌํ์ ์ฐ์ํจ๊ณผ ํจ์จ์ฑ์ C++17 ๊ธฐ๋ฅ์ ํฌ๊ฒ ์์กดํฉ๋๋ค. ์์น์ ์ด์ ๊ฐ๋ฅํ์ง๋ง, ๋ค๋ฅธ ์ธ์ด์์์ ๊ตฌํ ์ธ๋ถ ์ฌํญ์ ๋ค๋ฅผ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, Java์์๋ ์ต์ ๋ฒ์ ์์ ๋ด์ธ๋ ์ธํฐํ์ด์ค(sealed interface)์ ํจํด ๋งค์นญ์ ์ฌ์ฉํ๊ฑฐ๋, ๊ตฌ ๋ฒ์ ์์๋ ๋ ์ฅํฉํ ๋งต ๊ธฐ๋ฐ ๋์คํจ์ฒ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ค์ ์ ํ๋ฆฌ์ผ์ด์ ๋ฐ ์ฌ์ฉ ์ฌ๋ก
ํธ๋ฆฌ ์ํ๋ฅผ ์ํ ์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ํจํด์ ๋จ์ง ํ๋ฌธ์ ์ธ ์ฐ์ต์ด ์๋๋๋ค; ์ด๊ฒ์ ๋ง์ ๋ณต์กํ ์ํํธ์จ์ด ์์คํ ์ ์ค์ถ์ ๋๋ค.
- ์ปดํ์ผ๋ฌ ๋ฐ ์ธํฐํ๋ฆฌํฐ: ์ด๊ฒ์ ํ์ค์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ ๋๋ค. ์ถ์ ๊ตฌ๋ฌธ ํธ๋ฆฌ(AST)๋ ๋ค๋ฅธ "๋ฐฉ๋ฌธ์" ๋๋ "ํจ์ค"์ ์ํด ์ฌ๋ฌ ๋ฒ ์ํ๋ฉ๋๋ค. ์๋ฏธ ๋ถ์ ํจ์ค๋ ํ์ ์ค๋ฅ๋ฅผ ํ์ธํ๊ณ , ์ต์ ํ ํจ์ค๋ ํธ๋ฆฌ๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ์ฌ์์ฑํ๋ฉฐ, ์ฝ๋ ์์ฑ ํจ์ค๋ ์ต์ข ํธ๋ฆฌ๋ฅผ ์ํํ์ฌ ๊ธฐ๊ณ์ด ๋๋ ๋ฐ์ดํธ์ฝ๋๋ฅผ ๋ด๋ณด๋ ๋๋ค. ๊ฐ ํจ์ค๋ ๋์ผํ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํ ๋ณ๊ฐ์ ์ฐ์ฐ์ ๋๋ค.
- ์ ์ ๋ถ์ ๋๊ตฌ: ๋ฆฐํฐ, ์ฝ๋ ํฌ๋งทํฐ, ๋ณด์ ์ค์บ๋์ ๊ฐ์ ๋๊ตฌ๋ ์ฝ๋๋ฅผ AST๋ก ํ์ฑํ ๋ค์ ๋ค์ํ ๋ฐฉ๋ฌธ์๋ฅผ ์คํํ์ฌ ํจํด์ ์ฐพ๊ณ , ์คํ์ผ ๊ท์น์ ๊ฐ์ ํ๋ฉฐ, ์ ์ฌ์ ์ธ ์ทจ์ฝ์ ์ ํ์งํฉ๋๋ค.
- ๋ฌธ์ ์ฒ๋ฆฌ(DOM): XML ๋๋ HTML ๋ฌธ์๋ฅผ ์กฐ์ํ ๋, ๋น์ ์ ํธ๋ฆฌ์ ์์ ํ๊ณ ์์ต๋๋ค. ์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์๋ ๋ชจ๋ ๋งํฌ๋ฅผ ์ถ์ถํ๊ฑฐ๋, ๋ชจ๋ ์ด๋ฏธ์ง๋ฅผ ๋ณํํ๊ฑฐ๋, ๋ฌธ์๋ฅผ ๋ค๋ฅธ ํ์์ผ๋ก ์ง๋ ฌํํ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
- UI ํ๋ ์์ํฌ: ํ๋ UI ํ๋ ์์ํฌ๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ์ปดํฌ๋ํธ ํธ๋ฆฌ๋ก ํํํฉ๋๋ค. ์ด ํธ๋ฆฌ๋ฅผ ์ํํ๋ ๊ฒ์ ๋ ๋๋ง, ์ํ ์ ๋ฐ์ดํธ ์ ํ(React์ ์ฌ์กฐ์ ์๊ณ ๋ฆฌ์ฆ์ฒ๋ผ), ๋๋ ์ด๋ฒคํธ ๋์คํจ์น๋ฅผ ์ํด ํ์ํฉ๋๋ค.
- 3D ๊ทธ๋ํฝ์ค์ ์ฌ ๊ทธ๋ํ: 3D ์ฌ์ ์ข ์ข ๊ฐ์ฒด์ ๊ณ์ธต ๊ตฌ์กฐ๋ก ํํ๋ฉ๋๋ค. ๋ณํ์ ์ ์ฉํ๊ณ , ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์ ์ ์ํํ๋ฉฐ, ๊ฐ์ฒด๋ฅผ ๋ ๋๋ง ํ์ดํ๋ผ์ธ์ ์ ์ถํ๊ธฐ ์ํด ์ํ๊ฐ ํ์ํฉ๋๋ค. ์ ๋ค๋ฆญ ์์ปค๋ ๋ ๋๋ง ์ฐ์ฐ์ ์ ์ฉํ ๋ค์, ๋ฌผ๋ฆฌ ์ ๋ฐ์ดํธ ์ฐ์ฐ์ ์ ์ฉํ๊ธฐ ์ํด ์ฌ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
๊ฒฐ๋ก : ์๋ก์ด ์ฐจ์์ ์ถ์ํ
์ ๋ค๋ฆญ ๋ฐฉ๋ฌธ์ ํจํด์, ํนํ ์ ์ฉ `TreeWalker`๋ก ๊ตฌํ๋ ๋, ์ํํธ์จ์ด ์ค๊ณ์ ๊ฐ๋ ฅํ ์งํ๋ฅผ ๋ํ๋ ๋๋ค. ์ด๊ฒ์ ๋ฐฉ๋ฌธ์ ํจํด์ ์๋ ์ฝ์์ธ ๋ฐ์ดํฐ์ ์ฐ์ฐ์ ๋ถ๋ฆฌ๋ฅผ ์ทจํ๊ณ , ๋ณต์กํ ์ํ ๋ก์ง๋ ๋ถ๋ฆฌํจ์ผ๋ก์จ ๊ทธ๊ฒ์ ํ ๋จ๊ณ ๊ฒฉ์์ํต๋๋ค.
๋ฌธ์ ๋ฅผ ๋ฐ์ดํฐ, ์ํ, ์ฐ์ฐ์ด๋ผ๋ ์ธ ๊ฐ์ง ๋ณ๊ฐ์ ์ง๊ต ๊ตฌ์ฑ ์์๋ก ๋ถํดํจ์ผ๋ก์จ, ์ฐ๋ฆฌ๋ ๋ ๋ชจ๋ํ๋๊ณ , ์ ์ง๋ณด์ ๊ฐ๋ฅํ๋ฉฐ, ๊ฒฌ๊ณ ํ ์์คํ ์ ๊ตฌ์ถํฉ๋๋ค. ํต์ฌ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ์ํ ์ฝ๋๋ฅผ ์์ ํ์ง ์๊ณ ์๋ก์ด ์ฐ์ฐ์ ์ถ๊ฐํ ์ ์๋ ๋ฅ๋ ฅ์ ์ํํธ์จ์ด ์ํคํ ์ฒ์ ์์ด ๊ธฐ๋ ๋น์ ์ธ ์น๋ฆฌ์ ๋๋ค. `TreeWalker`๋ ์์ญ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ตฌ๋ํ ์ ์๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์์ฐ์ด ๋์ด, ์ํ ๋ก์ง์ด ์ฌ์ฉ๋๋ ๋ชจ๋ ๊ณณ์์ ์ผ๊ด๋๊ณ ์ ํํ๋๋ก ๋ณด์ฅํฉ๋๋ค.
์ดํด์ ์ค์ ์ ์ด๊ธฐ ํฌ์๊ฐ ํ์ํ์ง๋ง, ์ ๋ค๋ฆญ ํธ๋ฆฌ ์ํ ๋ฐฉ๋ฌธ์ ํจํด์ ํ๋ก์ ํธ์ ์๋ช ๋ด๋ด ๊ทธ ๊ฐ์น๋ฅผ ๋ฐํฉ๋๋ค. ๋ณต์กํ ๊ณ์ธต์ ๋ฐ์ดํฐ๋ก ์์ ํ๋ ๋ชจ๋ ๊ฐ๋ฐ์์๊ฒ ์ด๊ฒ์ ๊นจ๋ํ๊ณ , ์ ์ฐํ๋ฉฐ, ์ค๋ ์ง์๋๋ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํ ํ์์ ์ธ ๋๊ตฌ์ ๋๋ค.