반응형
지금까지 우리는 생성, 구조적 패턴들을 모던 C++ 관점에서 재해석하며 상속 계층, 가상 함수 테이블, 복잡한 클래스 증가 대신 Concepts, 람다, 함수 합성, std::expected, std::format, Ranges, std::variant 등을 활용해 더 간결하고 타입 안전하며 유지보수성 높은 코드를 작성할 수 있음을 확인했습니다. 이제는 행동(Behavioral) 패턴으로 넘어가 보겠습니다.행동 패턴은 객체 간의 상호작용, 책임 분배, 알고리즘 캡슐화를 다룹니다. 그 출발점으로 전략(Strategy) 패턴을 선택합니다. 전략 패턴은 알고리즘을 한 객체에 캡슐화하고, 이를 교체함으로써 런타임에 알고리즘을 선택할 수 있게 하는 패턴입니다. 전통적으로는 상속 기반 인터페이스를 통해 구현했지만,..
여러분, 코딩 인터뷰에서 정렬(Sorting)과 탐색(Searching)은 기본 중의 기본입니다. 단순하지만 중요한 개념이라 난이도를 자유롭게 조절할 수 있어 면접관이 선호하는 주제이며, 우선순위 큐(Priority Queue)나 이진 탐색(Binary Search)을 결합해 시간 복잡도를 최적화하는 문제도 자주 등장합니다. 이번 글에서는 정렬과 탐색, 우선순위 큐, 이진 탐색 패턴을 만나면 어떻게 접근하면 좋은지, 단계별로 아주 구체적이고 친절하게 풀어보겠습니다.우리는 단순히 “정렬 후 이진 탐색”이라는 키워드만 언급하고 끝나지 않고, 왜 이런 접근이 유효한지, 면접에서 이를 어떻게 표현할지, 코너 케이스나 추가 기능(비동기, 로깅, 에러 처리)을 어떻게 고려할지까지 모두 다루어보겠습니다. 이 글을 통..
지난 글에서는 플라이웨이트(Flyweight) 패턴을 모던 C++ 관점에서 재해석하며, 대량의 유사 객체 공유를 std::expected, std::string_view, Ranges, Concepts 등을 사용해 더 안전하고 유지보수성 높은 방식으로 구현할 수 있음을 살펴봤습니다. 이번 글에서는 구조적 패턴의 또 다른 핵심, 프록시(Proxy) 패턴을 다룹니다.프록시 패턴은 특정 객체(Real Subject)에 대한 접근을 제어하거나, 지연 로딩(Lazy Loading), 원격 호출(Remote Proxy), 캐싱(Caching) 등의 부가 기능을 중간에 삽입하는 기법을 제안합니다. 전통적 C++ 구현은 가상 함수를 통한 상속 기반 대리 객체로 접근했지만, 모던 C++20 이상의 기능을 활용하면 함수 ..
지난 글에서는 퍼사드(Facade) 패턴을 모던 C++ 관점에서 재해석하며, 모듈(Modules), Concepts, std::expected, std::format, std::variant 등을 활용해 복잡한 서브시스템을 단순화하는 전략을 살펴보았습니다. 이번 글에서는 또 하나의 구조적 패턴인 플라이웨이트(Flyweight) 패턴에 주목합니다.플라이웨이트 패턴은 다수의 유사한 객체를 효율적으로 다루기 위해, 공유 가능한 상태를 메모리 절약적으로 관리하는 방법을 제시합니다. 전통적으로는 "풀(Pool)을 두고 재활용"하거나 "공유된 객체를 전역 맵으로 관리"하는 방식으로 구현했으나, 모던 C++에서는 std::unordered_map, std::shared_ptr, std::string_view, Con..
지난 글에서는 데코레이터(Decorator) 패턴을 모던 C++ 관점에서 재해석하며, 상속 기반 장식(Decoration) 대신 함수 합성, 람다, Ranges 등을 활용해 기능 확장 과정을 유연하고 단순화할 수 있음을 확인했습니다. 이번 글에서는 퍼사드(Facade) 패턴에 주목합니다.퍼사드 패턴은 복잡한 서브시스템을 단일 인터페이스로 감싸, 클라이언트가 내부 구성 요소를 알 필요 없이 단순하고 일관된 방식으로 기능을 이용하도록 돕습니다. 전통적으로는 "정적인 클래스"나 "정적으로 링크된 라이브러리"를 단일 진입점으로 묶는 식으로 구현했지만, 모던 C++에서는 모듈(Modules), Concepts, std::expected, std::format 등을 활용해 퍼사드를 더 명확하고 문서화된 형태로 제공..
여러분, 코딩 인터뷰에서 트리와 그래프 문제는 난이도를 조정하기 매우 좋은 자료구조 문제 유형으로 꼽힙니다. 트리나 그래프는 노드(Node)와 엣지(Edge)로 구성되며, 선형적인 배열·문자열·스택·큐와 달리, 비선형적이고 연결 구조를 갖기 때문에 문제에서 다루는 패턴이 훨씬 다양하고 깊습니다. 이번 글에서는 트리와 그래프 문제를 만났을 때 어떤 사고 과정을 거쳐 해결할 수 있는지, 주요 패턴들(트리 순회, 레벨 순회, 최소/최대 깊이, 직경 계산, 그래프 사이클 검출, 위상 정렬, 최단 경로 알고리즘, MST 등)을 단계별로 하나하나 꼼꼼히 살펴보겠습니다.이 글을 읽고 나면, 여러분은 트리와 그래프 문제를 처음 보고도 당황하지 않고, "아, 이 문제는 DFS/BFS로 O(V+E)에 해결 가능하겠군", ..
앞선 글에서는 브리지(Bridge) 패턴을 통해 모던 C++에서 상속 기반의 전통적 설계를 어떻게 Concepts, 함수 객체, std::variant 등으로 대체하며 더 유연한 구조를 만들 수 있는지 살펴보았습니다. 이번에는 데코레이터(Decorator) 패턴을 재조명합니다.데코레이터 패턴은 객체에 기능을 동적으로 추가하는 방법을 제시합니다. 전통적으로는 상속이나 래핑(wrapper) 클래스를 사용해 "장식(Decoration)"을 더했지만, 모던 C++에서는 람다, std::function, Ranges, Concepts 등의 기능을 활용해 상속 계층 폭발을 줄이고, 훨씬 간결하고 가독성 높은 코드로 기능을 확장할 수 있습니다.패턴 소개: 데코레이터(Decorator)의도:객체에 추가 책임(기능)을 ..
이전 글에서는 추상 팩토리(Abstract Factory) 패턴을 모던 C++로 재해석하며, 상속 기반의 전통적 구현 방식이 어떻게 Concepts, std::expected, std::variant 등을 활용해 보다 탄탄하고 유연한 구조로 바뀔 수 있는지 알아보았습니다. 이번에는 브리지(Bridge) 패턴에 주목합니다.브리지 패턴의 핵심 의도는 "추상(Abstraction)과 구현(Implementation)을 분리하여 둘을 독립적으로 확장할 수 있게 하는 것"입니다. 전통적인 C++ 구현에서는 추상 클래스 계층과 구현 클래스 계층을 상속으로 연결하는 경향이 많았으나, 모던 C++에서는 Concepts, 컴포지션(합성), std::function, 그리고 Ranges나 람다를 통한 파이프라인형 사고로 ..
여러분, 알고리즘 인터뷰에서 자료구조를 다루는 문제는 매우 빈번합니다. 그중에서도 연결 리스트(Linked List), 스택(Stack), 그리고 큐(Queue)는 가장 기본적이면서도 면접관이 여러분의 기본 자료구조 이해도, 포인터 조작 능력, 추상적 개념을 코드로 구현하는 능력을 평가하기 좋은 주제입니다. 이번 글에서는 이 세 가지 자료구조에 대한 알고리즘 문제 접근 패턴을 하나하나 단계별로 아주 구체적으로 살펴볼게요.우리는 단순히 "연결 리스트 문제는 포인터 조작" 정도로 끝내지 않고, 실제 문제를 받았을 때 어떤 사고 과정을 거쳐 솔루션을 도출하고, 면접관 앞에서 어떻게 설명하면 좋을지, 각 자료구조별로 어떤 유형의 문제들이 빈출되는지, 코너 케이스나 최적화 포인트는 무엇인지까지 심층적으로 다루겠습..
이전 글에서는 팩토리 메서드(Factory Method) 패턴을 살펴보며, 가상 함수 기반의 고전적 구현을 어떻게 모던 C++20 이상의 기능(Concepts, std::expected, std::variant, std::optional, std::format)으로 개선할 수 있는지 논했습니다. 이번에는 추상 팩토리(Abstract Factory) 패턴으로 한 걸음 더 나아갑니다.추상 팩토리는 "연관되거나 의존적인 객체 패밀리를 생성하는 인터페이스"를 제공하는 패턴입니다. 즉, 서로 관련 있는 여러 종류의 객체를 일관성 있게 생성할 수 있는 팩토리를 추상화하는 것입니다. 전통적인 C++ 구현에서는 인터페이스 클래스를 상속받아 구체 팩토리를 제공했고, 다양한 제품 계열(class family)을 다룰 때 ..