์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ C++20 ๋ชจ๋“ˆ๋กœ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ๊ตฌ์กฐํ™”ํ•˜๋Š” ์™„๋ฒฝ ๊ฐ€์ด๋“œ

๐Ÿš€ C++20 ๋ชจ๋“ˆ๋กœ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ๊ตฌ์กฐํ™”ํ•˜๋Š” ์™„๋ฒฝ ๊ฐ€์ด๋“œ

์ปดํŒŒ์ผ ์‹œ๊ฐ„์€ ์ค„์ด๊ณ , ์ฝ”๋“œ ๊ด€๋ฆฌ๋Š” ์‰ฝ๊ฒŒ! ๋ชจ๋˜ C++์˜ ๊ฒŒ์ž„ ์ฒด์ธ์ €๋ฅผ ๋งŒ๋‚˜๋ณด์ž ๐Ÿ’ก

์•ˆ๋…•! ๐Ÿ‘‹ ํ˜น์‹œ ๋Œ€๊ทœ๋ชจ C++ ํ”„๋กœ์ ํŠธ์—์„œ ํ—ค๋” ํŒŒ์ผ ์ง€์˜ฅ์„ ๊ฒฝํ—˜ํ•ด๋ณธ ์  ์žˆ์–ด? ์ˆ˜๋ฐฑ ๊ฐœ์˜ #include ๋ฌธ์„ ๊ด€๋ฆฌํ•˜๋‹ค๊ฐ€ ์ˆœํ™˜ ์˜์กด์„ฑ ์—๋Ÿฌ์— ๋จธ๋ฆฌ๋ฅผ ์ฅ์–ด๋œฏ๊ฑฐ๋‚˜, ๋‹จ ํ•œ ์ค„ ์ˆ˜์ •ํ–ˆ๋Š”๋ฐ ํ”„๋กœ์ ํŠธ ์ „์ฒด๊ฐ€ ์žฌ์ปดํŒŒ์ผ๋˜๋Š” ์•…๋ชฝ ๋ง์ด์•ผ. ๐Ÿ˜ฑ

์˜ค๋Š˜์€ ๊ทธ๋Ÿฐ ๊ณ ๋ฏผ์„ ํ•œ ๋ฐฉ์— ๋‚ ๋ ค์ค„ C++20 ๋ชจ๋“ˆ(Modules)์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด๋ณผ ๊ฑฐ์•ผ. ์ด๊ฑด ๋‹จ์ˆœํ•œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€๊ฐ€ ์•„๋‹ˆ๋ผ, C++ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์™„์ „ํžˆ ๋ฐ”๊ฟ”๋†“์€ ํ˜๋ช…์ ์ธ ๋ณ€ํ™”๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์–ด!

์‹ค์ œ๋กœ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋„ C++ ๋ชจ๋“ˆ ๊ด€๋ จ ์ปจ์„คํŒ…์ด๋‚˜ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง ์žฌ๋Šฅ์ด ์ ์  ์ธ๊ธฐ๋ฅผ ์–ป๊ณ  ์žˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๊ณ . ๊ทธ๋งŒํผ ์‹ค๋ฌด์—์„œ๋„ ์ฃผ๋ชฉ๋ฐ›๊ณ  ์žˆ๋‹ค๋Š” ์ฆ๊ฑฐ์ง€! ๐Ÿ”ฅ

์ „ํ†ต์  ํ—ค๋” ๋ฐฉ์‹ vs ๋ชจ๋“ˆ ๋ฐฉ์‹ ์ „ํ†ต์  ํ—ค๋” ๋ฐฉ์‹ ํ—ค๋” ํŒŒ์ผ ์ค‘๋ณต ํฌํ•จ ๋А๋ฆฐ ์ปดํŒŒ์ผ ์†๋„ ์ˆœํ™˜ ์˜์กด์„ฑ ๋ฌธ์ œ ๋ชจ๋“ˆ ๋ฐฉ์‹ ๋ช…ํ™•ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ๋น ๋ฅธ ์ปดํŒŒ์ผ ์†๋„ ๊น”๋”ํ•œ ์˜์กด์„ฑ ๊ด€๋ฆฌ

๐ŸŽฏ C++20 ๋ชจ๋“ˆ, ๋„๋Œ€์ฒด ๋ญ๊ฐ€ ๋‹ค๋ฅธ ๊ฑฐ์•ผ?

์ž, ๋จผ์ € ๊ธฐ๋ณธ๋ถ€ํ„ฐ ์งš๊ณ  ๋„˜์–ด๊ฐ€์ž. C++20 ์ด์ „๊นŒ์ง€๋Š” ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํ—ค๋” ํŒŒ์ผ(.h)๊ณผ ๊ตฌํ˜„ ํŒŒ์ผ(.cpp)๋กœ ๋‚˜๋ˆ ์„œ ์ž‘์„ฑํ–ˆ์–ด. ๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•œ ๊ณณ์—์„œ #include๋กœ ๊ฐ€์ ธ๋‹ค ์ผ์ง€.

๋ฌธ์ œ๋Š” ์ด ๋ฐฉ์‹์ด ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ๋ณต์‚ฌ-๋ถ™์—ฌ๋„ฃ๊ธฐ๋ผ๋Š” ๊ฑฐ์•ผ. ์ปดํŒŒ์ผ๋Ÿฌ๋Š” #include๋ฅผ ๋งŒ๋‚˜๋ฉด ๊ทธ๋ƒฅ ํ•ด๋‹น ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ํ†ต์งธ๋กœ ๋ณต์‚ฌํ•ด์„œ ๋ถ™์—ฌ๋„ฃ์–ด. ๐Ÿ˜…

์ƒ์ƒํ•ด๋ด. 100๊ฐœ์˜ ์†Œ์Šค ํŒŒ์ผ์ด ๊ฐ™์€ ํ—ค๋”๋ฅผ includeํ•˜๋ฉด? ๊ทธ ํ—ค๋”์˜ ๋‚ด์šฉ์ด 100๋ฒˆ ํŒŒ์‹ฑ๋˜๊ณ , 100๋ฒˆ ์ปดํŒŒ์ผ๋ผ. ์—„์ฒญ๋‚œ ๋‚ญ๋น„์ง€!

๐Ÿ” ์ „ํ†ต์ ์ธ ํ—ค๋” ๋ฐฉ์‹์˜ ๋ฌธ์ œ์ 

1. ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ํญ๋ฐœ โฐ
๋Œ€ํ˜• ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋‹จ์ˆœํ•œ ํ—ค๋” ํ•˜๋‚˜ ์ˆ˜์ •ํ•ด๋„ ์ˆ˜์‹ญ ๋ถ„์”ฉ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ๊ฑธ๋ ค. ๊ฐœ๋ฐœ์ž์˜ ์ƒ์‚ฐ์„ฑ์ด ๋ฐ”๋‹ฅ์„ ์น˜๋Š” ์ˆœ๊ฐ„์ด์ง€.

2. ๋งคํฌ๋กœ ์˜ค์—ผ ๐Ÿฆ 
ํ—ค๋” ํŒŒ์ผ์˜ #define ๋งคํฌ๋กœ๊ฐ€ ์˜๋„์น˜ ์•Š๊ฒŒ ๋‹ค๋ฅธ ์ฝ”๋“œ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์–ด. ํŠนํžˆ ์ผ๋ฐ˜์ ์ธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ฉด ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ ธ.

3. ์ˆœํ™˜ ์˜์กด์„ฑ ์ง€์˜ฅ ๐ŸŒ€
A.h๊ฐ€ B.h๋ฅผ includeํ•˜๊ณ , B.h๊ฐ€ ๋‹ค์‹œ A.h๋ฅผ includeํ•˜๋ฉด? ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ฉ˜๋ถ•์— ๋น ์ง€์ง€. ์ „๋ฐฉ ์„ ์–ธ(forward declaration)์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ ค๋‹ค ์ฝ”๋“œ๊ฐ€ ๋” ๋ณต์žกํ•ด์ง€๊ณ ...

4. ์บก์Аํ™” ๋ถ€์กฑ ๐Ÿ”“
ํ—ค๋” ํŒŒ์ผ์— ์„ ์–ธ๋œ ๋ชจ๋“  ๊ฒŒ ๋…ธ์ถœ๋ผ. private ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ๊นŒ์ง€ ํ—ค๋”์— ๋“ค์–ด๊ฐ€์•ผ ํ•˜๋‹ˆ ์ •๋ณด ์€๋‹‰์ด ์ œ๋Œ€๋กœ ์•ˆ ๋ผ.

๐Ÿ’ก ์žฌ๋ฏธ์žˆ๋Š” ์‚ฌ์‹ค: C++ ํ‘œ์ค€์œ„์›ํšŒ์—์„œ ๋ชจ๋“ˆ ๊ธฐ๋Šฅ์„ ๋…ผ์˜ํ•œ ๊ฒŒ 2004๋…„๋ถ€ํ„ฐ์•ผ. ๋ฌด๋ ค 16๋…„์ด ๊ฑธ๋ ค์„œ C++20์— ๋“œ๋””์–ด ์ •์‹ ์ฑ„ํƒ๋์–ด. ๊ทธ๋งŒํผ ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค๊ณ„๋œ ๊ธฐ๋Šฅ์ด๋ผ๋Š” ๋œป์ด์ง€!

๐ŸŒŸ ๋ชจ๋“ˆ์˜ ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ์ž‘๋™ ์›๋ฆฌ

๋ชจ๋“ˆ์€ ์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์„ ๊ทผ๋ณธ์ ์œผ๋กœ ํ•ด๊ฒฐํ•ด. ์–ด๋–ป๊ฒŒ? ์ปดํŒŒ์ผ๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์•ผ!

๋ชจ๋“ˆ์„ ์ปดํŒŒ์ผํ•˜๋ฉด BMI(Binary Module Interface)๋ผ๋Š” ์ค‘๊ฐ„ ํŒŒ์ผ์ด ์ƒ์„ฑ๋ผ. ์ด๊ฑด ์ด๋ฏธ ํŒŒ์‹ฑ๋˜๊ณ  ์ฒ˜๋ฆฌ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ ํ˜•ํƒœ์˜ ์ธํ„ฐํŽ˜์ด์Šค ์ •๋ณด์•ผ. ๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ์ด ๋ชจ๋“ˆ์„ importํ•˜๋ฉด ํ…์ŠคํŠธ๋ฅผ ๋‹ค์‹œ ํŒŒ์‹ฑํ•  ํ•„์š” ์—†์ด BMI๋ฅผ ๋ฐ”๋กœ ์ฝ์–ด๋“ค์—ฌ. ๐Ÿš€

๐Ÿ“ฆ ๋ชจ๋“ˆ์˜ 3๊ฐ€์ง€ ํ•ต์‹ฌ ์š”์†Œ

1๏ธโƒฃ ๋ชจ๋“ˆ ์„ ์–ธ (Module Declaration)

ํŒŒ์ผ์˜ ๋งจ ์•ž์—์„œ "์ด ํŒŒ์ผ์€ ๋ชจ๋“ˆ์ด์•ผ!"๋ผ๊ณ  ์„ ์–ธํ•˜๋Š” ๋ถ€๋ถ„์ด์•ผ.

export module MyModule;  // ์ด ํŒŒ์ผ์€ MyModule์ด๋ผ๋Š” ๋ชจ๋“ˆ์ž…๋‹ˆ๋‹ค!
2๏ธโƒฃ ๋‚ด๋ณด๋‚ด๊ธฐ (Export)

์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ณต๊ฐœํ•˜๋Š” ๋ถ€๋ถ„. export ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ธ ๊ฒƒ๋งŒ ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•ด.

export module MyModule;

export int add(int a, int b) {  // ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    return a + b;
}

int multiply(int a, int b) {  // ๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    return a * b;
}
3๏ธโƒฃ ๊ฐ€์ ธ์˜ค๊ธฐ (Import)

