# Boost에서 시작된 `std::optional` – C++26까지의 진화와 실전 활용법

---

# # 서론 – “값이 없을 수도 있다”를 어떻게 표현할까?

C++에서 함수가 **값을 반환하지 않을 수도** 있다는 상황을 어떻게 표현하나요?

예전에는 `nullptr`, 특수한 마법 상수, 혹은 서드파티 라이브러리인 **Boost.Optional**을 사용했지만, 코드가 복잡해지고 가독성이 떨어지는 문제가 있었습니다.

2025년 CppCon에서 Steve Downey가 발표한 *“The Evolution of std::optional – From Boost to C++26”* 를 계기로, **표준 라이브러리**에 포함된 `std::optional`이 어떻게 탄생하고, C++26에서 어떤 새로운 기능을 제공하게 되었는지 살펴보겠습니다. 초보자도 바로 이해하고 적용할 수 있도록 단계별로 정리했습니다.

---

# # 1️⃣ Boost.Optional – 표준이 되기 전 첫 번째 선택지

| 특징 | 장점 | 한계 |

|------|------|------|

| `boost::optional<T>` | - 값이 없을 때 `nullopt` 로 명시<br>- `has_value()`, `operator*` 로 안전한 접근 | - 별도 라이브러리 설치·링크 필요<br>- 표준과 일관성 부족 (예: `operator==` 자동 생성 안 됨) |

| **사용 예** | 
```
cpp<br>#include <boost/optional.hpp><br>boost::optional<int> opt = 5;<br>if (opt) std::cout << *opt;
```
 |  |

Boost.Optional은 **“값이 존재하거나 존재하지 않을 수 있다”**는 의도를 타입 시스템에 명시해 주는 첫 번째 시도였으며, 많은 프로젝트에서 임시 해결책으로 활용되었습니다. 하지만 **빌드 복잡도**와 **표준화된 인터페이스 부재**가 점점 더 큰 장애물로 다가왔습니다.

---

# # 2️⃣ `std::optional`이 표준에 채택된 과정

| 연도 | 주요 사건 |

|------|-----------|

| 2014 | C++14 회의에서 `optional` 초안 제안 |

| 2015 | N4387 “Optional object for C++” 초안 발표 |

| 2017 | **C++17** 정식 표준에 `std::optional` 포함 |

| 2020 | `constexpr` 지원 확대 (C++20) |

| 2025 | **C++26** 에서 `transform`, `or_else`, `swap` 등 신규 멤버 함수 도입 |

## # 핵심 변화

1. **constexpr 확대** – 컴파일 타임에 `optional`을 만들고 변형할 수 있어 메타프로그래밍이 쉬워졌다.

2. **비교 연산 자동 생성** – `==`, `!=` 가 기본 제공돼 코드가 간결해졌다.

3. **C++26 신규 API** – 함수형 스타일을 지원하는 `transform`·`or_else`가 추가돼 **지연 평가**와 **체이닝**이 가능해졌다.

이러한 진화 덕분에 `std::optional`은 이제 **표준적인, 가볍고 안전한** “값이 없을 수도 있는” 타입으로 자리 잡았습니다.

---

# # 3️⃣ C++26에서 새롭게 추가된 기능 3가지

## # 3.1 `transform` – 함수형 매핑

```
cpp

std::optional<int> opt = 10;

auto doubled = opt.transform([](int v){ return v * 2; }); // doubled == std::optional<int>{20}

```

- `opt`가 값이 있으면 람다를 적용하고, 없으면 빈 `optional`을 그대로 반환합니다.

- 여러 변환을 **파이프라인**처럼 연결할 수 있어 코드가 직관적입니다.

## # 3.2 `or_else` – 지연 평가형 대체값

```
cpp

std::optional<std::string> name = std::nullopt;

auto result = name.or_else([]{

    // 복잡한 연산을 여기서만 수행

    return std::make_optional<std::string>('Anonymous');

});

```

- 기존 `value_or`와 달리 콜백이 **필요할 때만** 실행되므로 비용이 큰 연산을 안전하게 지연시킬 수 있습니다.

## # 3.3 `swap` – 명시적 교환

```
cpp

std::optional<int> a = 5, b = std::nullopt;

a.swap(b); // a = nullopt, b = 5

```

