메멘토 패턴은 객체의 이전 상태를 저장해두었다가 나중에 복원할 수 있게 해주는 디자인 패턴이에요.
무언가를 변경했다가 다시 원래 상태로 되돌릴 수 있다면, 그 상태를 어딘가에 기록해 둬야 하잖아요?
메멘토 패턴은 이 상태를 캡슐화해서 저장하고, 필요한 순간에 원본 객체를 손대지 않고 안전하게 복원할 수 있게 해줘요.
특히 커맨드 패턴의 undo/redo 기능을 구현할 때 많이 함께 사용돼요.
메멘토 패턴은 상태를 저장하는 Memento, 원본 객체인 Originator, 저장된 상태들을 관리하는 Caretaker로 구성돼요.

Originator (에디터)
역할 : 원본 객체이고 보통 에디터가 이에 해당해요. Memento 생성 및 복원 메서드가 있어요.
특징 :
Originator에서 상태 생성/복원 로직을 가지고 있어요.
예시 : 문서 편집기의 에디터 객체에요.
Memento (스냅샷 인터페이스)
역할 : state를 저장하는 역할을 하는 인터페이스에요.
특징 :
내부 필드는 외부에서 접근 불가해요.
Originator만 읽고 쓸 수 있도록 설계되어요. (Caretaker는 인터페이스만 알고 뭘 저장하는지 몰라요)
예시 : 에디터 혹은 피그마의 "중간 저장 히스토리 또는 버전"에 해당해요.
Caretaker
역할 : Originator가 만든 Memento를 보관하고 관리해요.
특징
Memento 내부에 뭐가 있는지 모르고 보관만 해요.
예시 : 피그마에서 최근 히스토리들을 저장해서 쭈루룩 보여주는 것
다음과 같은 기능이 있는 문서 편집기 버저닝 기능을 메멘토 패턴으로 구현해볼게요.
기능
에디터에 type을 하여 글을 쓸 수 있다.
중간 중간 스냅샷을 찍어서 나중에 해당 스냅샷으로 돌아갈 수 있다.
Originator (문서, 편집기) | Memento (스냅샷) | Caretaker (스냅샷 보관) |
|---|---|---|
| | |
Client 코드 | ||
| ||
장점
객체의 상태 저장/복원을 쉽게 구현할 수 있어요.
원본 객체의 내부 구조를 외부에 노출하지 않고 상태를 저장할 수 있어요.
undo/redo 기능을 구현하기 매우 좋아요.
단점
상태가 크면 Memento도 커져서 메모리를 많이 사용할 수 있어요. (파일화하거나 Serialze 가능한 포멧 설계, 부분 저장)
너무 많은 스냅샷을 만들면 관리가 복잡해져요.
메멘토 패턴은 상태를 저장/복원하는 게 목적이고,
커맨드 패턴은 작업(명령)을 객체로 캡슐화하는 게 목적이에요.
그런데 예전 블로그 글에서 커맨드 패턴을 통해 undo/redo 구현하는 방법을 알려드렸어요. 거기에서 Queue 1개를 이용해 undo/redo 구현하는 방법을 알려드렸었어요. 사실 그 방법으로 queue의 중간 중간 지점마다 플래그를 꼽고 버저닝이 가능해요. 왜냐하면 플래그된 곳까지 undo를 쭈루룩 실행하면 되거든요.
하지만! Command 기반 Undo 만으로는 복구가 어려워지는 경우가 있어요.
명령이 너무 많이 쌓임 → 메모리 문제
복잡한 변경으로 인해 의도치 않게 꼬임
무거운 상태를 복원하는데 Command 기반 Undo는 불안정
“되돌리기 200번” 같은 건 비효율적
뭐 위와같은 어려움이 발생했을때, Command가 많이 쌓이면 합쳐주는 로직을 추가한다거나 하면 개선은 되겠지만, 코드가 복잡해지고 확장성도 떨어질 확률이 높아요.
그래서 에디터 객체는 보통 메멘토 패턴과 커맨드 패턴을 함께 사용해요.
1. 사용자가 행동함 → Command 실행 2. 작은 변경 → Command.undo() 기반 Undo 3. 특정 간격 or 특정 큰 변화에서 → Memento 스냅샷 저장 4. 문제가 생기면 스냅샷으로 롤백 → 이후 Command로 세부 복구패턴 | 역할 |
|---|---|
메멘토 | 상태 스냅샷 저장/복원 |
커맨드 | 행동의 캡슐화 + 실행/취소에 사용 |
함께 사용 시 | 스냅샷은 Memento에 저장, 실행/취소는 Command가 담당 |
오늘은 메멘토 패턴을 살펴봤어요. 상태를 기억하고 복원하는 강력한 기능을 만들기 위해 정말 자주 사용되는 패턴이에요.
그리고 특히 커맨드 패턴과 함께 쓰일 때 진가를 발휘해요.
커맨드는 실행/취소를 담당하고,
메멘토는 실행 전후의 상태를 저장/복원해주기 때문에
둘이 함께 있으면 어떤 애플리케이션이든 안정적으로 undo/redo 흐름을 만들 수 있어요.
그런데 단점으로 소개했듯이 저장할 상태가 너무 크면 스냅샷을 어떻게 저장할 지 많은 고민을 해야해요. GitHub처럼 변경 부분(Delta)만 저장하는 증분 저장 방식을 사용할 수 있어요. 혹은 Serialize해서 메모리가 아닌 파일로 스냅샷을 저장하기도 해요. 아니면 처음부터 에디터를 직렬화 가능한 포멧으로 설계하여 이런 문제점을 더 쉽게 해결할 수 있도록 만들어요.
이제 여러분들도 장단점을 잘 파악했으니 잘 쓰실거라 믿어요.