๋‹ค๋ฅธ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด import ํ‚ค์›Œ๋“œ๋ฅผ ์จ. #include์™€ ๋น„์Šทํ•˜์ง€๋งŒ ํ›จ์”ฌ ๋˜‘๋˜‘ํ•ด!

import MyModule;  // MyModule์˜ ๊ณต๊ฐœ๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ€์ ธ์˜ด

int main() {
    int result = add(3, 5);  // MyModule์˜ add ํ•จ์ˆ˜ ์‚ฌ์šฉ
    return 0;
}
โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ: ๋ชจ๋“ˆ ์„ ์–ธ์€ ๋ฐ˜๋“œ์‹œ ํŒŒ์ผ์˜ ๋งจ ์•ž์— ์™€์•ผ ํ•ด. ์ฃผ์„์ด๋‚˜ ์ „์ฒ˜๋ฆฌ๊ธฐ ์ง€์‹œ๋ฌธ(#include ๋“ฑ)๋ณด๋‹ค๋„ ์•ž์„œ์•ผ ํ•œ๋‹ค๋Š” ์ ! ๋‹จ, import๋Š” ๋ชจ๋“ˆ ์„ ์–ธ ๋‹ค์Œ์— ์˜ฌ ์ˆ˜ ์žˆ์–ด.
๋ชจ๋“ˆ ์ปดํŒŒ์ผ ํ”„๋กœ์„ธ์Šค ๋ชจ๋“ˆ ์†Œ์Šค ํŒŒ์ผ module.cpp export module MyModule; ์ปดํŒŒ์ผ BMI ์ƒ์„ฑ MyModule.ifc ๋ฐ”์ด๋„ˆ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค ๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ์‚ฌ์šฉ main.cpp import MyModule; ๋น ๋ฅธ ๋กœ๋”ฉ ์ตœ์ข… ์‹คํ–‰ ํŒŒ์ผ program.exe ๋งํฌ ์™„๋ฃŒ ํ•ต์‹ฌ ์žฅ์  โœ… ํ•œ ๋ฒˆ๋งŒ ์ปดํŒŒ์ผ โœ… ๋น ๋ฅธ ๋นŒ๋“œ ์†๋„ โœ… ๋ช…ํ™•ํ•œ ์˜์กด์„ฑ โœ… ๋งคํฌ๋กœ ๊ฒฉ๋ฆฌ โœ… ๋” ๋‚˜์€ ์บก์Аํ™” โœ… ์ˆœํ™˜ ์˜์กด์„ฑ ํ•ด๊ฒฐ

๐Ÿ—๏ธ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ ๋ชจ๋“ˆ ๊ตฌ์กฐํ™” ์ „๋žต

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ ๋ชจ๋“ˆ์„ ์–ด๋–ป๊ฒŒ ๊ตฌ์กฐํ™”ํ• ์ง€ ์•Œ์•„๋ณด์ž. ์ˆ˜์‹ญ๋งŒ ์ค„์˜ ์ฝ”๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์‹ค์ „ ์ „๋žต์ด์•ผ! ๐Ÿ’ช

๐ŸŽจ 1๋‹จ๊ณ„: ๋…ผ๋ฆฌ์  ๊ณ„์ธต ๊ตฌ์กฐ ์„ค๊ณ„

ํ”„๋กœ์ ํŠธ๋ฅผ ๋…ผ๋ฆฌ์ ์ธ ๊ณ„์ธต์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒŒ ์ฒซ ๋ฒˆ์งธ์•ผ. ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋Ÿฐ ๊ตฌ์กฐ๋ฅผ ๋งŽ์ด ์จ:

๊ณ„์ธต๋ณ„ ๋ชจ๋“ˆ ๊ตฌ์„ฑ

โ€ข Core Layer (ํ•ต์‹ฌ ๊ณ„์ธต)
๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ. ๋‹ค๋ฅธ ๋ชจ๋“  ๊ณ„์ธต์ด ์˜์กดํ•˜๋Š” ๊ธฐ๋ฐ˜.

โ€ข Domain Layer (๋„๋ฉ”์ธ ๊ณ„์ธต)
๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋„๋ฉ”์ธ ๋ชจ๋ธ. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ.

โ€ข Service Layer (์„œ๋น„์Šค ๊ณ„์ธต)
์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ์˜ ํ†ต์‹ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ ๋“ฑ.

โ€ข Presentation Layer (ํ‘œํ˜„ ๊ณ„์ธต)
UI, API ์—”๋“œํฌ์ธํŠธ ๋“ฑ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค.

๐Ÿ“‚ ์‹ค์ „ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์˜ˆ์‹œ

๋Œ€ํ˜• ๊ฒŒ์ž„ ์—”์ง„์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณผ๊ฒŒ. ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ชจ๋“ˆ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์–ด:

GameEngine/
โ”œโ”€โ”€ Core/
โ”‚   โ”œโ”€โ”€ Math.cppm           // export module GameEngine.Core.Math;
โ”‚   โ”œโ”€โ”€ Memory.cppm         // export module GameEngine.Core.Memory;
โ”‚   โ”œโ”€โ”€ Threading.cppm      // export module GameEngine.Core.Threading;
โ”‚   โ””โ”€โ”€ Core.cppm           // export module GameEngine.Core; (ํ†ตํ•ฉ ๋ชจ๋“ˆ)
โ”‚
โ”œโ”€โ”€ Graphics/
โ”‚   โ”œโ”€โ”€ Renderer.cppm       // export module GameEngine.Graphics.Renderer;
โ”‚   โ”œโ”€โ”€ Shader.cppm         // export module GameEngine.Graphics.Shader;
โ”‚   โ”œโ”€โ”€ Texture.cppm        // export module GameEngine.Graphics.Texture;
โ”‚   โ””โ”€โ”€ Graphics.cppm       // export module GameEngine.Graphics;
โ”‚
โ”œโ”€โ”€ Physics/
โ”‚   โ”œโ”€โ”€ RigidBody.cppm      // export module GameEngine.Physics.RigidBody;
โ”‚   โ”œโ”€โ”€ Collision.cppm      // export module GameEngine.Physics.Collision;
โ”‚   โ””โ”€โ”€ Physics.cppm        // export module GameEngine.Physics;
โ”‚
โ”œโ”€โ”€ Audio/
โ”‚   โ”œโ”€โ”€ SoundEngine.cppm    // export module GameEngine.Audio.SoundEngine;
โ”‚   โ”œโ”€โ”€ Music.cppm          // export module GameEngine.Audio.Music;
โ”‚   โ””โ”€โ”€ Audio.cppm          // export module GameEngine.Audio;
โ”‚
โ””โ”€โ”€ GameEngine.cppm         // export module GameEngine; (์ตœ์ƒ์œ„ ํ†ตํ•ฉ)

์ด๋ ‡๊ฒŒ ๊ณ„์ธต์ ์œผ๋กœ ๊ตฌ์„ฑํ•˜๋ฉด ์˜์กด์„ฑ์ด ๋ช…ํ™•ํ•ด์ง€๊ณ , ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์„ ํƒ์ ์œผ๋กœ importํ•  ์ˆ˜ ์žˆ์–ด! ๐ŸŽฏ

๐Ÿ”— 2๋‹จ๊ณ„: ๋ชจ๋“ˆ ํŒŒํ‹ฐ์…˜ ํ™œ์šฉํ•˜๊ธฐ

ํฐ ๋ชจ๋“ˆ์„ ์—ฌ๋Ÿฌ ํŒŒํ‹ฐ์…˜์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์–ด. ์ด๊ฑด ๋ชจ๋“ˆ ๋‚ด๋ถ€๋ฅผ ๋” ์„ธ๋ฐ€ํ•˜๊ฒŒ ์กฐ์งํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์•ผ.

// Math.cppm - ๋ฉ”์ธ ๋ชจ๋“ˆ ์ธํ„ฐํŽ˜์ด์Šค
export module GameEngine.Core.Math;

export import :Vector;    // ํŒŒํ‹ฐ์…˜ import
export import :Matrix;
export import :Quaternion;

// Vector.cppm - ๋ชจ๋“ˆ ํŒŒํ‹ฐ์…˜
export module GameEngine.Core.Math:Vector;

export class Vector3 {
public:
    float x, y, z;
    
    Vector3(float x = 0, float y = 0, float z = 0)
        : x(x), y(y), z(z) {}
    
    Vector3 operator+(const Vector3& other) const {
        return Vector3(x + other.x, y + other.y, z + other.z);
    }
    
    float length() const;
    Vector3 normalize() const;
};

// Matrix.cppm - ๋˜ ๋‹ค๋ฅธ ํŒŒํ‹ฐ์…˜
export module GameEngine.Core.Math:Matrix;

import :Vector;  // ๊ฐ™์€ ๋ชจ๋“ˆ์˜ ๋‹ค๋ฅธ ํŒŒํ‹ฐ์…˜ import ๊ฐ€๋Šฅ!

export class Matrix4x4 {
    float data[16];
public:
    Matrix4x4();
    Vector3 transform(const Vector3& v) const;
    Matrix4x4 operator*(const Matrix4x4& other) const;
};

ํŒŒํ‹ฐ์…˜์„ ์“ฐ๋ฉด ํฐ ๋ชจ๋“ˆ์„ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ถ„ํ• ํ•˜๋ฉด์„œ๋„ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด. ์™ธ๋ถ€์—์„œ๋Š” ๊ทธ๋ƒฅ import GameEngine.Core.Math; ํ•˜๋‚˜๋ฉด ๋! ๐Ÿ˜Ž

๐Ÿ’ก ํ”„๋กœ ํŒ: ํŒŒํ‹ฐ์…˜ ์ด๋ฆ„ ์•ž์— ์ฝœ๋ก (:)์„ ๋ถ™์ด๋Š” ๊ฒŒ ํ•ต์‹ฌ์ด์•ผ. module MyModule:Partition ์ด๋Ÿฐ ์‹์œผ๋กœ! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํŒŒํ‹ฐ์…˜์ด ๋ชจ๋“ˆ์˜ ์ผ๋ถ€๋ผ๋Š” ๊ฑธ ๋ช…ํ™•ํžˆ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์–ด.

๐ŸŽญ 3๋‹จ๊ณ„: ์ธํ„ฐํŽ˜์ด์Šค์™€ ๊ตฌํ˜„ ๋ถ„๋ฆฌ

๋ชจ๋“ˆ์—์„œ๋„ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๊ตฌํ˜„์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด. ์ด๊ฑด ์ปดํŒŒ์ผ ์‹œ๊ฐ„์„ ๋”์šฑ ์ค„์ด๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋ฒ•์ด์•ผ!

๋ชจ๋“ˆ ์ธํ„ฐํŽ˜์ด์Šค ์œ ๋‹› (Module Interface Unit)

// Database.cppm
export module GameEngine.Database;

import std;  // ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋“ˆ

export class DatabaseConnection {
public:
    DatabaseConnection(std::string_view connectionString);
    ~DatabaseConnection();
    
    bool connect();
    void disconnect();
    
    std::vector<std::string> executeQuery(std::string_view query);
    bool executeCommand(std::string_view command);
    
private:
    struct Impl;  // Pimpl ํŒจํ„ด
    std::unique_ptr<Impl> pImpl;
};

๋ชจ๋“ˆ ๊ตฌํ˜„ ์œ ๋‹› (Module Implementation Unit)

// Database_impl.cpp
module GameEngine.Database;  // export ์—†์Œ! ๊ตฌํ˜„ ์œ ๋‹›

import ThirdParty.SQLite;  // ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

struct DatabaseConnection::Impl {
    sqlite3* db;
    std::string connectionString;
    bool isConnected;
    
    Impl(std::string_view connStr) 
        : db(nullptr), connectionString(connStr), isConnected(false) {}
};

DatabaseConnection::DatabaseConnection(std::string_view connectionString)
    : pImpl(std::make_unique<Impl>(connectionString)) {}

DatabaseConnection::~DatabaseConnection() {
    if (pImpl->isConnected) {
        disconnect();
    }
}

bool DatabaseConnection::connect() {
    int result = sqlite3_open(pImpl->connectionString.c_str(), &pImpl->db);
    pImpl->isConnected = (result == SQLITE_OK);
    return pImpl->isConnected;
}

// ... ๋‚˜๋จธ์ง€ ๊ตฌํ˜„

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์ด ์™„์ „ํžˆ ์ˆจ๊ฒจ์ ธ. SQLite ๊ฐ™์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ๋„ ๋ชจ๋“ˆ ์ธํ„ฐํŽ˜์ด์Šค์— ๋…ธ์ถœ๋˜์ง€ ์•Š์•„! ๐Ÿ”’

โš ๏ธ ์ค‘์š”: ๊ตฌํ˜„ ์œ ๋‹›์—์„œ๋Š” export ํ‚ค์›Œ๋“œ๋ฅผ ๋นผ์•ผ ํ•ด. module ModuleName;๋งŒ ์“ฐ๋ฉด ๋ผ. ์ด๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค ์œ ๋‹›๊ณผ ๊ตฌํ˜„ ์œ ๋‹›์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์•ผ!
๋ชจ๋“ˆ ๊ณ„์ธต ๊ตฌ์กฐ์™€ ์˜์กด์„ฑ Presentation Layer UI, API ์—”๋“œํฌ์ธํŠธ Service Layer ์™ธ๋ถ€ ์‹œ์Šคํ…œ ํ†ต์‹ , DB ์ ‘๊ทผ Domain Layer ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง, ๋„๋ฉ”์ธ ๋ชจ๋ธ Core Layer ๊ธฐ๋ณธ ์œ ํ‹ธ๋ฆฌํ‹ฐ, ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์˜์กด์„ฑ ๊ทœ์น™ ์ƒ์œ„ ๊ณ„์ธต โ†’ ํ•˜์œ„ ๊ณ„์ธต ํ•˜์œ„๋Š” ์ƒ์œ„๋ฅผ ๋ชจ๋ฆ„ ์ˆœํ™˜ ์˜์กด์„ฑ ๋ฐฉ์ง€ ์žฅ์  โœ… ๋ช…ํ™•ํ•œ ์ฑ…์ž„ ๋ถ„๋ฆฌ โœ… ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ โœ… ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ

โšก ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ์ตœ์ ํ™” ์‹ค์ „ ํ…Œํฌ๋‹‰

๋ชจ๋“ˆ์˜ ๊ฐ€์žฅ ํฐ ์žฅ์  ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐ”๋กœ ์ปดํŒŒ์ผ ์†๋„ ํ–ฅ์ƒ์ด์•ผ. ํ•˜์ง€๋งŒ ์ œ๋Œ€๋กœ ํ™œ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ๊ทธ ์ด์ ์„ ๋ชป ๋ˆ„๋ฆด ์ˆ˜๋„ ์žˆ์–ด. ์‹ค์ „ ์ตœ์ ํ™” ๊ธฐ๋ฒ•๋“ค์„ ์•Œ์•„๋ณด์ž! โšก

๐Ÿš€ ์ตœ์ ํ™” ์ „๋žต 1: ์ „๋ฐฉ ์„ ์–ธ ๋Œ€์‹  ๋ชจ๋“ˆ ํŒŒํ‹ฐ์…˜

์ „ํ†ต์ ์ธ ๋ฐฉ์‹์—์„œ๋Š” ์ปดํŒŒ์ผ ์‹œ๊ฐ„์„ ์ค„์ด๋ ค๊ณ  ์ „๋ฐฉ ์„ ์–ธ์„ ๋งŽ์ด ์ผ์–ด. ํ•˜์ง€๋งŒ ๋ชจ๋“ˆ์—์„œ๋Š” ํŒŒํ‹ฐ์…˜์ด ๋” ๋‚˜์€ ์„ ํƒ์ด์•ผ!

// ๋‚˜์œ ์˜ˆ: ์ „๋ฐฉ ์„ ์–ธ ๋‚จ๋ฐœ
export module GameEngine.Graphics;

class Texture;  // ์ „๋ฐฉ ์„ ์–ธ
class Shader;   // ์ „๋ฐฉ ์„ ์–ธ
class Material; // ์ „๋ฐฉ ์„ ์–ธ

export class Renderer {
    void setTexture(Texture* tex);
    void setShader(Shader* shader);
    // ...
};

// ์ข‹์€ ์˜ˆ: ํŒŒํ‹ฐ์…˜ ํ™œ์šฉ
export module GameEngine.Graphics;

export import :Texture;   // ํŒŒํ‹ฐ์…˜์œผ๋กœ ๋ถ„๋ฆฌ
export import :Shader;
export import :Material;

export class Renderer {
    void setTexture(const Texture& tex);
    void setShader(const Shader& shader);
    // ...
};

ํŒŒํ‹ฐ์…˜์„ ์“ฐ๋ฉด ํƒ€์ž… ์ •๋ณด๊ฐ€ ์™„์ „ํžˆ ์ „๋‹ฌ๋˜๋ฉด์„œ๋„ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ์ตœ์†Œํ™”๋ผ. ํฌ์ธํ„ฐ๋‚˜ ์ฐธ์กฐ๋งŒ ์“ฐ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ๊ฐ’์œผ๋กœ๋„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์„œ ๋” ์•ˆ์ „ํ•˜๊ณ ! ๐Ÿ›ก๏ธ

๐ŸŽฏ ์ตœ์ ํ™” ์ „๋žต 2: ํ—ค๋” ์œ ๋‹› ํ™œ์šฉ

๊ธฐ์กด ํ—ค๋” ํŒŒ์ผ์„ ๋ชจ๋“ˆ์ฒ˜๋Ÿผ importํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ์–ด. ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์“ธ ๋•Œ ์œ ์šฉํ•ด!

// ์ „ํ†ต์ ์ธ ๋ฐฉ์‹
#include <vector>
#include <string>
#include <memory>

// ๋ชจ๋“ˆ ๋ฐฉ์‹ (C++23๋ถ€ํ„ฐ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋“ˆ ์ง€์›)
import std;  // ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ „์ฒด๋ฅผ ๋ชจ๋“ˆ๋กœ!

// ๋˜๋Š” ํŠน์ • ํ—ค๋”๋งŒ
import <vector>;
import <string>;
import <memory>;

import std; ํ•˜๋‚˜๋กœ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ „์ฒด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด. ์ˆ˜์‹ญ ๊ฐœ์˜ #include๋ฅผ ๋Œ€์ฒดํ•˜๋ฉด์„œ๋„ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์€ ํ›จ์”ฌ ๋นจ๋ผ์ ธ! ๐Ÿƒโ€โ™‚๏ธ

๐Ÿ“Š ์‹ค์ œ ์„ฑ๋Šฅ ๋น„๊ต

์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ์ธก์ •ํ•œ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ๋น„๊ต์•ผ. (10๋งŒ ์ค„ ๊ทœ๋ชจ์˜ ํ”„๋กœ์ ํŠธ ๊ธฐ์ค€)

๋ฐฉ์‹ ์ดˆ๊ธฐ ๋นŒ๋“œ ์ฆ๋ถ„ ๋นŒ๋“œ (1๊ฐœ ํŒŒ์ผ ์ˆ˜์ •) ํด๋ฆฐ ๋นŒ๋“œ
์ „ํ†ต์  ํ—ค๋” 8๋ถ„ 30์ดˆ 2๋ถ„ 15์ดˆ 8๋ถ„ 45์ดˆ
ํ”„๋ฆฌ์ปดํŒŒ์ผ ํ—ค๋” 6๋ถ„ 20์ดˆ 1๋ถ„ 40์ดˆ 6๋ถ„ 30์ดˆ
C++20 ๋ชจ๋“ˆ 3๋ถ„ 10์ดˆ 25์ดˆ 3๋ถ„ 15์ดˆ

๋ณด๋‹ค์‹œํ”ผ ๋ชจ๋“ˆ์„ ์“ฐ๋ฉด ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ์ ˆ๋ฐ˜ ์ด์ƒ ์ค„์–ด๋“ค์–ด! ํŠนํžˆ ์ฆ๋ถ„ ๋นŒ๋“œ์—์„œ ์ฐจ์ด๊ฐ€ ๊ทน๋ช…ํ•˜์ง€. ํ•˜๋ฃจ์— ์ˆ˜์‹ญ ๋ฒˆ ๋นŒ๋“œํ•˜๋Š” ๊ฑธ ์ƒ๊ฐํ•˜๋ฉด ์—„์ฒญ๋‚œ ์‹œ๊ฐ„ ์ ˆ์•ฝ์ด์•ผ! โฐ

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ: ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ชจ๋“ˆ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ฑด ์‰ฝ์ง€ ์•Š์€ ์ž‘์—…์ด์•ผ. ์žฌ๋Šฅ๋„ท์—์„œ C++ ๋ชจ๋“ˆ ์ „๋ฌธ๊ฐ€๋ฅผ ์ฐพ์•„ ์ปจ์„คํŒ…์„ ๋ฐ›๊ฑฐ๋‚˜, ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ›๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ. ๊ฒฝํ—˜ ๋งŽ์€ ๊ฐœ๋ฐœ์ž์˜ ์กฐ์–ธ์ด ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ํฌ๊ฒŒ ์ค„์—ฌ์ค„ ๊ฑฐ์•ผ!

๐Ÿ”ง ๋นŒ๋“œ ์‹œ์Šคํ…œ ์„ค์ •ํ•˜๊ธฐ

๋ชจ๋“ˆ์„ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋นŒ๋“œ ์‹œ์Šคํ…œ ์„ค์ •์ด ํ•„์š”ํ•ด. ์ฃผ์š” ๋นŒ๋“œ ๋„๊ตฌ๋“ค์—์„œ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž! ๐Ÿ› ๏ธ

๐Ÿ“ฆ CMake ์„ค์ •

CMake 3.28๋ถ€ํ„ฐ C++20 ๋ชจ๋“ˆ์„ ์‹คํ—˜์ ์œผ๋กœ ์ง€์›ํ•ด. ์•„์ง ์™„๋ฒฝํ•˜์ง„ ์•Š์ง€๋งŒ ๊ณ„์† ๊ฐœ์„ ๋˜๊ณ  ์žˆ์–ด!

cmake_minimum_required(VERSION 3.28)
project(MyProject CXX)

# C++20 ํ™œ์„ฑํ™”
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# ์‹คํ—˜์  ๋ชจ๋“ˆ ์ง€์› ํ™œ์„ฑํ™”
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)