- `std::swap`보다 명시적이며, `noexcept` 보장이 있어 예외 안전성을 강화합니다.

---

# # 4️⃣ 실전 예제 – 파일 읽기 함수에 `std::optional` 적용하기

아래 코드는 파일을 열고 첫 번째 라인을 읽어 `std::optional<std::string>` 로 반환합니다.

C++17 이전에는 `boost::optional`이나 `nullptr` 체크가 필요했지만, 이제는 한 줄 코드로 충분합니다.

```
cpp

# include <optional>

# include <fstream>

# include <string>

# include <iostream>

std::optional<std::string> read_first_line(const std::string& path)

{
    std::ifstream file(path);

    if (!file) return std::nullopt;          // 파일 열기에 실패하면 빈 optional 반환

    std::string line;

    if (std::getline(file, line))

        return line;                         // 성공 → 값이 있는 optional 반환

    return std::nullopt;                    // 파일이 비어 있어도 빈 optional 반환

}

// C++26에서 transform·or_else 활용

void demo(const std::string& path)

{
    auto upper = read_first_line(path)

        .transform([](auto&& s){            // 첫 라인을 대문자로 변환

            std::string r;

            for (char c : s) r += std::toupper(c);

            return r;

        })

        .or_else([]{ return std::make_optional<std::string>('NO DATA'); });

    std::cout << 'Result: ' << *upper << '\n';

}

```

- `std::nullopt` 로 **값이 없음을 명시**합니다.

- `transform` 은 값이 있을 때만 변환 로직을 실행하고, `or_else` 로 **지연 평가**된 대체값을 제공합니다.

초보자도 위 코드를 그대로 복사해 프로젝트에 넣어 보면, **안전하고 가독성 좋은** 옵션 처리를 바로 체험할 수 있습니다.

---

# # 5️⃣ `std::optional`을 팀에 도입하는 체크리스트

| 체크 항목 | 설명 | 적용 팁 |

|----------|------|--------|

| **컴파일러 옵션** | `-std=c++17` 이상 (C++26 사용 시 `-std=c++26`) | 최신 GCC/Clang/MSVC 사용 |

| **코드 리뷰** | `optional` 사용 시 `has_value()` 검증을 반드시 포함 | 리뷰 체크리스트에 `optional` 항목 추가 |

| **테스트** | `nullopt` 경로와 정상값 경로 모두 테스트 | 구체적인 `EXPECT_TRUE(opt.has_value())` 작성 |

| **문서화** | API 문서에 `optional` 반환 규칙 명시 | Doxygen 주석에 `@return std::optional<T>` 표기 |

| **성능 측정** | `constexpr` 활용 시 컴파일 타임 비용 확인 | `-O2`/`-O3` 옵션과 함께 `benchmark` 실행 |

---

# # 결론 – 지금 바로 `std::optional`을 활용해 코드 품질을 높이세요!

`Boost.Optional`에서 시작해 **C++26**에 이르는 `std::optional`은 **값이 없을 수도 있는 상황을 명시적으로** 표현하고, **함수형 스타일**까지 지원하는 강력한 도구가 되었습니다.

1️⃣ **표준화**로 빌드 복잡도가 사라지고,

2️⃣ **constexpr**와 **새 API**로 컴파일 타임 활용도가 높아지며,

3️⃣ **안전한 접근**과 **자동 충돌 방지**가 기본 제공됩니다.

> **행동 유도**

> - 오늘 프로젝트에 `std::optional`을 **하나**라도 도입해 보세요. (예: 파일 입출력, 설정값 파싱)

> - `transform`·`or_else`를 사용해 **지연 평가**와 **체이닝**을 연습해 보세요.

> - 팀 회고 때 “우리 코드에서 `optional`을 더 사용할 수 있는 부분은?”을 질문 리스트에 추가해, 점진적으로 적용 범위를 넓혀갑시다.

`std::optional`을 제대로 활용한다면 **버그는 줄고, 가독성은 올라가며, 유지보수 비용은 크게 감소**합니다. 이제는 “값이 없을 수도 있다”는 상황을 **표준적인 방법**으로 처리할 차례입니다.

---

**SEO 키워드**: `std::optional`, `C++26`, `Boost.Optional`