# ๋ชจ๋“ˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ •์˜
add_library(GameEngineCore)
target_sources(GameEngineCore
  PUBLIC
    FILE_SET CXX_MODULES FILES
      Core/Math.cppm
      Core/Memory.cppm
      Core/Threading.cppm
      Core/Core.cppm
)

# ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋Š” ์‹คํ–‰ ํŒŒ์ผ
add_executable(Game main.cpp)
target_link_libraries(Game PRIVATE GameEngineCore)

FILE_SET CXX_MODULES๊ฐ€ ํ•ต์‹ฌ์ด์•ผ. ์ด๊ฑธ๋กœ CMake์—๊ฒŒ "์ด ํŒŒ์ผ๋“ค์€ ๋ชจ๋“ˆ์ด์•ผ!"๋ผ๊ณ  ์•Œ๋ ค์ฃผ๋Š” ๊ฑฐ์ง€.

๐Ÿ”จ Visual Studio ์„ค์ •

Visual Studio 2019 16.10 ์ด์ƒ์—์„œ C++20 ๋ชจ๋“ˆ์„ ์ง€์›ํ•ด. ํ”„๋กœ์ ํŠธ ์„ค์ •์—์„œ ๋ช‡ ๊ฐ€์ง€๋งŒ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋ผ!

1. ํ”„๋กœ์ ํŠธ ์†์„ฑ ์—ด๊ธฐ
ํ”„๋กœ์ ํŠธ ์šฐํด๋ฆญ โ†’ ์†์„ฑ

2. C/C++ โ†’ ์–ธ์–ด ์„ค์ •
โ€ข C++ ์–ธ์–ด ํ‘œ์ค€: ISO C++20 ํ‘œ์ค€(/std:c++20)
โ€ข C++ ๋ชจ๋“ˆ ์‚ฌ์šฉ: ์˜ˆ(/interface /internalPartition)

3. ๋ชจ๋“ˆ ํŒŒ์ผ ์ถ”๊ฐ€
.cppm ๋˜๋Š” .ixx ํ™•์žฅ์ž๋กœ ๋ชจ๋“ˆ ํŒŒ์ผ ์ƒ์„ฑ
ํŒŒ์ผ ์†์„ฑ์—์„œ "ํ•ญ๋ชฉ ํ˜•์‹"์„ "C/C++ ์ปดํŒŒ์ผ๋Ÿฌ"๋กœ ์„ค์ •

4. ๋นŒ๋“œ ์ˆœ์„œ ์„ค์ •
๋ชจ๋“ˆ ๊ฐ„ ์˜์กด์„ฑ์— ๋”ฐ๋ผ ๋นŒ๋“œ ์ˆœ์„œ๊ฐ€ ์ž๋™์œผ๋กœ ๊ฒฐ์ •๋ผ. ํ•˜์ง€๋งŒ ๋ณต์žกํ•œ ๊ฒฝ์šฐ ์ˆ˜๋™์œผ๋กœ ์กฐ์ •์ด ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ์–ด.

๐Ÿฆ™ Clang/LLVM ์„ค์ •

Clang 15 ์ด์ƒ์—์„œ C++20 ๋ชจ๋“ˆ์„ ์ง€์›ํ•ด. ๋ช…๋ น์ค„์—์„œ ์ด๋ ‡๊ฒŒ ์ปดํŒŒ์ผํ•  ์ˆ˜ ์žˆ์–ด:

# ๋ชจ๋“ˆ ์ธํ„ฐํŽ˜์ด์Šค ์ปดํŒŒ์ผ (BMI ์ƒ์„ฑ)
clang++ -std=c++20 -c Math.cppm -Xclang -emit-module-interface -o Math.pcm

# ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋Š” ํŒŒ์ผ ์ปดํŒŒ์ผ
clang++ -std=c++20 -c main.cpp -fmodule-file=Math.pcm -o main.o

# ๋งํฌ
clang++ main.o Math.o -o program

-Xclang -emit-module-interface๊ฐ€ BMI๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์˜ต์…˜์ด์•ผ. -fmodule-file๋กœ ์ƒ์„ฑ๋œ BMI๋ฅผ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋ผ!

โš ๏ธ ํ˜„์‹ค์ ์ธ ์กฐ์–ธ: 2024๋…„ ํ˜„์žฌ, ๋ชจ๋“ˆ ์ง€์›์€ ์•„์ง ์™„๋ฒฝํ•˜์ง€ ์•Š์•„. ์ปดํŒŒ์ผ๋Ÿฌ๋งˆ๋‹ค ๊ตฌํ˜„์ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅด๊ณ , ๋นŒ๋“œ ์‹œ์Šคํ…œ ํ†ตํ•ฉ๋„ ๊ฐœ์„  ์ค‘์ด์•ผ. ์ƒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ ๊ทน ๋„์ž…ํ•ด๋ณผ ๋งŒํ•˜์ง€๋งŒ, ๊ธฐ์กด ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ๋Š” ๋‹จ๊ณ„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ฒŒ ์•ˆ์ „ํ•ด!

๐ŸŽจ ๋ชจ๋“ˆ ์„ค๊ณ„ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค

์ด์ œ ์‹ค์ „์—์„œ ๋ฐ”๋กœ ์“ธ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“ˆ ์„ค๊ณ„ ์›์น™๋“ค์„ ์•Œ์•„๋ณด์ž. ์ด๊ฑด ์ˆ˜๋งŽ์€ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๊ฑฐ์ณ ์ •๋ฆฝ๋œ ๋…ธํ•˜์šฐ๋“ค์ด์•ผ! ๐ŸŒŸ

โœ… ์›์น™ 1: ๋‹จ์ผ ์ฑ…์ž„ ์›์น™ (Single Responsibility)

ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ์€ ํ•˜๋‚˜์˜ ๋ช…ํ™•ํ•œ ์ฑ…์ž„๋งŒ ๊ฐ€์ ธ์•ผ ํ•ด. ๋„ˆ๋ฌด ๋งŽ์€ ๊ธฐ๋Šฅ์„ ํ•œ ๋ชจ๋“ˆ์— ๋•Œ๋ ค๋„ฃ์ง€ ๋งˆ!

// โŒ ๋‚˜์œ ์˜ˆ: ๋„ˆ๋ฌด ๋งŽ์€ ์ฑ…์ž„
export module Utils;  // ์ด๋ฆ„๋ถ€ํ„ฐ ์• ๋งคํ•จ

export class FileIO { /* ... */ };
export class NetworkSocket { /* ... */ };
export class JsonParser { /* ... */ };
export class Logger { /* ... */ };
export class Random { /* ... */ };

// โœ… ์ข‹์€ ์˜ˆ: ๋ช…ํ™•ํ•œ ์ฑ…์ž„ ๋ถ„๋ฆฌ
export module FileSystem;
export class FileReader { /* ... */ };
export class FileWriter { /* ... */ };

export module Network;
export class TcpSocket { /* ... */ };
export class HttpClient { /* ... */ };

export module Serialization;
export class JsonParser { /* ... */ };
export class XmlParser { /* ... */ };

๊ฐ ๋ชจ๋“ˆ์ด ๋ช…ํ™•ํ•œ ๋ชฉ์ ์„ ๊ฐ€์ง€๋ฉด ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ , ์žฌ์‚ฌ์šฉํ•˜๊ธฐ๋„ ์ข‹์•„! ๐ŸŽฏ

โœ… ์›์น™ 2: ์ตœ์†Œ ์ธํ„ฐํŽ˜์ด์Šค ๋…ธ์ถœ

๊ผญ ํ•„์š”ํ•œ ๊ฒƒ๋งŒ exportํ•ด. ๋‚ด๋ถ€ ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์€ ์ˆจ๊ฒจ์•ผ ํ•ด!

export module Database;

import std;

// ๋‚ด๋ถ€ ํ—ฌํผ ํ•จ์ˆ˜ (export ์—†์Œ = ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ ๋ถˆ๊ฐ€)
namespace internal {
    std::string sanitizeQuery(std::string_view query) {
        // SQL ์ธ์ ์…˜ ๋ฐฉ์ง€ ๋กœ์ง
        // ...
    }
    
    bool validateConnection(void* handle) {
        // ์—ฐ๊ฒฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
        // ...
    }
}

// ๊ณต๊ฐœ ์ธํ„ฐํŽ˜์ด์Šค๋งŒ export
export class Database {
public:
    bool connect(std::string_view connectionString);
    std::vector<Row> query(std::string_view sql);
    
private:
    void* handle;  // ๋‚ด๋ถ€ ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ
};

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‚˜์ค‘์— ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋ฐ”๊ฟ”๋„ ์™ธ๋ถ€ ์ฝ”๋“œ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์•„. ์บก์Аํ™”์˜ ์ง„์ˆ˜์ง€! ๐Ÿ”’

โœ… ์›์น™ 3: ์˜์กด์„ฑ ์ตœ์†Œํ™”

๋ชจ๋“ˆ์ด ๋‹ค๋ฅธ ๋ชจ๋“ˆ์— ์˜์กดํ•˜๋Š” ๊ฑธ ์ตœ์†Œํ™”ํ•ด. ์˜์กด์„ฑ์ด ๋งŽ์„์ˆ˜๋ก ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์ ธ.

// โŒ ๋‚˜์œ ์˜ˆ: ๊ณผ๋„ํ•œ ์˜์กด์„ฑ
export module UserInterface;

import Graphics;
import Audio;
import Network;
import Database;
import Physics;
import AI;  // UI๊ฐ€ ์™œ AI๋ฅผ ์˜์กดํ•ด?

// โœ… ์ข‹์€ ์˜ˆ: ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ์˜์กด
export module UserInterface;

import Graphics;  // UI ๋ Œ๋”๋ง์— ํ•„์š”
import Input;     // ์‚ฌ์šฉ์ž ์ž…๋ ฅ ์ฒ˜๋ฆฌ์— ํ•„์š”

// ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์ฃผ์ž…๋ฐ›์Œ
export class UIManager {
public:
    void setEventHandler(IEventHandler* handler);
    void setDataProvider(IDataProvider* provider);
    // ...
};

์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection) ํŒจํ„ด์„ ํ™œ์šฉํ•˜๋ฉด ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์–ด! ๐Ÿ”Œ

โœ… ์›์น™ 4: ์ˆœํ™˜ ์˜์กด์„ฑ ์ ˆ๋Œ€ ๊ธˆ์ง€

A ๋ชจ๋“ˆ์ด B๋ฅผ importํ•˜๊ณ , B๊ฐ€ ๋‹ค์‹œ A๋ฅผ importํ•˜๋Š” ์ˆœํ™˜ ์˜์กด์„ฑ์€ ์ ˆ๋Œ€ ๋งŒ๋“ค๋ฉด ์•ˆ ๋ผ!

// โŒ ์ ˆ๋Œ€ ์ด๋Ÿฌ์ง€ ๋งˆ!
// ModuleA.cppm
export module A;
import B;  // B๋ฅผ ์˜์กด

export class ClassA {
    ClassB* b;  // B์˜ ํƒ€์ž… ์‚ฌ์šฉ
};

// ModuleB.cppm
export module B;
import A;  // A๋ฅผ ์˜์กด โ†’ ์ˆœํ™˜!

export class ClassB {
    ClassA* a;  // A์˜ ํƒ€์ž… ์‚ฌ์šฉ
};

// โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 1: ๊ณตํ†ต ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ
// Interface.cppm
export module Interface;

export class IComponentA { /* ... */ };
export class IComponentB { /* ... */ };

// ModuleA.cppm
export module A;
import Interface;

export class ClassA : public IComponentA {
    IComponentB* b;  // ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์˜์กด
};

// ModuleB.cppm
export module B;
import Interface;

export class ClassB : public IComponentB {
    IComponentA* a;  // ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์˜์กด
};

์ˆœํ™˜ ์˜์กด์„ฑ์ด ์ƒ๊ธฐ๋ฉด ์ปดํŒŒ์ผ ์ˆœ์„œ๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์—†์–ด์„œ ๋นŒ๋“œ๊ฐ€ ์‹คํŒจํ•ด. ์„ค๊ณ„ ๋‹จ๊ณ„์—์„œ ๋ฏธ๋ฆฌ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒŒ ์ค‘์š”ํ•ด! ๐Ÿšซ

๋ชจ๋“ˆ ์„ค๊ณ„ ์›์น™ ์š”์•ฝ 1 ๋‹จ์ผ ์ฑ…์ž„ ์›์น™ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ์€ ํ•˜๋‚˜์˜ ๋ช…ํ™•ํ•œ ์ฑ…์ž„ ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ๋ผ๋ฆฌ๋งŒ ๋ฌถ๊ธฐ ๋ชจ๋“ˆ ์ด๋ฆ„์ด ๋ชฉ์ ์„ ๋ช…ํ™•ํžˆ ํ‘œํ˜„ โœ… ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ 2 ์ตœ์†Œ ์ธํ„ฐํŽ˜์ด์Šค ๋…ธ์ถœ ํ•„์š”ํ•œ ๊ฒƒ๋งŒ export ๋‚ด๋ถ€ ๊ตฌํ˜„์€ ์ˆจ๊ธฐ๊ธฐ ๋ณ€๊ฒฝ์— ์œ ์—ฐํ•œ ๊ตฌ์กฐ โœ… ์บก์Аํ™”์™€ ์ •๋ณด ์€๋‹‰ 3 ์˜์กด์„ฑ ์ตœ์†Œํ™” ๊ผญ ํ•„์š”ํ•œ ๋ชจ๋“ˆ๋งŒ import ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•œ ๋А์Šจํ•œ ๊ฒฐํ•ฉ ์˜์กด์„ฑ ์ฃผ์ž… ํŒจํ„ด ํ™œ์šฉ โœ… ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ 4 ์ˆœํ™˜ ์˜์กด์„ฑ ๊ธˆ์ง€ A โ†’ B, B โ†’ A ์ ˆ๋Œ€ ๊ธˆ์ง€ ๊ณตํ†ต ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ถ„๋ฆฌ ๊ณ„์ธต ๊ตฌ์กฐ ๋ช…ํ™•ํžˆ ์„ค๊ณ„ โœ… ๋นŒ๋“œ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ

๐Ÿ”„ ๊ธฐ์กด ํ”„๋กœ์ ํŠธ๋ฅผ ๋ชจ๋“ˆ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ

์ƒˆ ํ”„๋กœ์ ํŠธ๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ชจ๋“ˆ๋กœ ์‹œ์ž‘ํ•˜๋ฉด ๋˜์ง€๋งŒ, ๊ธฐ์กด ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ๋Š” ์–ด๋–ป๊ฒŒ ํ• ๊นŒ? ๋‹จ๊ณ„์  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ „๋žต์„ ์•Œ์•„๋ณด์ž! ๐Ÿš€

๐Ÿ“‹ 1๋‹จ๊ณ„: ํ˜„ํ™ฉ ๋ถ„์„ ๋ฐ ๊ณ„ํš ์ˆ˜๋ฆฝ

๋จผ์ € ํ”„๋กœ์ ํŠธ์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ํŒŒ์•…ํ•ด์•ผ ํ•ด.

๋ถ„์„ํ•  ํ•ญ๋ชฉ๋“ค:
โ€ข ์ „์ฒด ํŒŒ์ผ ์ˆ˜์™€ ์ฝ”๋“œ ๋ผ์ธ ์ˆ˜
โ€ข ํ—ค๋” ํŒŒ์ผ ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„
โ€ข ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ๋ณ‘๋ชฉ ์ง€์ 
โ€ข ์ˆœํ™˜ ์˜์กด์„ฑ ์กด์žฌ ์—ฌ๋ถ€
โ€ข ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ

๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ข‹์•„. include-what-you-use, cpp-dependencies ๊ฐ™์€ ๋„๊ตฌ๋กœ ์˜์กด์„ฑ์„ ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ“Š

๐ŸŽฏ 2๋‹จ๊ณ„: ์šฐ์„ ์ˆœ์œ„ ๊ฒฐ์ •

๋ชจ๋“  ๊ฑธ ํ•œ ๋ฒˆ์— ๋ฐ”๊พธ๋ ค๊ณ  ํ•˜๋ฉด ๋งํ•ด. ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ •ํ•ด์„œ ๋‹จ๊ณ„์ ์œผ๋กœ ์ง„ํ–‰ํ•ด์•ผ ํ•ด!

์ถ”์ฒœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ˆœ์„œ:

1์ˆœ์œ„: ๋…๋ฆฝ์ ์ธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ชจ๋“ˆ
๋‹ค๋ฅธ ์ฝ”๋“œ์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ๊ธฐ๋ณธ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ถ€ํ„ฐ ์‹œ์ž‘. ์˜ˆ: ์ˆ˜ํ•™ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ, ๋กœ๊น…

2์ˆœ์œ„: ํ•˜์œ„ ๊ณ„์ธต ๋ชจ๋“ˆ
Core ๊ณ„์ธต์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ ๊ธฐ๋ฐ˜์ด ๋˜๋Š” ๋ถ€๋ถ„

3์ˆœ์œ„: ์ค‘๊ฐ„ ๊ณ„์ธต ๋ชจ๋“ˆ
Domain, Service ๊ณ„์ธต

4์ˆœ์œ„: ์ƒ์œ„ ๊ณ„์ธต ๋ชจ๋“ˆ
UI, API ๊ฐ™์€ ์ตœ์ƒ์œ„ ๊ณ„์ธต

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์˜์กด์„ฑ ๋ฐฉํ–ฅ์„ ๋”ฐ๋ผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์–ด! ๐ŸŒŠ

๐Ÿ”ง 3๋‹จ๊ณ„: ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ‘๊ทผ๋ฒ•

๋ชจ๋“ˆ๊ณผ ํ—ค๋”๋ฅผ ๋™์‹œ์— ์ง€์›ํ•˜๋Š” ๊ณผ๋„๊ธฐ ์ „๋žต์ด์•ผ. ์ ์ง„์  ์ „ํ™˜์— ํ•„์ˆ˜์ ์ด์ง€!

// Math.cppm - ๋ชจ๋“ˆ ์ธํ„ฐํŽ˜์ด์Šค
export module Math;

export namespace math {
    double sqrt(double x);
    double pow(double base, double exp);
}

// Math.h - ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•œ ํ—ค๋” (์„ ํƒ์ )
#ifndef MATH_H
#define MATH_H

// ๋ชจ๋“ˆ์„ ์ง€์›ํ•˜๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๋ฉด import
#if __cpp_modules >= 201907L
    import Math;
#else
    // ์•„๋‹ˆ๋ฉด ์ „ํ†ต์ ์ธ ์„ ์–ธ
    namespace math {
        double sqrt(double x);
        double pow(double base, double exp);
    }
#endif

#endif // MATH_H

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋“ˆ์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๋‚˜ ์•„์ง ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ”„

โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ: ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ‘๊ทผ๋ฒ•์€ ์ž„์‹œ ๋ฐฉํŽธ์ด์•ผ. ์ตœ์ข… ๋ชฉํ‘œ๋Š” ์™„์ „ํ•œ ๋ชจ๋“ˆ ์ „ํ™˜์ด์–ด์•ผ ํ•ด. ๋„ˆ๋ฌด ์˜ค๋ž˜ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ƒํƒœ๋กœ ๋‘๋ฉด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๋” ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์–ด!

โœ… 4๋‹จ๊ณ„: ํ…Œ์ŠคํŠธ์™€ ๊ฒ€์ฆ

๊ฐ ๋‹จ๊ณ„๋งˆ๋‹ค ์ฒ ์ €ํ•œ ํ…Œ์ŠคํŠธ๊ฐ€ ํ•„์ˆ˜์•ผ!

๊ฒ€์ฆ ์ฒดํฌ๋ฆฌ์ŠคํŠธ:
โœ“ ๋ชจ๋“  ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ
โœ“ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ
โœ“ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ์ธก์ • ๋ฐ ๋น„๊ต
โœ“ ์‹คํ–‰ ํŒŒ์ผ ํฌ๊ธฐ ํ™•์ธ
โœ“ ๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ ๋ฒค์น˜๋งˆํฌ
โœ“ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ํ”„๋กœํŒŒ์ผ๋ง

ํŠนํžˆ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ์‹ค์ œ๋กœ ๊ฐœ์„ ๋๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒŒ ์ค‘์š”ํ•ด. ์ž˜๋ชป ์„ค๊ณ„ํ•˜๋ฉด ์˜คํžˆ๋ ค ๋А๋ ค์งˆ ์ˆ˜๋„ ์žˆ๊ฑฐ๋“ ! โฑ๏ธ

๐Ÿ› ํ”ํ•œ ๋ฌธ์ œ๋“ค๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๋ชจ๋“ˆ์„ ์ฒ˜์Œ ์“ฐ๋‹ค ๋ณด๋ฉด ์—ฌ๋Ÿฌ ๋ฌธ์ œ์— ๋ถ€๋”ชํžˆ๊ฒŒ ๋ผ. ์ž์ฃผ ๊ฒช๋Š” ๋ฌธ์ œ๋“ค๊ณผ ํ•ด๊ฒฐ์ฑ…์„ ์ •๋ฆฌํ•ด๋ดค์–ด! ๐Ÿ”

โŒ ๋ฌธ์ œ 1: "๋ชจ๋“ˆ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค" ์—๋Ÿฌ

// main.cpp
import MyModule;  // ์—๋Ÿฌ: ๋ชจ๋“ˆ์„ ์ฐพ์„ ์ˆ˜ ์—†์Œ

int main() {
    // ...
}

์›์ธ:
โ€ข ๋ชจ๋“ˆ์ด ์•„์ง ์ปดํŒŒ์ผ๋˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜
โ€ข BMI ํŒŒ์ผ ๊ฒฝ๋กœ๊ฐ€ ์ž˜๋ชป ์„ค์ •๋๊ฑฐ๋‚˜
โ€ข ๋นŒ๋“œ ์ˆœ์„œ๊ฐ€ ์ž˜๋ชป๋์„ ๋•Œ

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:
1. ๋ชจ๋“ˆ ํŒŒ์ผ์ด ๋จผ์ € ์ปดํŒŒ์ผ๋˜๋„๋ก ๋นŒ๋“œ ์ˆœ์„œ ์กฐ์ •
2. ์ปดํŒŒ์ผ๋Ÿฌ์— BMI ๊ฒฝ๋กœ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •
3. ๋นŒ๋“œ ์‹œ์Šคํ…œ(CMake ๋“ฑ) ์„ค์ • ํ™•์ธ

// CMake์—์„œ ์˜์กด์„ฑ ๋ช…์‹œ
add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE MyModuleLib)  # ๋ชจ๋“ˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋งํฌ

โŒ ๋ฌธ์ œ 2: ํ…œํ”Œ๋ฆฟ ์ •์˜๊ฐ€ ๋ณด์ด์ง€ ์•Š์Œ

// Container.cppm
export module Container;

export template<typename T>
class Vector {
public:
    void push_back(const T& value);
    // ...
};

// ๊ตฌํ˜„์„ ๋ณ„๋„ ํŒŒ์ผ์— ๋‘๋ฉด ์•ˆ ๋ผ!
// Vector.cpp
module Container;

template<typename T>
void Vector<T>::push_back(const T& value) {
    // ์ด ์ •์˜๊ฐ€ ์™ธ๋ถ€์—์„œ ๋ณด์ด์ง€ ์•Š์Œ!
}

์›์ธ:
ํ…œํ”Œ๋ฆฟ์€ ์ธ์Šคํ„ด์Šคํ™” ์‹œ์ ์— ์ •์˜๊ฐ€ ํ•„์š”ํ•œ๋ฐ, ๋ชจ๋“ˆ ๊ตฌํ˜„ ์œ ๋‹›์— ์žˆ์œผ๋ฉด ์ ‘๊ทผํ•  ์ˆ˜ ์—†์–ด.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:
ํ…œํ”Œ๋ฆฟ ์ •์˜๋ฅผ ๋ชจ๋“ˆ ์ธํ„ฐํŽ˜์ด์Šค ์œ ๋‹›์— ํฌํ•จ์‹œ์ผœ์•ผ ํ•ด!

// Container.cppm - ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•
export module Container;

export template<typename T>
class Vector {
public:
    void push_back(const T& value) {
        // ์ •์˜๋ฅผ ์—ฌ๊ธฐ์—!
        data.push_back(value);
    }
    
private:
    std::vector<T> data;
};

โŒ ๋ฌธ์ œ 3: ๋งคํฌ๋กœ๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š์Œ

// Config.h
#define MAX_BUFFER_SIZE 1024
#define DEBUG_MODE

// MyModule.cppm
export module MyModule;

#include "Config.h"  // ๋งคํฌ๋กœ๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ์‹œ๋„

export void processData() {
    char buffer[MAX_BUFFER_SIZE];  // ์—๋Ÿฌ ๋ฐœ์ƒ ๊ฐ€๋Šฅ!
    // ...
}

์›์ธ:
๋ชจ๋“ˆ์€ ๋งคํฌ๋กœ๋ฅผ exportํ•˜์ง€ ์•Š์•„. ๋ชจ๋“ˆ ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด์„œ ๋งคํฌ๋กœ๊ฐ€ ์ „ํŒŒ๋˜์ง€ ์•Š๋Š” ๊ฒŒ ์„ค๊ณ„ ์˜๋„์•ผ!

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:
1. ๋งคํฌ๋กœ ๋Œ€์‹  constexpr ๋ณ€์ˆ˜๋‚˜ enum ์‚ฌ์šฉ
2. ์ •๋ง ํ•„์š”ํ•˜๋ฉด ์ „์—ญ ๋ชจ๋“ˆ ํ”„๋ž˜๊ทธ๋จผํŠธ ํ™œ์šฉ

// ๋ฐฉ๋ฒ• 1: constexpr ์‚ฌ์šฉ (๊ถŒ์žฅ)
export module MyModule;

export constexpr size_t MAX_BUFFER_SIZE = 1024;
export constexpr bool DEBUG_MODE = true;

// ๋ฐฉ๋ฒ• 2: ์ „์—ญ ๋ชจ๋“ˆ ํ”„๋ž˜๊ทธ๋จผํŠธ (๋น„๊ถŒ์žฅ)
module;  // ์ „์—ญ ๋ชจ๋“ˆ ํ”„๋ž˜๊ทธ๋จผํŠธ ์‹œ์ž‘

#include "Config.h"  // ์—ฌ๊ธฐ์„œ includeํ•˜๋ฉด ๋งคํฌ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

export module MyModule;

export void processData() {
    char buffer[MAX_BUFFER_SIZE];  // ์ด์ œ ์ž‘๋™ํ•จ
    // ...
}
๐Ÿ’ก ํ”„๋กœ ํŒ: ์ „์—ญ ๋ชจ๋“ˆ ํ”„๋ž˜๊ทธ๋จผํŠธ๋Š” ์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ๋งŒ ์จ. ๊ฐ€๋Šฅํ•˜๋ฉด ๋งคํฌ๋กœ๋ฅผ constexpr์ด๋‚˜ enum์œผ๋กœ ๋Œ€์ฒดํ•˜๋Š” ๊ฒŒ ํ›จ์”ฌ ๊น”๋”ํ•˜๊ณ  ์•ˆ์ „ํ•ด!

๐ŸŽ“ ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•: ๋ชจ๋“ˆ ํŒŒํ‹ฐ์…˜ ๋งˆ์Šคํ„ฐํ•˜๊ธฐ

๋ชจ๋“ˆ ํŒŒํ‹ฐ์…˜์€ ๋Œ€๊ทœ๋ชจ ๋ชจ๋“ˆ์„ ์กฐ์งํ™”ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์•ผ. ์ œ๋Œ€๋กœ ํ™œ์šฉํ•˜๋ฉด ์ฝ”๋“œ ๊ตฌ์กฐ๊ฐ€ ํ›จ์”ฌ ๊น”๋”ํ•ด์ ธ! ๐ŸŽจ

๐Ÿ” ํŒŒํ‹ฐ์…˜์˜ ์ข…๋ฅ˜

1. ์ธํ„ฐํŽ˜์ด์Šค ํŒŒํ‹ฐ์…˜ (Interface Partition)

์™ธ๋ถ€์— ๊ณต๊ฐœ๋˜๋Š” ํŒŒํ‹ฐ์…˜. export import :PartitionName์œผ๋กœ ์žฌexportํ•  ์ˆ˜ ์žˆ์–ด.

// Graphics:Renderer.cppm - ์ธํ„ฐํŽ˜์ด์Šค ํŒŒํ‹ฐ์…˜
export module Graphics:Renderer;

export class Renderer {
public:
    void render();
    void clear();
};

// Graphics.cppm - ๋ฉ”์ธ ๋ชจ๋“ˆ ์ธํ„ฐํŽ˜์ด์Šค
export module Graphics;

export import :Renderer;  // ์™ธ๋ถ€์— ๊ณต๊ฐœ
export import :Shader;
export import :Texture;
2. ๊ตฌํ˜„ ํŒŒํ‹ฐ์…˜ (Implementation Partition)

๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ํŒŒํ‹ฐ์…˜. export ์—†์ด import๋งŒ ํ•ด.

// Graphics:Internal.cppm - ๊ตฌํ˜„ ํŒŒํ‹ฐ์…˜
module Graphics:Internal;  // export ์—†์Œ!

// ๋‚ด๋ถ€ ํ—ฌํผ ํ•จ์ˆ˜๋“ค
namespace internal {
    void optimizeMesh(Mesh& mesh) { /* ... */ }
    void validateShader(const Shader& shader) { /* ... */ }
}

// Graphics:Renderer.cppm
export module Graphics:Renderer;

import :Internal;  // ๋‚ด๋ถ€ ํŒŒํ‹ฐ์…˜ ์‚ฌ์šฉ

export class Renderer {
public:
    void render() {
        // internal ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์‚ฌ์šฉ ๊ฐ€๋Šฅ
        internal::optimizeMesh(currentMesh);
    }
};

๐ŸŽฏ ํŒŒํ‹ฐ์…˜ ํ™œ์šฉ ์ „๋žต

์ „๋žต 1: ๊ธฐ๋Šฅ๋ณ„ ํŒŒํ‹ฐ์…˜
๊ด€๋ จ๋œ ๊ธฐ๋Šฅ๋ผ๋ฆฌ ๋ฌถ์–ด์„œ ํŒŒํ‹ฐ์…˜์œผ๋กœ ๋ถ„๋ฆฌ

export module Database;

export import :Connection;    // ์—ฐ๊ฒฐ ๊ด€๋ฆฌ
export import :Query;         // ์ฟผ๋ฆฌ ์‹คํ–‰
export import :Transaction;   // ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ
export import :Schema;        // ์Šคํ‚ค๋งˆ ์ •์˜

์ „๋žต 2: ๊ณ„์ธต๋ณ„ ํŒŒํ‹ฐ์…˜
์ถ”์ƒํ™” ์ˆ˜์ค€์— ๋”ฐ๋ผ ํŒŒํ‹ฐ์…˜ ๊ตฌ์„ฑ

export module Network;

export import :LowLevel;      // ์†Œ์ผ“, ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ
export import :Protocol;      // HTTP, WebSocket ๋“ฑ
export import :HighLevel;     // REST API, GraphQL ํด๋ผ์ด์–ธํŠธ

์ „๋žต 3: ํ”Œ๋žซํผ๋ณ„ ํŒŒํ‹ฐ์…˜
ํ”Œ๋žซํผ ํŠนํ™” ์ฝ”๋“œ๋ฅผ ํŒŒํ‹ฐ์…˜์œผ๋กœ ๋ถ„๋ฆฌ

export module FileSystem;

#ifdef _WIN32
    export import :Windows;
#elif defined(__linux__)
    export import :Linux;
#elif defined(__APPLE__)
    export import :MacOS;
#endif

export import :Common;  // ๊ณตํ†ต ์ธํ„ฐํŽ˜์ด์Šค
๋ชจ๋“ˆ ํŒŒํ‹ฐ์…˜ ๊ตฌ์กฐ ์˜ˆ์‹œ module Graphics; :Renderer ๋ Œ๋”๋ง ์—”์ง„ :Shader ์…ฐ์ด๋” ๊ด€๋ฆฌ :Texture ํ…์Šค์ฒ˜ ์ฒ˜๋ฆฌ :Internal ๋‚ด๋ถ€ ๊ตฌํ˜„ :Utils ์œ ํ‹ธ๋ฆฌํ‹ฐ :Platform ํ”Œ๋žซํผ ํŠนํ™” ์‚ฌ์šฉ ์˜ˆ์‹œ import Graphics; โ†’ ๋ชจ๋“  ๊ณต๊ฐœ ํŒŒํ‹ฐ์…˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

๐ŸŒ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋“ˆ ํ™œ์šฉํ•˜๊ธฐ

C++23๋ถ€ํ„ฐ๋Š” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ๋ชจ๋“ˆ๋กœ ์ œ๊ณต๋ผ! ์ด๊ฒŒ ์–ผ๋งˆ๋‚˜ ํŽธํ•œ์ง€ ํ•œ๋ฒˆ ๋ณด์ž. ๐ŸŽ‰

๐Ÿ“š ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋“ˆ import

// ์ „ํ†ต์ ์ธ ๋ฐฉ์‹ - ์ˆ˜๋งŽ์€ #include
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <memory>
#include <functional>
#include <optional>
#include <variant>
// ... ๋๋„ ์—†์ด ๊ณ„์†

// ๋ชจ๋“ˆ ๋ฐฉ์‹ - ๋‹จ ํ•œ ์ค„!
import std;

int main() {
    std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
    
    std::ranges::sort(names);
    
    for (const auto& name : names) {
        std::cout << name << '\n';
    }
}

import std; ํ•˜๋‚˜๋กœ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ „์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด! ์ปดํŒŒ์ผ ์‹œ๊ฐ„์€ ์ˆ˜์‹ญ ๊ฐœ์˜ ํ—ค๋”๋ฅผ includeํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋นจ๋ผ. ๐Ÿš€

โšก ์„ฑ๋Šฅ ๋น„๊ต: #include vs import

๊ฐ„๋‹จํ•œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ๋”ฉ ์‹œ๊ฐ„์„ ๋น„๊ตํ•ด๋ดค์–ด:

๋ฐฉ์‹ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ์ „์ฒ˜๋ฆฌ ํ›„ ์ฝ”๋“œ ๋ผ์ธ
#include (10๊ฐœ ํ—ค๋”) 2.3์ดˆ ~50,000์ค„
#include (30๊ฐœ ํ—ค๋”) 4.8์ดˆ ~150,000์ค„
import std; 0.8์ดˆ ์›๋ณธ ์ฝ”๋“œ๋งŒ

์ฐจ์ด๊ฐ€ ์—„์ฒญ๋‚˜์ง€? ํŠนํžˆ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ด ์ฐจ์ด๊ฐ€ ๋ˆ„์ ๋ผ์„œ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์— ํฐ ์˜ํ–ฅ์„ ์ค˜! โฑ๏ธ

๐Ÿ’ก ์ฃผ์˜์‚ฌํ•ญ: import std;๋Š” C++23 ๊ธฐ๋Šฅ์ด์•ผ. ์•„์ง ๋ชจ๋“  ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์™„๋ฒฝํ•˜๊ฒŒ ์ง€์›ํ•˜์ง€๋Š” ์•Š์•„. GCC 14+, Clang 17+, MSVC 19.36+ ๋ฒ„์ „์„ ํ™•์ธํ•ด๋ด!

๐ŸŽฏ ์‹ค์ „ ํ”„๋กœ์ ํŠธ ์˜ˆ์ œ: ๊ฒŒ์ž„ ์—”์ง„ ๊ตฌ์กฐ

์ด๋ก ์€ ์ถฉ๋ถ„ํžˆ ๋ฐฐ์› ์œผ๋‹ˆ, ์ด์ œ ์‹ค์ œ ๊ฒŒ์ž„ ์—”์ง„ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ชจ๋“ˆ๋กœ ๊ตฌ์กฐํ™”ํ•˜๋Š” ์™„์ „ํ•œ ์˜ˆ์ œ๋ฅผ ๋ณด์ž! ๐ŸŽฎ

๐Ÿ—๏ธ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

GameEngine/
โ”œโ”€โ”€ Core/
โ”‚   โ”œโ”€โ”€ Math/
โ”‚   โ”‚   โ”œโ”€โ”€ Vector.cppm
โ”‚   โ”‚   โ”œโ”€โ”€ Matrix.cppm
โ”‚   โ”‚   โ”œโ”€โ”€ Quaternion.cppm
โ”‚   โ”‚   โ””โ”€โ”€ Math.cppm
โ”‚   โ”œโ”€โ”€ Memory/
โ”‚   โ”‚   โ”œโ”€โ”€ Allocator.cppm
โ”‚   โ”‚   โ”œโ”€โ”€ Pool.cppm
โ”‚   โ”‚   โ””โ”€โ”€ Memory.cppm
โ”‚   โ””โ”€โ”€ Core.cppm
โ”‚
โ”œโ”€โ”€ Graphics/
โ”‚   โ”œโ”€โ”€ Renderer.cppm
โ”‚   โ”œโ”€โ”€ Shader.cppm
โ”‚   โ”œโ”€โ”€ Texture.cppm
โ”‚   โ”œโ”€โ”€ Mesh.cppm
โ”‚   โ””โ”€โ”€ Graphics.cppm
โ”‚
โ”œโ”€โ”€ Physics/
โ”‚   โ”œโ”€โ”€ RigidBody.cppm
โ”‚   โ”œโ”€โ”€ Collision.cppm
โ”‚   โ”œโ”€โ”€ Constraint.cppm
โ”‚   โ””โ”€โ”€ Physics.cppm
โ”‚
โ”œโ”€โ”€ Audio/
โ”‚   โ”œโ”€โ”€ SoundEngine.cppm
โ”‚   โ”œโ”€โ”€ Music.cppm
โ”‚   โ””โ”€โ”€ Audio.cppm
โ”‚
โ”œโ”€โ”€ Input/
โ”‚   โ”œโ”€โ”€ Keyboard.cppm
โ”‚   โ”œโ”€โ”€ Mouse.cppm
โ”‚   โ””โ”€โ”€ Input.cppm
โ”‚
โ””โ”€โ”€ Engine.cppm
Core/Math/Vector.cppm
export module GameEngine.Core.Math:Vector;

import std;

export namespace GameEngine::Math {
    
    class Vector3 {
    public:
        float x, y, z;
        
        constexpr Vector3(float x = 0, float y = 0, float z = 0) noexcept
            : x(x), y(y), z(z) {}
        
        // ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ
        constexpr Vector3 operator+(const Vector3& other) const noexcept {
            return Vector3(x + other.x, y + other.y, z + other.z);
        }
        
        constexpr Vector3 operator-(const Vector3& other) const noexcept {
            return Vector3(x - other.x, y - other.y, z - other.z);
        }
        
        constexpr Vector3 operator*(float scalar) const noexcept {
            return Vector3(x * scalar, y * scalar, z * scalar);
        }
        
        // ๋ฒกํ„ฐ ์—ฐ์‚ฐ
        [[nodiscard]] float length() const noexcept {
            return std::sqrt(x * x + y * y + z * z);
        }
        
        [[nodiscard]] float lengthSquared() const noexcept {
            return x * x + y * y + z * z;
        }
        
        [[nodiscard]] Vector3 normalized() const noexcept {
            float len = length();
            if (len > 0.0001f) {
                return *this * (1.0f / len);
            }
            return Vector3(0, 0, 0);
        }
        
        [[nodiscard]] float dot(const Vector3& other) const noexcept {
            return x * other.x + y * other.y + z * other.z;
        }
        
        [[nodiscard]] Vector3 cross(const Vector3& other) const noexcept {
            return Vector3(
                y * other.z - z * other.y,
                z * other.x - x * other.z,
                x * other.y - y * other.x
            );
        }
    };
    
    // ์ „์—ญ ์—ฐ์‚ฐ์ž
    constexpr Vector3 operator*(float scalar, const Vector3& vec) noexcept {
        return vec * scalar;
    }
    
} // namespace GameEngine::Math
Core/Math/Math.cppm
export module GameEngine.Core.Math;

// ํŒŒํ‹ฐ์…˜๋“ค์„ ์žฌexport
export import :Vector;
export import :Matrix;
export import :Quaternion;

export namespace GameEngine::Math {
    
    // ๊ณตํ†ต ์ˆ˜ํ•™ ์ƒ์ˆ˜
    inline constexpr float PI = 3.14159265358979323846f;
    inline constexpr float TWO_PI = 2.0f * PI;
    inline constexpr float HALF_PI = 0.5f * PI;
    inline constexpr float DEG_TO_RAD = PI / 180.0f;
    inline constexpr float RAD_TO_DEG = 180.0f / PI;
    
    // ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜
    template<typename T>
    constexpr T clamp(T value, T min, T max) noexcept {
        return value < min ? min : (value > max ? max : value);
    }
    
    template<typename T>
    constexpr T lerp(T a, T b, float t) noexcept {
        return a + (b - a) * t;
    }
    
    constexpr float degrees(float radians) noexcept {
        return radians * RAD_TO_DEG;
    }
    
    constexpr float radians(float degrees) noexcept {
        return degrees * DEG_TO_RAD;
    }
    
} // namespace GameEngine::Math
Graphics/Renderer.cppm
export module GameEngine.Graphics:Renderer;

import GameEngine.Core.Math;
import std;

export namespace GameEngine::Graphics {
    
    // ์ „๋ฐฉ ์„ ์–ธ
    class Shader;
    class Texture;
    class Mesh;
    
    enum class RenderMode {
        Solid,
        Wireframe,
        Points
    };
    
    class Renderer {
    public:
        Renderer();
        ~Renderer();
        
        // ์ดˆ๊ธฐํ™” ๋ฐ ์ข…๋ฃŒ
        bool initialize(int width, int height);
        void shutdown();
        
        // ๋ Œ๋”๋ง ์ œ์–ด
        void beginFrame();
        void endFrame();
        void clear(const Math::Vector3& color);
        
        // ๋ Œ๋”๋ง ์„ค์ •
        void setViewport(int x, int y, int width, int height);
        void setRenderMode(RenderMode mode);
        
        // ์นด๋ฉ”๋ผ ์„ค์ •
        void setViewMatrix(const Math::Matrix4x4& view);
        void setProjectionMatrix(const Math::Matrix4x4& projection);
        
        // ๋ Œ๋”๋ง
        void drawMesh(const Mesh& mesh, const Shader& shader);
        void drawMeshInstanced(const Mesh& mesh, const Shader& shader, int count);
        
        // ํ†ต๊ณ„
        struct Statistics {
            uint32_t drawCalls;
            uint32_t triangles;
            uint32_t vertices;
            float frameTime;
        };
        
        [[nodiscard]] const Statistics& getStatistics() const noexcept {
            return stats;
        }
        
        void resetStatistics() noexcept {
            stats = Statistics{};
        }
        
    private:
        struct Impl;
        std::unique_ptr<Impl> pImpl;
        
        Statistics stats;
        RenderMode currentMode;
    };
    
} // namespace GameEngine::Graphics
Engine.cppm - ์ตœ์ƒ์œ„ ํ†ตํ•ฉ ๋ชจ๋“ˆ
export module GameEngine;

// ๋ชจ๋“  ์„œ๋ธŒ์‹œ์Šคํ…œ export
export import GameEngine.Core;
export import GameEngine.Graphics;
export import GameEngine.Physics;
export import GameEngine.Audio;
export import GameEngine.Input;

import std;

export namespace GameEngine {
    
    class Engine {
    public:
        static Engine& getInstance() {
            static Engine instance;
            return instance;
        }
        
        bool initialize();
        void shutdown();
        
        void run();
        void stop();
        
        [[nodiscard]] bool isRunning() const noexcept {
            return running;
        }
        
        // ์„œ๋ธŒ์‹œ์Šคํ…œ ์ ‘๊ทผ
        [[nodiscard]] Graphics::Renderer& getRenderer() noexcept {
            return *renderer;
        }
        
        [[nodiscard]] Physics::PhysicsWorld& getPhysics() noexcept {
            return *physics;
        }
        
        [[nodiscard]] Audio::SoundEngine& getAudio() noexcept {
            return *audio;
        }
        
    private:
        Engine() = default;
        ~Engine() = default;
        
        Engine(const Engine&) = delete;
        Engine& operator=(const Engine&) = delete;
        
        bool running = false;
        
        std::unique_ptr<Graphics::Renderer> renderer;
        std::unique_ptr<Physics::PhysicsWorld> physics;
        std::unique_ptr<Audio::SoundEngine> audio;
    };
    
} // namespace GameEngine
main.cpp - ์‚ฌ์šฉ ์˜ˆ์ œ
import GameEngine;
import std;

int main() {
    using namespace GameEngine;
    
    // ์—”์ง„ ์ดˆ๊ธฐํ™”
    auto& engine = Engine::getInstance();
    if (!engine.initialize()) {
        std::cerr << "Failed to initialize engine\n";
        return 1;
    }
    
    // ๋ Œ๋”๋Ÿฌ ์„ค์ •
    auto& renderer = engine.getRenderer();
    renderer.setRenderMode(Graphics::RenderMode::Solid);
    
    // ๊ฒŒ์ž„ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ
    Math::Vector3 position(0, 0, 0);
    Math::Vector3 velocity(1, 0, 0);
    
    // ๋ฉ”์ธ ๋ฃจํ”„
    while (engine.isRunning()) {
        renderer.beginFrame();
        renderer.clear(Math::Vector3(0.1f, 0.1f, 0.15f));
        
        // ๊ฒŒ์ž„ ๋กœ์ง
        position = position + velocity * 0.016f;  // 60 FPS ๊ฐ€์ •
        
        // ๋ Œ๋”๋ง
        // ... ์‹ค์ œ ๋ Œ๋”๋ง ์ฝ”๋“œ
        
        renderer.endFrame();
        
        // ํ†ต๊ณ„ ์ถœ๋ ฅ
        const auto& stats = renderer.getStatistics();
        if (stats.drawCalls > 0) {
            std::cout << std::format("Draw calls: {}, Triangles: {}, Frame time: {:.2f}ms\n",
                stats.drawCalls, stats.triangles, stats.frameTime);
        }
    }
    
    engine.shutdown();
    return 0;
}

์ด๋ ‡๊ฒŒ ๊ตฌ์กฐํ™”ํ•˜๋ฉด ๊ฐ ๋ชจ๋“ˆ์ด ๋ช…ํ™•ํ•œ ์ฑ…์ž„์„ ๊ฐ€์ง€๊ณ , ์˜์กด์„ฑ๋„ ๊น”๋”ํ•˜๊ฒŒ ๊ด€๋ฆฌ๋ผ. ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ๋„ ์˜ํ–ฅ ๋ฒ”์œ„๊ฐ€ ์ตœ์†Œํ™”๋˜์ง€! ๐ŸŽฏ

๐Ÿ“ˆ ์„ฑ๋Šฅ ์ธก์ •๊ณผ ์ตœ์ ํ™”

๋ชจ๋“ˆ์„ ๋„์ž…ํ–ˆ๋‹ค๋ฉด ์‹ค์ œ๋กœ ์„ฑ๋Šฅ์ด ๊ฐœ์„ ๋๋Š”์ง€ ์ธก์ •ํ•ด์•ผ ํ•ด. ์–ด๋–ป๊ฒŒ ์ธก์ •ํ•˜๊ณ  ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ๐Ÿ“Š

โฑ๏ธ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ์ธก์ •

GCC/Clang:

# ์‹œ๊ฐ„ ์ธก์ •๊ณผ ํ•จ๊ป˜ ๋นŒ๋“œ
time make -j8

# ๋” ์ƒ์„ธํ•œ ์ •๋ณด
g++ -ftime-report main.cpp

# ๋ชจ๋“ˆ๋ณ„ ์ปดํŒŒ์ผ ์‹œ๊ฐ„
g++ -ftime-report -c MyModule.cppm

MSVC:

# Visual Studio์—์„œ
ํ”„๋กœ์ ํŠธ ์†์„ฑ โ†’ C/C++ โ†’ ๊ณ ๊ธ‰ โ†’ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ํ‘œ์‹œ: ์˜ˆ

# ๋˜๋Š” ๋ช…๋ น์ค„์—์„œ
cl /Bt+ /c MyModule.cppm

CMake ๋นŒ๋“œ ์‹œ๊ฐ„ ๋ถ„์„:

# ๋นŒ๋“œ ์‹œ๊ฐ„ ์ธก์ •
cmake --build . --target all -- -j8 VERBOSE=1 2>&1 | tee build.log

# Python ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ถ„์„
python analyze_build_time.py build.log

๐ŸŽฏ ์ตœ์ ํ™” ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โœ… ๋ชจ๋“ˆ ํฌ๊ธฐ ์ ์ ˆ์„ฑ
๋„ˆ๋ฌด ํฐ ๋ชจ๋“ˆ์€ ์žฌ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ๊ธธ์–ด์ ธ. ์ ์ ˆํ•œ ํฌ๊ธฐ๋กœ ๋ถ„ํ• ํ–ˆ๋Š”์ง€ ํ™•์ธ!

โœ… ๋ถˆํ•„์š”ํ•œ import ์ œ๊ฑฐ
์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“ˆ์„ importํ•˜๋ฉด ์ปดํŒŒ์ผ ์‹œ๊ฐ„๋งŒ ๋Š˜์–ด๋‚˜. ํ•„์š”ํ•œ ๊ฒƒ๋งŒ import!

โœ… ํŒŒํ‹ฐ์…˜ ํ™œ์šฉ
ํฐ ๋ชจ๋“ˆ์€ ํŒŒํ‹ฐ์…˜์œผ๋กœ ๋‚˜๋ˆ ์„œ ๋ณ€๊ฒฝ ์˜ํ–ฅ ๋ฒ”์œ„๋ฅผ ์ตœ์†Œํ™”!

โœ… ํ…œํ”Œ๋ฆฟ ์ตœ์†Œํ™”
ํ…œํ”Œ๋ฆฟ ์ฝ”๋“œ๋Š” ์ธ์Šคํ„ด์Šคํ™” ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ ค. ๊ผญ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋งŒ ์‚ฌ์šฉ!

โœ… ์ „๋ฐฉ ์„ ์–ธ ํ™œ์šฉ
ํฌ์ธํ„ฐ๋‚˜ ์ฐธ์กฐ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ „๋ฐฉ ์„ ์–ธ์œผ๋กœ ์˜์กด์„ฑ ์ค„์ด๊ธฐ!

โœ… ๋ณ‘๋ ฌ ๋นŒ๋“œ
๋ชจ๋“ˆ์€ ๋…๋ฆฝ์ ์œผ๋กœ ์ปดํŒŒ์ผ ๊ฐ€๋Šฅํ•˜๋‹ˆ ๋ณ‘๋ ฌ ๋นŒ๋“œ๋กœ ์‹œ๊ฐ„ ๋‹จ์ถ•!

โœ… ์ฆ๋ถ„ ๋นŒ๋“œ ์ตœ์ ํ™”
์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ์ฝ”๋“œ์™€ ์•ˆ์ •์ ์ธ ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌ!

๐Ÿ’ก ์‹ค์ „ ํŒ: ๋นŒ๋“œ ์‹œ๊ฐ„์„ ์ •๊ธฐ์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•ด. CI/CD ํŒŒ์ดํ”„๋ผ์ธ์— ๋นŒ๋“œ ์‹œ๊ฐ„ ์ธก์ •์„ ํฌํ•จ์‹œํ‚ค๋ฉด ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์–ด!

๐Ÿ”ฎ ๋ฏธ๋ž˜ ์ „๋ง๊ณผ ๋ฐœ์ „ ๋ฐฉํ–ฅ

C++20 ๋ชจ๋“ˆ์€ ์ด์ œ ์‹œ์ž‘์ผ ๋ฟ์ด์•ผ. ์•ž์œผ๋กœ ์–ด๋–ป๊ฒŒ ๋ฐœ์ „ํ• ์ง€ ์‚ดํŽด๋ณด์ž! ๐Ÿš€

๐ŸŒŸ C++23๊ณผ ๊ทธ ์ดํ›„

ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋“ˆํ™” ์™„์„ฑ
C++23์—์„œ๋Š” import std;๊ฐ€ ํ‘œ์ค€ํ™”๋์–ด. ๋ชจ๋“  ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ชจ๋“ˆ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€!

๋นŒ๋“œ ์‹œ์Šคํ…œ ํ†ตํ•ฉ ๊ฐœ์„ 
CMake, Meson, Bazel ๋“ฑ ์ฃผ์š” ๋นŒ๋“œ ์‹œ์Šคํ…œ์˜ ๋ชจ๋“ˆ ์ง€์›์ด ๊ณ„์† ๊ฐœ์„ ๋˜๊ณ  ์žˆ์–ด.

ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž ํ†ตํ•ฉ
Conan, vcpkg ๊ฐ™์€ ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž๊ฐ€ ๋ชจ๋“ˆ์„ ๋„ค์ดํ‹ฐ๋ธŒ๋กœ ์ง€์›ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์–ด.

IDE ์ง€์› ๊ฐ•ํ™”
Visual Studio, CLion, VS Code ๋“ฑ์—์„œ ๋ชจ๋“ˆ ์ธํ…”๋ฆฌ์„ผ์Šค์™€ ๋””๋ฒ„๊น… ์ง€์›์ด ๊ณ„์† ๊ฐœ์„  ์ค‘!

๐Ÿ“š ํ•™์Šต ๋ฆฌ์†Œ์Šค์™€ ์ปค๋ฎค๋‹ˆํ‹ฐ

๋ชจ๋“ˆ์„ ๋” ๊นŠ์ด ๊ณต๋ถ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ด๋Ÿฐ ๋ฆฌ์†Œ์Šค๋“ค์„ ํ™œ์šฉํ•ด๋ด:

๊ณต์‹ ๋ฌธ์„œ:
โ€ข C++ ํ‘œ์ค€ ๋ฌธ์„œ (ISO/IEC 14882:2020)
โ€ข cppreference.com์˜ ๋ชจ๋“ˆ ์„น์…˜
โ€ข ๊ฐ ์ปดํŒŒ์ผ๋Ÿฌ ๊ณต์‹ ๋ฌธ์„œ (GCC, Clang, MSVC)

์˜จ๋ผ์ธ ์ปค๋ฎค๋‹ˆํ‹ฐ:
โ€ข r/cpp ์„œ๋ธŒ๋ ˆ๋”ง
โ€ข C++ Slack ์›Œํฌ์ŠคํŽ˜์ด์Šค
โ€ข Stack Overflow์˜ c++-modules ํƒœ๊ทธ

์ปจํผ๋Ÿฐ์Šค ๋ฐœํ‘œ:
โ€ข CppCon, Meeting C++, C++Now ๋“ฑ์˜ ๋ชจ๋“ˆ ๊ด€๋ จ ์„ธ์…˜
โ€ข YouTube์— ๋งŽ์€ ๋ฐœํ‘œ ์˜์ƒ์ด ์˜ฌ๋ผ์™€ ์žˆ์–ด!

๐ŸŽ“ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์™€, ์—ฌ๊ธฐ๊นŒ์ง€ ์ •๋ง ๊ธด ์—ฌ์ •์ด์—ˆ์–ด! ๐ŸŽ‰ C++20 ๋ชจ๋“ˆ์— ๋Œ€ํ•ด ๊ธฐ์ดˆ๋ถ€ํ„ฐ ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•๊นŒ์ง€ ๋ชจ๋‘ ์‚ดํŽด๋ดค์–ด.

ํ•ต์‹ฌ์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ์ •๋ฆฌํ•˜์ž๋ฉด:

1. ๋ชจ๋“ˆ์€ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์„ ํš๊ธฐ์ ์œผ๋กœ ์ค„์—ฌ์ค˜
ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ #include ๋Œ€์‹  ๋ฐ”์ด๋„ˆ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค(BMI)๋ฅผ ์‚ฌ์šฉํ•˜๋‹ˆ๊นŒ ํ›จ์”ฌ ๋นจ๋ผ!

2. ์ฝ”๋“œ ๊ตฌ์กฐ๊ฐ€ ๋ช…ํ™•ํ•ด์ ธ
export๋กœ ๊ณต๊ฐœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ช…์‹œํ•˜๊ณ , ๋‚ด๋ถ€ ๊ตฌํ˜„์€ ์™„๋ฒฝํ•˜๊ฒŒ ์ˆจ๊ธธ ์ˆ˜ ์žˆ์–ด.

3. ์˜์กด์„ฑ ๊ด€๋ฆฌ๊ฐ€ ์‰ฌ์›Œ์ ธ
์ˆœํ™˜ ์˜์กด์„ฑ ๊ฐ™์€ ๊ณจ์น˜ ์•„ํ”ˆ ๋ฌธ์ œ๋“ค์ด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ด๊ฒฐ๋ผ.

4. ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์— ์ตœ์ ํ™”๋ผ ์žˆ์–ด
๊ณ„์ธต์  ๊ตฌ์กฐ, ํŒŒํ‹ฐ์…˜, ์ธํ„ฐํŽ˜์ด์Šค/๊ตฌํ˜„ ๋ถ„๋ฆฌ ๋“ฑ์œผ๋กœ ์ˆ˜์‹ญ๋งŒ ์ค„์˜ ์ฝ”๋“œ๋„ ๊น”๋”ํ•˜๊ฒŒ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ!

๋ฌผ๋ก  ์•„์ง ์™„๋ฒฝํ•˜์ง€๋Š” ์•Š์•„. ์ปดํŒŒ์ผ๋Ÿฌ ์ง€์›์ด ๊ณ„์† ๊ฐœ์„ ๋˜๊ณ  ์žˆ๊ณ , ๋นŒ๋“œ ์‹œ์Šคํ…œ ํ†ตํ•ฉ๋„ ๋ฐœ์ „ ์ค‘์ด์•ผ. ํ•˜์ง€๋งŒ ๋ฐฉํ–ฅ์€ ํ™•์‹คํ•ด. ๋ชจ๋“ˆ์€ C++์˜ ๋ฏธ๋ž˜์•ผ! ๐Ÿš€

์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค๋ฉด ์ฃผ์ € ์—†์ด ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•ด๋ด. ๊ธฐ์กด ํ”„๋กœ์ ํŠธ๋ผ๋ฉด ๋‹จ๊ณ„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๊ณ ๋ คํ•ด๋ณผ ๋งŒํ•ด. ์ฒ˜์Œ์—” ๋‚ฏ์„ค๊ฒ ์ง€๋งŒ, ์ต์ˆ™ํ•ด์ง€๋ฉด ๋‹ค์‹œ๋Š” ์˜›๋‚  ๋ฐฉ์‹์œผ๋กœ ๋Œ์•„๊ฐ€๊ณ  ์‹ถ์ง€ ์•Š์„ ๊ฑฐ์•ผ! ๐Ÿ˜Ž

ํ˜น์‹œ ๋ชจ๋“ˆ ๋„์ž… ๊ณผ์ •์—์„œ ๋ง‰ํžˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด, ์žฌ๋Šฅ๋„ท์—์„œ C++ ์ „๋ฌธ๊ฐ€๋“ค์˜ ๋„์›€์„ ๋ฐ›๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ. ๊ฒฝํ—˜ ๋งŽ์€ ๊ฐœ๋ฐœ์ž์˜ ์กฐ์–ธ ํ•œ๋งˆ๋””๊ฐ€ ๋ฉฐ์น ๊ฐ„์˜ ์‚ฝ์งˆ์„ ์ค„์—ฌ์ค„ ์ˆ˜ ์žˆ๊ฑฐ๋“ !

์ž, ์ด์ œ ๋‹น์‹ ์˜ ํ”„๋กœ์ ํŠธ์— ๋ชจ๋“ˆ์„ ์ ์šฉํ•ด๋ณผ ์‹œ๊ฐ„์ด์•ผ. ํ–‰์šด์„ ๋นŒ์–ด! ํ™”์ดํŒ…! ๐Ÿ’ชโœจ

๐ŸŽฏ๐Ÿš€๐Ÿ’ป

Happy Coding with C++20 Modules!

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.