Repository: yorkie-team/yorkie
Pull request #301 (2022-02-05 13:38:29)

Add FetchHistory API
<!--  Thanks for sending a pull request! -->

**What this PR does / why we need it**:

Add FetchHistory API

- Rename key.BSONKey to key.CombinedKey
- Use a struct instead of the pointer of Checkpoint, Key and change.ID
- Rename operation package to operations package
- Use time package for decoding clientID

**Which issue(s) this PR fixes**:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->
Address #52

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
-->
```release-note

```

**Additional documentation**:

<!--
This section can be blank if this pull request does not require a release note.

Please use the following format for linking documentation:
- [Usage]: <link>
- [Other doc]: <link>
-->
```docs

```

**Checklist**:
- [x] Added relevant tests or not required
- [x] Didn't break anything


codecov[bot]: # [Codecov](https://codecov.io/gh/yorkie-team/yorkie/pull/301?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team) Report
> Merging [#301](https://codecov.io/gh/yorkie-team/yorkie/pull/301?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team) (bd2e7a8) into [main](https://codecov.io/gh/yorkie-team/yorkie/commit/1b4c602ecea860fe57718c59a839ce5bab70bc3f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team) (1b4c602) will **decrease** coverage by `0.27%`.
> The diff coverage is `43.02%`.

[![Impacted file tree graph](https://codecov.io/gh/yorkie-team/yorkie/pull/301/graphs/tree.svg?width=650&height=150&src=pr&token=P6COB1ZNIC&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team)](https://codecov.io/gh/yorkie-team/yorkie/pull/301?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team)

```diff
@@            Coverage Diff             @@
##             main     #301      +/-   ##
==========================================
- Coverage   48.95%   48.67%   -0.28%     
==========================================
  Files          59       59              
  Lines        4764     4803      +39     
==========================================
+ Hits         2332     2338       +6     
- Misses       2170     2201      +31     
- Partials      262      264       +2     
```


| [Impacted Files](https://codecov.io/gh/yorkie-team/yorkie/pull/301?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team) | Coverage Δ | |
|---|---|---|
| [client/client.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-Y2xpZW50L2NsaWVudC5nbw==) | `10.85% <0.00%> (-0.44%)` | :arrow_down: |
| [pkg/document/change/change.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-cGtnL2RvY3VtZW50L2NoYW5nZS9jaGFuZ2UuZ28=) | `0.00% <ø> (ø)` | |
| [pkg/document/change/context.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-cGtnL2RvY3VtZW50L2NoYW5nZS9jb250ZXh0Lmdv) | `0.00% <ø> (ø)` | |
| [yorkie/backend/db/change\_info.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-eW9ya2llL2JhY2tlbmQvZGIvY2hhbmdlX2luZm8uZ28=) | `29.16% <ø> (ø)` | |
| [yorkie/backend/db/doc\_info.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-eW9ya2llL2JhY2tlbmQvZGIvZG9jX2luZm8uZ28=) | `0.00% <0.00%> (ø)` | |
| [yorkie/backend/sync/etcd/pubsub.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-eW9ya2llL2JhY2tlbmQvc3luYy9ldGNkL3B1YnN1Yi5nbw==) | `0.00% <0.00%> (ø)` | |
| [pkg/document/time/actor\_id.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-cGtnL2RvY3VtZW50L3RpbWUvYWN0b3JfaWQuZ28=) | `61.53% <33.33%> (ø)` | |
| [api/converter/from\_pb.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-YXBpL2NvbnZlcnRlci9mcm9tX3BiLmdv) | `62.05% <44.00%> (-2.15%)` | :arrow_down: |
| [yorkie/backend/sync/memory/pubsub.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-eW9ya2llL2JhY2tlbmQvc3luYy9tZW1vcnkvcHVic3ViLmdv) | `45.45% <50.00%> (ø)` | |
| [yorkie/rpc/yorkie\_server.go](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team#diff-eW9ya2llL3JwYy95b3JraWVfc2VydmVyLmdv) | `41.93% <54.54%> (-0.11%)` | :arrow_down: |
| ... and [1 more](https://codecov.io/gh/yorkie-team/yorkie/pull/301/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/yorkie-team/yorkie/pull/301?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/yorkie-team/yorkie/pull/301?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team). Last update [1b4c602...bd2e7a8](https://codecov.io/gh/yorkie-team/yorkie/pull/301?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yorkie-team).


Patch:
diff --git a/api/converter/from_pb.go b/api/converter/from_pb.go
index e3c24b3d..598f70d7 100644
--- a/api/converter/from_pb.go
+++ b/api/converter/from_pb.go
@@ -23,7 +23,7 @@ import (
 	"github.com/yorkie-team/yorkie/pkg/document/change"
 	"github.com/yorkie-team/yorkie/pkg/document/json"
 	"github.com/yorkie-team/yorkie/pkg/document/key"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 	"github.com/yorkie-team/yorkie/pkg/document/time"
 	"github.com/yorkie-team/yorkie/pkg/types"
 	"github.com/yorkie-team/yorkie/yorkie/backend/sync"
@@ -59,7 +59,7 @@ func FromChangePack(pbPack *api.ChangePack) (*change.Pack, error) {
 		return nil, ErrCheckpointRequired
 	}
 
-	changes, err := fromChanges(pbPack.Changes)
+	changes, err := FromChanges(pbPack.Changes)
 	if err != nil {
 		return nil, err
 	}
@@ -70,7 +70,7 @@ func FromChangePack(pbPack *api.ChangePack) (*change.Pack, error) {
 	}
 
 	return &change.Pack{
-		DocumentKey:     fromDocumentKey(pbPack.DocumentKey),
+		DocumentKey:     FromDocumentKey(pbPack.DocumentKey),
 		Checkpoint:      fromCheckpoint(pbPack.Checkpoint),
 		Changes:         changes,
 		Snapshot:        pbPack.Snapshot,
@@ -78,58 +78,60 @@ func FromChangePack(pbPack *api.ChangePack) (*change.Pack, error) {
 	}, nil
 }
 
-func fromDocumentKey(pbKey *api.DocumentKey) *key.Key {
-	return &key.Key{
+// FromDocumentKey converts the given Protobuf formats to model format.
+func FromDocumentKey(pbKey *api.DocumentKey) key.Key {
+	return key.Key{
 		Collection: pbKey.Collection,
 		Document:   pbKey.Document,
 	}
 }
 
-func fromCheckpoint(pbCheckpoint *api.Checkpoint) *change.Checkpoint {
+func fromCheckpoint(pbCheckpoint *api.Checkpoint) change.Checkpoint {
 	return change.NewCheckpoint(
 		pbCheckpoint.ServerSeq,
 		pbCheckpoint.ClientSeq,
 	)
 }
 
-func fromChanges(pbChanges []*api.Change) ([]*change.Change, error) {
+// FromChanges converts the given Protobuf formats to model format.
+func FromChanges(pbChanges []*api.Change) ([]*change.Change, error) {
 	var changes []*change.Change
 	for _, pbChange := range pbChanges {
 		changeID, err := fromChangeID(pbChange.Id)
 		if err != nil {
 			return nil, err
 		}
-		operations, err := FromOperations(pbChange.Operations)
+		ops, err := FromOperations(pbChange.Operations)
 		if err != nil {
 			return nil, err
 		}
 		changes = append(changes, change.New(
 			changeID,
 			pbChange.Message,
-			operations,
+			ops,
 		))
 	}
 
 	return changes, nil
 }
 
-func fromChangeID(id *api.ChangeID) (*change.ID, error) {
+func fromChangeID(id *api.ChangeID) (change.ID, error) {
 	actorID, err := time.ActorIDFromBytes(id.ActorId)
 	if err != nil {
-		return nil, err
+		return change.InitialID, err
 	}
 	return change.NewID(
 		id.ClientSeq,
 		id.Lamport,
-		actorID,
+		&actorID,
 	), nil
 }
 
 // FromDocumentKeys converts the given Protobuf formats to model format.
-func FromDocumentKeys(pbKeys []*api.DocumentKey) []*key.Key {
-	var keys []*key.Key
+func FromDocumentKeys(pbKeys []*api.DocumentKey) []key.Key {
+	var keys []key.Key
 	for _, pbKey := range pbKeys {
-		keys = append(keys, fromDocumentKey(pbKey))
+		keys = append(keys, FromDocumentKey(pbKey))
 	}
 	return keys
 }
@@ -183,10 +185,10 @@ func FromClients(pbClients *api.Clients) ([]*types.Client, error) {
 }
 
 // FromOperations converts the given Protobuf formats to model format.
-func FromOperations(pbOps []*api.Operation) ([]operation.Operation, error) {
-	var ops []operation.Operation
+func FromOperations(pbOps []*api.Operation) ([]operations.Operation, error) {
+	var ops []operations.Operation
 	for _, pbOp := range pbOps {
-		var op operation.Operation
+		var op operations.Operation
 		var err error
 		switch decoded := pbOp.Body.(type) {
 		case *api.Operation_Set_:
@@ -219,7 +221,7 @@ func FromOperations(pbOps []*api.Operation) ([]operation.Operation, error) {
 	return ops, nil
 }
 
-func fromSet(pbSet *api.Operation_Set) (*operation.Set, error) {
+func fromSet(pbSet *api.Operation_Set) (*operations.Set, error) {
 	parentCreatedAt, err := fromTimeTicket(pbSet.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -233,7 +235,7 @@ func fromSet(pbSet *api.Operation_Set) (*operation.Set, error) {
 		return nil, err
 	}
 
-	return operation.NewSet(
+	return operations.NewSet(
 		parentCreatedAt,
 		pbSet.Key,
 		elem,
@@ -241,7 +243,7 @@ func fromSet(pbSet *api.Operation_Set) (*operation.Set, error) {
 	), nil
 }
 
-func fromAdd(pbAdd *api.Operation_Add) (*operation.Add, error) {
+func fromAdd(pbAdd *api.Operation_Add) (*operations.Add, error) {
 	parentCreatedAt, err := fromTimeTicket(pbAdd.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -258,7 +260,7 @@ func fromAdd(pbAdd *api.Operation_Add) (*operation.Add, error) {
 	if err != nil {
 		return nil, err
 	}
-	return operation.NewAdd(
+	return operations.NewAdd(
 		parentCreatedAt,
 		prevCreatedAt,
 		elem,
@@ -266,7 +268,7 @@ func fromAdd(pbAdd *api.Operation_Add) (*operation.Add, error) {
 	), nil
 }
 
-func fromMove(pbMove *api.Operation_Move) (*operation.Move, error) {
+func fromMove(pbMove *api.Operation_Move) (*operations.Move, error) {
 	parentCreatedAt, err := fromTimeTicket(pbMove.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -283,7 +285,7 @@ func fromMove(pbMove *api.Operation_Move) (*operation.Move, error) {
 	if err != nil {
 		return nil, err
 	}
-	return operation.NewMove(
+	return operations.NewMove(
 		parentCreatedAt,
 		prevCreatedAt,
 		createdAt,
@@ -291,7 +293,7 @@ func fromMove(pbMove *api.Operation_Move) (*operation.Move, error) {
 	), nil
 }
 
-func fromRemove(pbRemove *api.Operation_Remove) (*operation.Remove, error) {
+func fromRemove(pbRemove *api.Operation_Remove) (*operations.Remove, error) {
 	parentCreatedAt, err := fromTimeTicket(pbRemove.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -304,14 +306,14 @@ func fromRemove(pbRemove *api.Operation_Remove) (*operation.Remove, error) {
 	if err != nil {
 		return nil, err
 	}
-	return operation.NewRemove(
+	return operations.NewRemove(
 		parentCreatedAt,
 		createdAt,
 		executedAt,
 	), nil
 }
 
-func fromEdit(pbEdit *api.Operation_Edit) (*operation.Edit, error) {
+func fromEdit(pbEdit *api.Operation_Edit) (*operations.Edit, error) {
 	parentCreatedAt, err := fromTimeTicket(pbEdit.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -334,7 +336,7 @@ func fromEdit(pbEdit *api.Operation_Edit) (*operation.Edit, error) {
 	if err != nil {
 		return nil, err
 	}
-	return operation.NewEdit(
+	return operations.NewEdit(
 		parentCreatedAt,
 		from,
 		to,
@@ -344,7 +346,7 @@ func fromEdit(pbEdit *api.Operation_Edit) (*operation.Edit, error) {
 	), nil
 }
 
-func fromSelect(pbSelect *api.Operation_Select) (*operation.Select, error) {
+func fromSelect(pbSelect *api.Operation_Select) (*operations.Select, error) {
 	parentCreatedAt, err := fromTimeTicket(pbSelect.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -361,7 +363,7 @@ func fromSelect(pbSelect *api.Operation_Select) (*operation.Select, error) {
 	if err != nil {
 		return nil, err
 	}
-	return operation.NewSelect(
+	return operations.NewSelect(
 		parentCreatedAt,
 		from,
 		to,
@@ -369,7 +371,7 @@ func fromSelect(pbSelect *api.Operation_Select) (*operation.Select, error) {
 	), nil
 }
 
-func fromRichEdit(pbEdit *api.Operation_RichEdit) (*operation.RichEdit, error) {
+func fromRichEdit(pbEdit *api.Operation_RichEdit) (*operations.RichEdit, error) {
 	parentCreatedAt, err := fromTimeTicket(pbEdit.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -392,7 +394,7 @@ func fromRichEdit(pbEdit *api.Operation_RichEdit) (*operation.RichEdit, error) {
 	if err != nil {
 		return nil, err
 	}
-	return operation.NewRichEdit(
+	return operations.NewRichEdit(
 		parentCreatedAt,
 		from,
 		to,
@@ -403,7 +405,7 @@ func fromRichEdit(pbEdit *api.Operation_RichEdit) (*operation.RichEdit, error) {
 	), nil
 }
 
-func fromStyle(pbStyle *api.Operation_Style) (*operation.Style, error) {
+func fromStyle(pbStyle *api.Operation_Style) (*operations.Style, error) {
 	parentCreatedAt, err := fromTimeTicket(pbStyle.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -420,7 +422,7 @@ func fromStyle(pbStyle *api.Operation_Style) (*operation.Style, error) {
 	if err != nil {
 		return nil, err
 	}
-	return operation.NewStyle(
+	return operations.NewStyle(
 		parentCreatedAt,
 		from,
 		to,
@@ -429,7 +431,7 @@ func fromStyle(pbStyle *api.Operation_Style) (*operation.Style, error) {
 	), nil
 }
 
-func fromIncrease(pbInc *api.Operation_Increase) (*operation.Increase, error) {
+func fromIncrease(pbInc *api.Operation_Increase) (*operations.Increase, error) {
 	parentCreatedAt, err := fromTimeTicket(pbInc.ParentCreatedAt)
 	if err != nil {
 		return nil, err
@@ -442,7 +444,7 @@ func fromIncrease(pbInc *api.Operation_Increase) (*operation.Increase, error) {
 	if err != nil {
 		return nil, err
 	}
-	return operation.NewIncrease(
+	return operations.NewIncrease(
 		parentCreatedAt,
 		elem,
 		executedAt,
@@ -488,7 +490,7 @@ func fromTimeTicket(pbTicket *api.TimeTicket) (*time.Ticket, error) {
 	return time.NewTicket(
 		pbTicket.Lamport,
 		pbTicket.Delimiter,
-		actorID,
+		&actorID,
 	), nil
 }
 
diff --git a/api/converter/to_pb.go b/api/converter/to_pb.go
index 5a4f5cf5..70aa5b7a 100644
--- a/api/converter/to_pb.go
+++ b/api/converter/to_pb.go
@@ -24,7 +24,7 @@ import (
 	"github.com/yorkie-team/yorkie/pkg/document/change"
 	"github.com/yorkie-team/yorkie/pkg/document/json"
 	"github.com/yorkie-team/yorkie/pkg/document/key"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 	"github.com/yorkie-team/yorkie/pkg/document/time"
 	"github.com/yorkie-team/yorkie/pkg/types"
 	"github.com/yorkie-team/yorkie/yorkie/backend/sync"
@@ -48,7 +48,7 @@ func ToMetadataInfo(metadata types.MetadataInfo) *api.Metadata {
 
 // ToChangePack converts the given model format to Protobuf format.
 func ToChangePack(pack *change.Pack) (*api.ChangePack, error) {
-	pbChanges, err := toChanges(pack.Changes)
+	pbChanges, err := ToChanges(pack.Changes)
 	if err != nil {
 		return nil, err
 	}
@@ -63,7 +63,7 @@ func ToChangePack(pack *change.Pack) (*api.ChangePack, error) {
 }
 
 // ToDocumentKey converts the given model format to Protobuf format.
-func ToDocumentKey(key *key.Key) *api.DocumentKey {
+func ToDocumentKey(key key.Key) *api.DocumentKey {
 	return &api.DocumentKey{
 		Collection: key.Collection,
 		Document:   key.Document,
@@ -71,7 +71,7 @@ func ToDocumentKey(key *key.Key) *api.DocumentKey {
 }
 
 // ToCheckpoint converts the given model format to Protobuf format.
-func ToCheckpoint(cp *change.Checkpoint) *api.Checkpoint {
+func ToCheckpoint(cp change.Checkpoint) *api.Checkpoint {
 	return &api.Checkpoint{
 		ServerSeq: cp.ServerSeq,
 		ClientSeq: cp.ClientSeq,
@@ -79,7 +79,7 @@ func ToCheckpoint(cp *change.Checkpoint) *api.Checkpoint {
 }
 
 // ToChangeID converts the given model format to Protobuf format.
-func ToChangeID(id *change.ID) *api.ChangeID {
+func ToChangeID(id change.ID) *api.ChangeID {
 	return &api.ChangeID{
 		ClientSeq: id.ClientSeq(),
 		Lamport:   id.Lamport(),
@@ -88,7 +88,7 @@ func ToChangeID(id *change.ID) *api.ChangeID {
 }
 
 // ToDocumentKeys converts the given model format to Protobuf format.
-func ToDocumentKeys(keys []*key.Key) []*api.DocumentKey {
+func ToDocumentKeys(keys []key.Key) []*api.DocumentKey {
 	var pbKeys []*api.DocumentKey
 	for _, k := range keys {
 		pbKeys = append(pbKeys, ToDocumentKey(k))
@@ -145,30 +145,30 @@ func ToDocEvent(docEvent sync.DocEvent) (*api.DocEvent, error) {
 }
 
 // ToOperations converts the given model format to Protobuf format.
-func ToOperations(operations []operation.Operation) ([]*api.Operation, error) {
+func ToOperations(ops []operations.Operation) ([]*api.Operation, error) {
 	var pbOperations []*api.Operation
 
-	for _, o := range operations {
+	for _, o := range ops {
 		pbOperation := &api.Operation{}
 		var err error
 		switch op := o.(type) {
-		case *operation.Set:
+		case *operations.Set:
 			pbOperation.Body, err = toSet(op)
-		case *operation.Add:
+		case *operations.Add:
 			pbOperation.Body, err = toAdd(op)
-		case *operation.Move:
+		case *operations.Move:
 			pbOperation.Body, err = toMove(op)
-		case *operation.Remove:
+		case *operations.Remove:
 			pbOperation.Body, err = toRemove(op)
-		case *operation.Edit:
+		case *operations.Edit:
 			pbOperation.Body, err = toEdit(op)
-		case *operation.Select:
+		case *operations.Select:
 			pbOperation.Body, err = toSelect(op)
-		case *operation.RichEdit:
+		case *operations.RichEdit:
 			pbOperation.Body, err = toRichEdit(op)
-		case *operation.Style:
+		case *operations.Style:
 			pbOperation.Body, err = toStyle(op)
-		case *operation.Increase:
+		case *operations.Increase:
 			pbOperation.Body, err = toIncrease(op)
 		default:
 			return nil, ErrUnsupportedOperation
@@ -195,7 +195,8 @@ func ToTimeTicket(ticket *time.Ticket) *api.TimeTicket {
 	}
 }
 
-func toChanges(changes []*change.Change) ([]*api.Change, error) {
+// ToChanges converts the given model format to Protobuf format.
+func ToChanges(changes []*change.Change) ([]*api.Change, error) {
 	var pbChanges []*api.Change
 
 	for _, c := range changes {
@@ -214,7 +215,7 @@ func toChanges(changes []*change.Change) ([]*api.Change, error) {
 	return pbChanges, nil
 }
 
-func toSet(set *operation.Set) (*api.Operation_Set_, error) {
+func toSet(set *operations.Set) (*api.Operation_Set_, error) {
 	pbElem, err := toJSONElementSimple(set.Value())
 	if err != nil {
 		return nil, err
@@ -230,7 +231,7 @@ func toSet(set *operation.Set) (*api.Operation_Set_, error) {
 	}, nil
 }
 
-func toAdd(add *operation.Add) (*api.Operation_Add_, error) {
+func toAdd(add *operations.Add) (*api.Operation_Add_, error) {
 	pbElem, err := toJSONElementSimple(add.Value())
 	if err != nil {
 		return nil, err
@@ -246,7 +247,7 @@ func toAdd(add *operation.Add) (*api.Operation_Add_, error) {
 	}, nil
 }
 
-func toMove(move *operation.Move) (*api.Operation_Move_, error) {
+func toMove(move *operations.Move) (*api.Operation_Move_, error) {
 	return &api.Operation_Move_{
 		Move: &api.Operation_Move{
 			ParentCreatedAt: ToTimeTicket(move.ParentCreatedAt()),
@@ -257,7 +258,7 @@ func toMove(move *operation.Move) (*api.Operation_Move_, error) {
 	}, nil
 }
 
-func toRemove(remove *operation.Remove) (*api.Operation_Remove_, error) {
+func toRemove(remove *operations.Remove) (*api.Operation_Remove_, error) {
 	return &api.Operation_Remove_{
 		Remove: &api.Operation_Remove{
 			ParentCreatedAt: ToTimeTicket(remove.ParentCreatedAt()),
@@ -267,7 +268,7 @@ func toRemove(remove *operation.Remove) (*api.Operation_Remove_, error) {
 	}, nil
 }
 
-func toEdit(edit *operation.Edit) (*api.Operation_Edit_, error) {
+func toEdit(edit *operations.Edit) (*api.Operation_Edit_, error) {
 	return &api.Operation_Edit_{
 		Edit: &api.Operation_Edit{
 			ParentCreatedAt:     ToTimeTicket(edit.ParentCreatedAt()),
@@ -280,7 +281,7 @@ func toEdit(edit *operation.Edit) (*api.Operation_Edit_, error) {
 	}, nil
 }
 
-func toSelect(s *operation.Select) (*api.Operation_Select_, error) {
+func toSelect(s *operations.Select) (*api.Operation_Select_, error) {
 	return &api.Operation_Select_{
 		Select: &api.Operation_Select{
 			ParentCreatedAt: ToTimeTicket(s.ParentCreatedAt()),
@@ -291,7 +292,7 @@ func toSelect(s *operation.Select) (*api.Operation_Select_, error) {
 	}, nil
 }
 
-func toRichEdit(richEdit *operation.RichEdit) (*api.Operation_RichEdit_, error) {
+func toRichEdit(richEdit *operations.RichEdit) (*api.Operation_RichEdit_, error) {
 	return &api.Operation_RichEdit_{
 		RichEdit: &api.Operation_RichEdit{
 			ParentCreatedAt:     ToTimeTicket(richEdit.ParentCreatedAt()),
@@ -305,7 +306,7 @@ func toRichEdit(richEdit *operation.RichEdit) (*api.Operation_RichEdit_, error)
 	}, nil
 }
 
-func toStyle(style *operation.Style) (*api.Operation_Style_, error) {
+func toStyle(style *operations.Style) (*api.Operation_Style_, error) {
 	return &api.Operation_Style_{
 		Style: &api.Operation_Style{
 			ParentCreatedAt: ToTimeTicket(style.ParentCreatedAt()),
@@ -317,7 +318,7 @@ func toStyle(style *operation.Style) (*api.Operation_Style_, error) {
 	}, nil
 }
 
-func toIncrease(increase *operation.Increase) (*api.Operation_Increase_, error) {
+func toIncrease(increase *operations.Increase) (*api.Operation_Increase_, error) {
 	pbElem, err := toJSONElementSimple(increase.Value())
 	if err != nil {
 		return nil, err
diff --git a/api/yorkie.pb.go b/api/yorkie.pb.go
index f8eed333..25be9d1e 100644
--- a/api/yorkie.pb.go
+++ b/api/yorkie.pb.go
@@ -1025,6 +1025,108 @@ func (m *UpdateMetadataResponse) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_UpdateMetadataResponse proto.InternalMessageInfo
 
+type FetchHistoryRequest struct {
+	ClientId             []byte       `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
+	DocumentKey          *DocumentKey `protobuf:"bytes,2,opt,name=document_key,json=documentKey,proto3" json:"document_key,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
+}
+
+func (m *FetchHistoryRequest) Reset()         { *m = FetchHistoryRequest{} }
+func (m *FetchHistoryRequest) String() string { return proto.CompactTextString(m) }
+func (*FetchHistoryRequest) ProtoMessage()    {}
+func (*FetchHistoryRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_9df40050e88fbc16, []int{16}
+}
+func (m *FetchHistoryRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *FetchHistoryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_FetchHistoryRequest.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *FetchHistoryRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FetchHistoryRequest.Merge(m, src)
+}
+func (m *FetchHistoryRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *FetchHistoryRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_FetchHistoryRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FetchHistoryRequest proto.InternalMessageInfo
+
+func (m *FetchHistoryRequest) GetClientId() []byte {
+	if m != nil {
+		return m.ClientId
+	}
+	return nil
+}
+
+func (m *FetchHistoryRequest) GetDocumentKey() *DocumentKey {
+	if m != nil {
+		return m.DocumentKey
+	}
+	return nil
+}
+
+type FetchHistoryResponse struct {
+	Changes              []*Change `protobuf:"bytes,1,rep,name=changes,proto3" json:"changes,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
+	XXX_unrecognized     []byte    `json:"-"`
+	XXX_sizecache        int32     `json:"-"`
+}
+
+func (m *FetchHistoryResponse) Reset()         { *m = FetchHistoryResponse{} }
+func (m *FetchHistoryResponse) String() string { return proto.CompactTextString(m) }
+func (*FetchHistoryResponse) ProtoMessage()    {}
+func (*FetchHistoryResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_9df40050e88fbc16, []int{17}
+}
+func (m *FetchHistoryResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *FetchHistoryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_FetchHistoryResponse.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *FetchHistoryResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FetchHistoryResponse.Merge(m, src)
+}
+func (m *FetchHistoryResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *FetchHistoryResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_FetchHistoryResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FetchHistoryResponse proto.InternalMessageInfo
+
+func (m *FetchHistoryResponse) GetChanges() []*Change {
+	if m != nil {
+		return m.Changes
+	}
+	return nil
+}
+
 type ChangePack struct {
 	DocumentKey          *DocumentKey `protobuf:"bytes,1,opt,name=document_key,json=documentKey,proto3" json:"document_key,omitempty"`
 	Checkpoint           *Checkpoint  `protobuf:"bytes,2,opt,name=checkpoint,proto3" json:"checkpoint,omitempty"`
@@ -1040,7 +1142,7 @@ func (m *ChangePack) Reset()         { *m = ChangePack{} }
 func (m *ChangePack) String() string { return proto.CompactTextString(m) }
 func (*ChangePack) ProtoMessage()    {}
 func (*ChangePack) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{16}
+	return fileDescriptor_9df40050e88fbc16, []int{18}
 }
 func (m *ChangePack) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1117,7 +1219,7 @@ func (m *Change) Reset()         { *m = Change{} }
 func (m *Change) String() string { return proto.CompactTextString(m) }
 func (*Change) ProtoMessage()    {}
 func (*Change) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{17}
+	return fileDescriptor_9df40050e88fbc16, []int{19}
 }
 func (m *Change) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1180,7 +1282,7 @@ func (m *ChangeID) Reset()         { *m = ChangeID{} }
 func (m *ChangeID) String() string { return proto.CompactTextString(m) }
 func (*ChangeID) ProtoMessage()    {}
 func (*ChangeID) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{18}
+	return fileDescriptor_9df40050e88fbc16, []int{20}
 }
 func (m *ChangeID) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1251,7 +1353,7 @@ func (m *Operation) Reset()         { *m = Operation{} }
 func (m *Operation) String() string { return proto.CompactTextString(m) }
 func (*Operation) ProtoMessage()    {}
 func (*Operation) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19}
+	return fileDescriptor_9df40050e88fbc16, []int{21}
 }
 func (m *Operation) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1423,7 +1525,7 @@ func (m *Operation_Set) Reset()         { *m = Operation_Set{} }
 func (m *Operation_Set) String() string { return proto.CompactTextString(m) }
 func (*Operation_Set) ProtoMessage()    {}
 func (*Operation_Set) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 0}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 0}
 }
 func (m *Operation_Set) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1494,7 +1596,7 @@ func (m *Operation_Add) Reset()         { *m = Operation_Add{} }
 func (m *Operation_Add) String() string { return proto.CompactTextString(m) }
 func (*Operation_Add) ProtoMessage()    {}
 func (*Operation_Add) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 1}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 1}
 }
 func (m *Operation_Add) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1565,7 +1667,7 @@ func (m *Operation_Move) Reset()         { *m = Operation_Move{} }
 func (m *Operation_Move) String() string { return proto.CompactTextString(m) }
 func (*Operation_Move) ProtoMessage()    {}
 func (*Operation_Move) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 2}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 2}
 }
 func (m *Operation_Move) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1635,7 +1737,7 @@ func (m *Operation_Remove) Reset()         { *m = Operation_Remove{} }
 func (m *Operation_Remove) String() string { return proto.CompactTextString(m) }
 func (*Operation_Remove) ProtoMessage()    {}
 func (*Operation_Remove) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 3}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 3}
 }
 func (m *Operation_Remove) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1701,7 +1803,7 @@ func (m *Operation_Edit) Reset()         { *m = Operation_Edit{} }
 func (m *Operation_Edit) String() string { return proto.CompactTextString(m) }
 func (*Operation_Edit) ProtoMessage()    {}
 func (*Operation_Edit) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 4}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 4}
 }
 func (m *Operation_Edit) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1786,7 +1888,7 @@ func (m *Operation_Select) Reset()         { *m = Operation_Select{} }
 func (m *Operation_Select) String() string { return proto.CompactTextString(m) }
 func (*Operation_Select) ProtoMessage()    {}
 func (*Operation_Select) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 5}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 5}
 }
 func (m *Operation_Select) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1860,7 +1962,7 @@ func (m *Operation_RichEdit) Reset()         { *m = Operation_RichEdit{} }
 func (m *Operation_RichEdit) String() string { return proto.CompactTextString(m) }
 func (*Operation_RichEdit) ProtoMessage()    {}
 func (*Operation_RichEdit) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 6}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 6}
 }
 func (m *Operation_RichEdit) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1953,7 +2055,7 @@ func (m *Operation_Style) Reset()         { *m = Operation_Style{} }
 func (m *Operation_Style) String() string { return proto.CompactTextString(m) }
 func (*Operation_Style) ProtoMessage()    {}
 func (*Operation_Style) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 7}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 7}
 }
 func (m *Operation_Style) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2030,7 +2132,7 @@ func (m *Operation_Increase) Reset()         { *m = Operation_Increase{} }
 func (m *Operation_Increase) String() string { return proto.CompactTextString(m) }
 func (*Operation_Increase) ProtoMessage()    {}
 func (*Operation_Increase) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{19, 8}
+	return fileDescriptor_9df40050e88fbc16, []int{21, 8}
 }
 func (m *Operation_Increase) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2095,7 +2197,7 @@ func (m *JSONElementSimple) Reset()         { *m = JSONElementSimple{} }
 func (m *JSONElementSimple) String() string { return proto.CompactTextString(m) }
 func (*JSONElementSimple) ProtoMessage()    {}
 func (*JSONElementSimple) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{20}
+	return fileDescriptor_9df40050e88fbc16, []int{22}
 }
 func (m *JSONElementSimple) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2177,7 +2279,7 @@ func (m *JSONElement) Reset()         { *m = JSONElement{} }
 func (m *JSONElement) String() string { return proto.CompactTextString(m) }
 func (*JSONElement) ProtoMessage()    {}
 func (*JSONElement) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{21}
+	return fileDescriptor_9df40050e88fbc16, []int{23}
 }
 func (m *JSONElement) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2313,7 +2415,7 @@ func (m *JSONElement_JSONObject) Reset()         { *m = JSONElement_JSONObject{}
 func (m *JSONElement_JSONObject) String() string { return proto.CompactTextString(m) }
 func (*JSONElement_JSONObject) ProtoMessage()    {}
 func (*JSONElement_JSONObject) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{21, 0}
+	return fileDescriptor_9df40050e88fbc16, []int{23, 0}
 }
 func (m *JSONElement_JSONObject) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2384,7 +2486,7 @@ func (m *JSONElement_JSONArray) Reset()         { *m = JSONElement_JSONArray{} }
 func (m *JSONElement_JSONArray) String() string { return proto.CompactTextString(m) }
 func (*JSONElement_JSONArray) ProtoMessage()    {}
 func (*JSONElement_JSONArray) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{21, 1}
+	return fileDescriptor_9df40050e88fbc16, []int{23, 1}
 }
 func (m *JSONElement_JSONArray) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2456,7 +2558,7 @@ func (m *JSONElement_Primitive) Reset()         { *m = JSONElement_Primitive{} }
 func (m *JSONElement_Primitive) String() string { return proto.CompactTextString(m) }
 func (*JSONElement_Primitive) ProtoMessage()    {}
 func (*JSONElement_Primitive) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{21, 2}
+	return fileDescriptor_9df40050e88fbc16, []int{23, 2}
 }
 func (m *JSONElement_Primitive) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2534,7 +2636,7 @@ func (m *JSONElement_Text) Reset()         { *m = JSONElement_Text{} }
 func (m *JSONElement_Text) String() string { return proto.CompactTextString(m) }
 func (*JSONElement_Text) ProtoMessage()    {}
 func (*JSONElement_Text) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{21, 3}
+	return fileDescriptor_9df40050e88fbc16, []int{23, 3}
 }
 func (m *JSONElement_Text) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2605,7 +2707,7 @@ func (m *JSONElement_RichText) Reset()         { *m = JSONElement_RichText{} }
 func (m *JSONElement_RichText) String() string { return proto.CompactTextString(m) }
 func (*JSONElement_RichText) ProtoMessage()    {}
 func (*JSONElement_RichText) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{21, 4}
+	return fileDescriptor_9df40050e88fbc16, []int{23, 4}
 }
 func (m *JSONElement_RichText) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2677,7 +2779,7 @@ func (m *JSONElement_Counter) Reset()         { *m = JSONElement_Counter{} }
 func (m *JSONElement_Counter) String() string { return proto.CompactTextString(m) }
 func (*JSONElement_Counter) ProtoMessage()    {}
 func (*JSONElement_Counter) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{21, 5}
+	return fileDescriptor_9df40050e88fbc16, []int{23, 5}
 }
 func (m *JSONElement_Counter) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2753,7 +2855,7 @@ func (m *RHTNode) Reset()         { *m = RHTNode{} }
 func (m *RHTNode) String() string { return proto.CompactTextString(m) }
 func (*RHTNode) ProtoMessage()    {}
 func (*RHTNode) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{22}
+	return fileDescriptor_9df40050e88fbc16, []int{24}
 }
 func (m *RHTNode) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2808,7 +2910,7 @@ func (m *RGANode) Reset()         { *m = RGANode{} }
 func (m *RGANode) String() string { return proto.CompactTextString(m) }
 func (*RGANode) ProtoMessage()    {}
 func (*RGANode) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{23}
+	return fileDescriptor_9df40050e88fbc16, []int{25}
 }
 func (m *RGANode) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2865,7 +2967,7 @@ func (m *TextNode) Reset()         { *m = TextNode{} }
 func (m *TextNode) String() string { return proto.CompactTextString(m) }
 func (*TextNode) ProtoMessage()    {}
 func (*TextNode) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{24}
+	return fileDescriptor_9df40050e88fbc16, []int{26}
 }
 func (m *TextNode) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2935,7 +3037,7 @@ func (m *RichTextNodeAttr) Reset()         { *m = RichTextNodeAttr{} }
 func (m *RichTextNodeAttr) String() string { return proto.CompactTextString(m) }
 func (*RichTextNodeAttr) ProtoMessage()    {}
 func (*RichTextNodeAttr) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{25}
+	return fileDescriptor_9df40050e88fbc16, []int{27}
 }
 func (m *RichTextNodeAttr) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3000,7 +3102,7 @@ func (m *RichTextNode) Reset()         { *m = RichTextNode{} }
 func (m *RichTextNode) String() string { return proto.CompactTextString(m) }
 func (*RichTextNode) ProtoMessage()    {}
 func (*RichTextNode) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{26}
+	return fileDescriptor_9df40050e88fbc16, []int{28}
 }
 func (m *RichTextNode) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3076,7 +3178,7 @@ func (m *TextNodeID) Reset()         { *m = TextNodeID{} }
 func (m *TextNodeID) String() string { return proto.CompactTextString(m) }
 func (*TextNodeID) ProtoMessage()    {}
 func (*TextNodeID) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{27}
+	return fileDescriptor_9df40050e88fbc16, []int{29}
 }
 func (m *TextNodeID) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3131,7 +3233,7 @@ func (m *Metadata) Reset()         { *m = Metadata{} }
 func (m *Metadata) String() string { return proto.CompactTextString(m) }
 func (*Metadata) ProtoMessage()    {}
 func (*Metadata) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{28}
+	return fileDescriptor_9df40050e88fbc16, []int{30}
 }
 func (m *Metadata) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3186,7 +3288,7 @@ func (m *Client) Reset()         { *m = Client{} }
 func (m *Client) String() string { return proto.CompactTextString(m) }
 func (*Client) ProtoMessage()    {}
 func (*Client) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{29}
+	return fileDescriptor_9df40050e88fbc16, []int{31}
 }
 func (m *Client) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3240,7 +3342,7 @@ func (m *Clients) Reset()         { *m = Clients{} }
 func (m *Clients) String() string { return proto.CompactTextString(m) }
 func (*Clients) ProtoMessage()    {}
 func (*Clients) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{30}
+	return fileDescriptor_9df40050e88fbc16, []int{32}
 }
 func (m *Clients) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3288,7 +3390,7 @@ func (m *DocumentKey) Reset()         { *m = DocumentKey{} }
 func (m *DocumentKey) String() string { return proto.CompactTextString(m) }
 func (*DocumentKey) ProtoMessage()    {}
 func (*DocumentKey) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{31}
+	return fileDescriptor_9df40050e88fbc16, []int{33}
 }
 func (m *DocumentKey) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3343,7 +3445,7 @@ func (m *Checkpoint) Reset()         { *m = Checkpoint{} }
 func (m *Checkpoint) String() string { return proto.CompactTextString(m) }
 func (*Checkpoint) ProtoMessage()    {}
 func (*Checkpoint) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{32}
+	return fileDescriptor_9df40050e88fbc16, []int{34}
 }
 func (m *Checkpoint) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3399,7 +3501,7 @@ func (m *TextNodePos) Reset()         { *m = TextNodePos{} }
 func (m *TextNodePos) String() string { return proto.CompactTextString(m) }
 func (*TextNodePos) ProtoMessage()    {}
 func (*TextNodePos) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{33}
+	return fileDescriptor_9df40050e88fbc16, []int{35}
 }
 func (m *TextNodePos) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3462,7 +3564,7 @@ func (m *TimeTicket) Reset()         { *m = TimeTicket{} }
 func (m *TimeTicket) String() string { return proto.CompactTextString(m) }
 func (*TimeTicket) ProtoMessage()    {}
 func (*TimeTicket) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{34}
+	return fileDescriptor_9df40050e88fbc16, []int{36}
 }
 func (m *TimeTicket) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3525,7 +3627,7 @@ func (m *DocEvent) Reset()         { *m = DocEvent{} }
 func (m *DocEvent) String() string { return proto.CompactTextString(m) }
 func (*DocEvent) ProtoMessage()    {}
 func (*DocEvent) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9df40050e88fbc16, []int{35}
+	return fileDescriptor_9df40050e88fbc16, []int{37}
 }
 func (m *DocEvent) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -3596,6 +3698,8 @@ func init() {
 	proto.RegisterType((*PushPullResponse)(nil), "api.PushPullResponse")
 	proto.RegisterType((*UpdateMetadataRequest)(nil), "api.UpdateMetadataRequest")
 	proto.RegisterType((*UpdateMetadataResponse)(nil), "api.UpdateMetadataResponse")
+	proto.RegisterType((*FetchHistoryRequest)(nil), "api.FetchHistoryRequest")
+	proto.RegisterType((*FetchHistoryResponse)(nil), "api.FetchHistoryResponse")
 	proto.RegisterType((*ChangePack)(nil), "api.ChangePack")
 	proto.RegisterType((*Change)(nil), "api.Change")
 	proto.RegisterType((*ChangeID)(nil), "api.ChangeID")
@@ -3642,159 +3746,162 @@ func init() {
 func init() { proto.RegisterFile("api/yorkie.proto", fileDescriptor_9df40050e88fbc16) }
 
 var fileDescriptor_9df40050e88fbc16 = []byte{
-	// 2425 bytes of a gzipped FileDescriptorProto
+	// 2474 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x1a, 0x4d, 0x6f, 0xdb, 0xc8,
-	0x55, 0xd4, 0x37, 0x9f, 0x64, 0x99, 0x99, 0xc4, 0x8e, 0x56, 0xf9, 0x68, 0xc2, 0x6c, 0x9a, 0x8f,
-	0x0d, 0x9c, 0xc0, 0xdb, 0x4d, 0xb6, 0xbb, 0xd8, 0x02, 0xb4, 0x24, 0x58, 0xda, 0xc4, 0xb2, 0x4b,
-	0x29, 0x9b, 0xe6, 0xa4, 0xd2, 0xe4, 0x38, 0x66, 0x2c, 0x89, 0x0c, 0x49, 0x19, 0x51, 0x0f, 0x3d,
-	0xf6, 0xd0, 0x6b, 0x7b, 0x68, 0xaf, 0x45, 0x81, 0xfd, 0x03, 0x05, 0x7a, 0x68, 0x81, 0x1c, 0x7a,
-	0xc9, 0x6d, 0xdb, 0x63, 0x51, 0xa0, 0x28, 0xd2, 0x4b, 0xcf, 0xfd, 0x05, 0xc5, 0x7c, 0x90, 0x22,
-	0x29, 0xda, 0xb2, 0x9a, 0xcd, 0xae, 0xb1, 0x37, 0xce, 0xbc, 0xef, 0x79, 0x6f, 0xde, 0x7b, 0x9c,
-	0x19, 0x90, 0x34, 0xdb, 0xbc, 0x3b, 0xb1, 0x9c, 0x03, 0x13, 0xaf, 0xd9, 0x8e, 0xe5, 0x59, 0x28,
-	0xa3, 0xd9, 0xa6, 0xdc, 0x87, 0x95, 0x0d, 0xc7, 0xd2, 0x0c, 0x5d, 0x73, 0xbd, 0xe6, 0x21, 0x1e,
-	0x79, 0x2a, 0x7e, 0x31, 0xc6, 0xae, 0x87, 0xae, 0x42, 0xd9, 0x1e, 0xef, 0x0e, 0x4c, 0x77, 0x1f,
-	0x3b, 0x7d, 0xd3, 0xa8, 0x0a, 0x57, 0x84, 0x9b, 0x65, 0xb5, 0x14, 0xcc, 0xb5, 0x0d, 0x74, 0x0d,
-	0x72, 0x98, 0x90, 0x54, 0xd3, 0x57, 0x84, 0x9b, 0xa5, 0xf5, 0xa5, 0x35, 0xcd, 0x36, 0xd7, 0x1a,
-	0x96, 0xce, 0xf8, 0x30, 0x98, 0x5c, 0x85, 0xd5, 0xb8, 0x00, 0xd7, 0xb6, 0x46, 0x2e, 0x96, 0xef,
-	0xc3, 0x8a, 0xa2, 0x7b, 0xe6, 0xa1, 0xe6, 0xe1, 0xfa, 0xc0, 0x0c, 0x89, 0xbe, 0x04, 0xa0, 0xd3,
-	0x89, 0xfe, 0x01, 0x9e, 0x50, 0xc1, 0xa2, 0x2a, 0xb2, 0x99, 0x87, 0x78, 0x22, 0xf7, 0x60, 0x35,
-	0x4e, 0xc7, 0x38, 0xce, 0x21, 0x44, 0x17, 0x80, 0x0f, 0x88, 0x3d, 0x69, 0x6a, 0x4f, 0x91, 0x4d,
-	0xb4, 0x0d, 0xf9, 0x3e, 0x9c, 0x6f, 0x60, 0x2d, 0x51, 0x9f, 0x08, 0x9d, 0x10, 0xa3, 0x7b, 0x00,
-	0xd5, 0x59, 0x3a, 0xae, 0xcf, 0xb1, 0x84, 0x7b, 0xb0, 0xa2, 0x78, 0x9e, 0xa6, 0xef, 0x37, 0x2c,
-	0x7d, 0x3c, 0x3c, 0xa1, 0x38, 0x74, 0x0f, 0x4a, 0xfa, 0xbe, 0x36, 0x7a, 0x86, 0xfb, 0xb6, 0xa6,
-	0x1f, 0xf0, 0x95, 0x5f, 0xa6, 0x2b, 0x5f, 0xa7, 0xf3, 0x3b, 0x9a, 0x7e, 0xa0, 0x82, 0x1e, 0x7c,
-	0xcb, 0xcf, 0x60, 0x35, 0x2e, 0xe7, 0x04, 0xea, 0xfd, 0x1f, 0x82, 0xf6, 0x60, 0xa5, 0x81, 0xbf,
-	0x01, 0x83, 0x4c, 0x58, 0x8d, 0xcb, 0x39, 0x99, 0xff, 0x17, 0x17, 0xe5, 0xc2, 0xca, 0x13, 0xcd,
-	0x9b, 0x4a, 0x72, 0x7d, 0x93, 0xae, 0x41, 0x9e, 0xf1, 0xa5, 0x52, 0x4a, 0xeb, 0x25, 0xc6, 0x85,
-	0xb9, 0x9f, 0x83, 0xd0, 0x47, 0xb0, 0x64, 0x70, 0x42, 0xa2, 0x90, 0x5b, 0x4d, 0x5f, 0xc9, 0xdc,
-	0x2c, 0xad, 0x4b, 0xfe, 0x3e, 0xa1, 0x90, 0x87, 0x78, 0xa2, 0x96, 0x8d, 0xe9, 0xc0, 0x95, 0xff,
-	0x93, 0x86, 0xd5, 0xb8, 0x54, 0x6e, 0x60, 0x0f, 0x2a, 0xe6, 0xc8, 0xf4, 0x4c, 0x6d, 0x60, 0xfe,
-	0x4c, 0xf3, 0x4c, 0x6b, 0xc4, 0xc5, 0xdf, 0xa6, 0x2c, 0x93, 0x89, 0xd6, 0xda, 0x11, 0x8a, 0x56,
-	0x4a, 0x8d, 0xf1, 0x40, 0xd7, 0x8f, 0xdb, 0xc7, 0xad, 0x14, 0xdf, 0xc9, 0xb5, 0xd7, 0x02, 0x54,
-	0xa2, 0xbc, 0xd0, 0x1e, 0x48, 0x36, 0xc6, 0x8e, 0xdb, 0x1f, 0x6a, 0x76, 0x7f, 0x77, 0xd2, 0x37,
-	0x2c, 0xbd, 0x2a, 0x50, 0x23, 0x3f, 0x3b, 0xb9, 0x46, 0x6b, 0x3b, 0x84, 0xc5, 0x96, 0x66, 0x6f,
-	0x4c, 0x88, 0xd0, 0x91, 0xe7, 0x4c, 0xd4, 0x25, 0x3b, 0x3c, 0x57, 0xeb, 0x00, 0x9a, 0x45, 0x42,
-	0x12, 0x64, 0xa6, 0x7e, 0x26, 0x9f, 0x48, 0x86, 0xdc, 0xa1, 0x36, 0x18, 0x63, 0x6e, 0x49, 0x39,
-	0xe4, 0x15, 0x57, 0x65, 0xa0, 0x4f, 0xd2, 0x1f, 0x0b, 0x1b, 0x79, 0xc8, 0xee, 0x5a, 0xc6, 0x44,
-	0xfe, 0x29, 0x2c, 0xef, 0x8c, 0xdd, 0xfd, 0x9d, 0xf1, 0x60, 0xf0, 0x8e, 0x82, 0x55, 0x03, 0x69,
-	0x2a, 0xe1, 0xdd, 0xec, 0x3b, 0x17, 0x56, 0x1e, 0xdb, 0x86, 0xe6, 0xe1, 0x2d, 0xec, 0x69, 0x86,
-	0xe6, 0x69, 0xdf, 0x44, 0x90, 0x56, 0x61, 0x35, 0x2e, 0x94, 0xa7, 0xf5, 0xff, 0x0a, 0x00, 0x53,
-	0x4d, 0xd1, 0x87, 0x50, 0x0e, 0xf3, 0xe7, 0xaa, 0xcc, 0xb2, 0x2f, 0x85, 0xd8, 0xa3, 0xbb, 0x00,
-	0xfa, 0x3e, 0xd6, 0x0f, 0x6c, 0xcb, 0x0c, 0xc2, 0xd2, 0x5f, 0x03, 0x7f, 0x5a, 0x0d, 0xa1, 0xa0,
-	0x1a, 0x14, 0xdd, 0x91, 0x66, 0xbb, 0xfb, 0x96, 0x57, 0xcd, 0xb0, 0x15, 0xf5, 0xc7, 0xe8, 0x3a,
-	0x14, 0xd8, 0x6a, 0xb9, 0xd5, 0x2c, 0xb5, 0xad, 0x14, 0x5a, 0x4d, 0xd5, 0x87, 0xa1, 0x4f, 0xe1,
-	0xcc, 0xd0, 0x1c, 0xf5, 0xdd, 0xc9, 0x48, 0xc7, 0x46, 0xdf, 0x33, 0xf5, 0x03, 0xec, 0x55, 0x73,
-	0x21, 0xd1, 0x3d, 0x73, 0x88, 0x7b, 0x74, 0x5a, 0x5d, 0x1e, 0x9a, 0xa3, 0x2e, 0x45, 0x64, 0x13,
-	0xf2, 0x0b, 0xc8, 0x33, 0x7e, 0xe8, 0x12, 0xa4, 0xb9, 0x57, 0xfd, 0x9d, 0xc4, 0x00, 0xed, 0x86,
-	0x9a, 0x36, 0x0d, 0x54, 0x85, 0xc2, 0x10, 0xbb, 0xae, 0xf6, 0x8c, 0xc5, 0xa8, 0xa8, 0xfa, 0x43,
-	0xb4, 0x06, 0x60, 0xd9, 0xd8, 0xa1, 0x5b, 0xc2, 0xad, 0x66, 0xa8, 0xa6, 0x15, 0xca, 0x60, 0xdb,
-	0x9f, 0x56, 0x43, 0x18, 0xf2, 0x2e, 0x14, 0x7d, 0xce, 0xa1, 0xc4, 0xe7, 0xe2, 0x17, 0x54, 0xf8,
-	0x92, 0x9f, 0xf8, 0xba, 0xf8, 0x05, 0xba, 0x08, 0x85, 0x81, 0x36, 0xb4, 0x2d, 0x87, 0xad, 0x65,
-	0x76, 0x23, 0x7d, 0x4f, 0x50, 0xfd, 0x29, 0xf4, 0x1e, 0x14, 0x35, 0xdd, 0xb3, 0x68, 0x95, 0x67,
-	0x6b, 0x57, 0xa0, 0xe3, 0xb6, 0x21, 0xbf, 0x5e, 0x05, 0x31, 0x90, 0x8e, 0xbe, 0x0f, 0x19, 0x17,
-	0xfb, 0xc1, 0x84, 0xa2, 0xaa, 0xad, 0x75, 0x31, 0x49, 0x15, 0x04, 0x81, 0xe0, 0x69, 0x86, 0xc1,
-	0xdd, 0x16, 0xc7, 0x53, 0x0c, 0x83, 0xe0, 0x69, 0x86, 0x81, 0x6e, 0x41, 0x76, 0x68, 0x1d, 0x62,
-	0x2a, 0xb4, 0xb4, 0x7e, 0x36, 0x86, 0xb8, 0x65, 0x1d, 0xe2, 0x56, 0x4a, 0xa5, 0x28, 0xe8, 0x2e,
-	0xe4, 0x1d, 0x4c, 0x91, 0xb3, 0x14, 0x79, 0x25, 0x86, 0xac, 0x52, 0x60, 0x2b, 0xa5, 0x72, 0x34,
-	0xc2, 0x1b, 0x1b, 0xa6, 0xef, 0xc0, 0x38, 0xef, 0xa6, 0x61, 0x12, 0x6d, 0x29, 0x0a, 0xe1, 0xed,
-	0xe2, 0x01, 0xd6, 0xbd, 0x6a, 0x3e, 0x91, 0x77, 0x97, 0x02, 0x09, 0x6f, 0x86, 0x86, 0xee, 0x83,
-	0xe8, 0x98, 0xfa, 0x7e, 0x9f, 0x0a, 0x28, 0x50, 0x9a, 0xf3, 0x71, 0x7d, 0x4c, 0x7d, 0x9f, 0x0b,
-	0x29, 0x3a, 0xfc, 0x1b, 0xdd, 0x81, 0x9c, 0xeb, 0x4d, 0x06, 0xb8, 0x5a, 0xa4, 0x34, 0xe7, 0xe2,
-	0x72, 0x08, 0x8c, 0xa4, 0x5b, 0x8a, 0x84, 0x3e, 0x82, 0xa2, 0x39, 0xd2, 0x1d, 0xac, 0xb9, 0xb8,
-	0x2a, 0x26, 0x0a, 0x69, 0x73, 0x30, 0x11, 0xe2, 0xa3, 0xd6, 0xfe, 0x20, 0x40, 0xa6, 0x8b, 0x3d,
-	0x12, 0xce, 0xb6, 0xe6, 0x90, 0x90, 0x20, 0x00, 0x0f, 0x1b, 0x7d, 0xcd, 0x77, 0xdd, 0x6c, 0x38,
-	0x33, 0xcc, 0x3a, 0x43, 0x54, 0x3c, 0x3f, 0xb3, 0xa6, 0xa7, 0x99, 0xf5, 0x8e, 0x9f, 0x59, 0x99,
-	0xb3, 0x56, 0x29, 0x8b, 0xcf, 0xbb, 0xdb, 0x9d, 0xe6, 0x00, 0x93, 0x5d, 0xdb, 0x35, 0x87, 0xf6,
-	0x00, 0xf3, 0x1c, 0x4b, 0x92, 0x18, 0x7e, 0x89, 0xf5, 0x31, 0x17, 0x9b, 0x4d, 0x16, 0x0b, 0x3e,
-	0x8e, 0xe2, 0xd5, 0xfe, 0x21, 0x40, 0x46, 0x31, 0x8c, 0xb7, 0x53, 0xfb, 0x01, 0x2c, 0xdb, 0x0e,
-	0x3e, 0x0c, 0x93, 0xa6, 0x93, 0x49, 0x97, 0x08, 0xde, 0x94, 0xf0, 0x5d, 0x5b, 0xf7, 0x4f, 0x01,
-	0xb2, 0x24, 0x9e, 0xbf, 0x25, 0xf3, 0xd6, 0x00, 0x42, 0x34, 0x99, 0x64, 0x1a, 0x51, 0x0f, 0xf0,
-	0x17, 0x37, 0xf0, 0x4b, 0x01, 0xf2, 0x6c, 0x0f, 0xbe, 0x9d, 0x89, 0x51, 0x4d, 0xd3, 0x8b, 0x6a,
-	0x9a, 0x99, 0xaf, 0xe9, 0xaf, 0x33, 0x90, 0xa5, 0xbb, 0xf1, 0xad, 0xf4, 0x7c, 0x1f, 0xb2, 0x7b,
-	0x8e, 0x35, 0xe4, 0x1a, 0xb2, 0x6a, 0xd6, 0xc3, 0x2f, 0xbd, 0x8e, 0x65, 0xe0, 0x1d, 0xcb, 0x55,
-	0x29, 0x14, 0x5d, 0x81, 0xb4, 0x67, 0x71, 0xa5, 0x66, 0x71, 0xd2, 0x9e, 0x85, 0x76, 0xe1, 0xfc,
-	0x54, 0xba, 0xdf, 0x45, 0xd1, 0xec, 0xcb, 0x6b, 0xd5, 0x9d, 0x84, 0xcc, 0xb5, 0x16, 0xe8, 0x41,
-	0xfb, 0x21, 0x85, 0xa0, 0xb3, 0xb6, 0xe9, 0xac, 0x3e, 0x0b, 0x21, 0x25, 0x47, 0xb7, 0x46, 0x1e,
-	0xe9, 0x03, 0x72, 0xac, 0xe4, 0xf0, 0x61, 0x7c, 0xf5, 0xf2, 0xf3, 0x57, 0xef, 0x09, 0x54, 0x8f,
-	0x12, 0x9e, 0xd0, 0x8e, 0x5d, 0x8f, 0xb6, 0x63, 0x33, 0x9c, 0xa7, 0x1d, 0x59, 0xed, 0x95, 0x00,
-	0x79, 0x96, 0x68, 0x4f, 0x87, 0x63, 0x16, 0xdf, 0x02, 0xbf, 0xcf, 0x42, 0xd1, 0x4f, 0xfb, 0xa7,
-	0xc3, 0x86, 0xbd, 0x79, 0xc1, 0x75, 0xef, 0x88, 0xaa, 0xf5, 0xb5, 0x05, 0xd8, 0x26, 0x80, 0xe6,
-	0x79, 0x8e, 0xb9, 0x3b, 0xf6, 0xb0, 0x5b, 0xcd, 0x53, 0xa1, 0x37, 0x8e, 0x12, 0xaa, 0x04, 0x98,
-	0x4c, 0x56, 0x88, 0x34, 0xee, 0x8e, 0xc2, 0xb7, 0x18, 0xa9, 0x9f, 0xc1, 0x72, 0x4c, 0xd3, 0x04,
-	0x7e, 0xe7, 0xc2, 0xfc, 0xc4, 0x30, 0xf9, 0x5f, 0xd2, 0x90, 0xa3, 0x95, 0xfe, 0x74, 0xc4, 0x48,
-	0x23, 0xe2, 0x21, 0x16, 0x16, 0xef, 0x27, 0x35, 0x26, 0x8b, 0xb8, 0x27, 0x37, 0xdf, 0x3d, 0x6f,
-	0xb9, 0x8a, 0x5f, 0x0a, 0x50, 0xf4, 0xdb, 0x9f, 0xb7, 0x5b, 0xc8, 0x3b, 0x51, 0xcf, 0x2f, 0x56,
-	0xfa, 0xe7, 0xd7, 0x9b, 0xe0, 0x57, 0xf3, 0xef, 0x02, 0x9c, 0x99, 0x61, 0x1b, 0xab, 0x77, 0xc2,
-	0xdc, 0x7a, 0x77, 0x1b, 0x8a, 0xa4, 0xc8, 0x1e, 0x57, 0x1d, 0x0b, 0x14, 0x81, 0xd5, 0x52, 0xd6,
-	0x0c, 0x1f, 0x5b, 0xf5, 0x39, 0x8a, 0xe2, 0x21, 0x19, 0xb2, 0xde, 0xc4, 0x66, 0x1d, 0x76, 0x85,
-	0xff, 0x7a, 0x7c, 0x41, 0xac, 0xee, 0x4d, 0x6c, 0xac, 0x52, 0xd8, 0xd4, 0x23, 0x39, 0xfa, 0xa3,
-	0xc0, 0x06, 0xf2, 0x2f, 0xcb, 0x50, 0x0a, 0xd9, 0x86, 0x7e, 0x04, 0xa5, 0xe7, 0xae, 0x35, 0xea,
-	0x5b, 0xbb, 0xcf, 0x49, 0x5b, 0xcd, 0xcc, 0xba, 0x10, 0x5f, 0x59, 0xfa, 0xbd, 0x4d, 0x51, 0x5a,
-	0x29, 0x15, 0x08, 0x05, 0x1b, 0xa1, 0x4f, 0x81, 0x8e, 0xfa, 0x9a, 0xe3, 0x68, 0x13, 0x6e, 0x67,
-	0x2d, 0x91, 0x5c, 0x21, 0x18, 0xad, 0x94, 0x2a, 0x12, 0x7c, 0x3a, 0x40, 0x9f, 0x80, 0x68, 0x3b,
-	0xe6, 0xd0, 0xf4, 0xcc, 0xe0, 0xd7, 0x62, 0x96, 0x76, 0xc7, 0xc7, 0x20, 0xb4, 0x01, 0x3a, 0xfa,
-	0x00, 0xb2, 0x1e, 0x7e, 0xe9, 0x45, 0x7e, 0x32, 0xc2, 0x64, 0x64, 0xf7, 0x90, 0xff, 0x06, 0x82,
-	0x84, 0x3e, 0xe6, 0xbf, 0x01, 0x94, 0x82, 0x85, 0xfc, 0x7b, 0x33, 0x14, 0x24, 0xbb, 0x71, 0x2a,
-	0xfa, 0x23, 0x40, 0xbe, 0xd1, 0x0f, 0x48, 0xc2, 0x1c, 0x8f, 0x3c, 0xec, 0xf0, 0x9a, 0x5b, 0x9d,
-	0xa1, 0xab, 0x33, 0x78, 0x2b, 0xa5, 0xfa, 0xa8, 0xb5, 0x3f, 0x0b, 0x00, 0xd3, 0x25, 0x43, 0x32,
-	0xe4, 0x46, 0x96, 0x81, 0x5d, 0x7e, 0xe0, 0xc2, 0xce, 0x3a, 0xd4, 0x56, 0x8f, 0xec, 0x6e, 0x95,
-	0x81, 0x16, 0x6e, 0xa7, 0xc2, 0xe1, 0x95, 0x59, 0x28, 0xbc, 0xb2, 0xf3, 0xc2, 0xab, 0xf6, 0x27,
-	0x01, 0xc4, 0xc0, 0x65, 0x47, 0x68, 0xbf, 0xa9, 0x9c, 0x56, 0xed, 0xff, 0x26, 0x80, 0x18, 0x04,
-	0x4d, 0xb0, 0x55, 0x84, 0x93, 0x6c, 0x95, 0x74, 0x68, 0xab, 0x2c, 0xdc, 0x8a, 0x87, 0x6d, 0xca,
-	0x2e, 0x64, 0x53, 0x6e, 0xae, 0x4d, 0x7f, 0x14, 0x20, 0x4b, 0xe3, 0xf1, 0x5a, 0xd4, 0x19, 0x4b,
-	0x91, 0x4a, 0x71, 0x1a, 0xbd, 0xf1, 0x4a, 0x60, 0xbd, 0x16, 0xd5, 0xfe, 0x46, 0x54, 0xfb, 0x33,
-	0x2c, 0x94, 0x38, 0xf4, 0xb4, 0x5a, 0xf0, 0x95, 0x00, 0x05, 0xbe, 0xc7, 0xbf, 0x1b, 0xd1, 0x44,
-	0x0a, 0xdd, 0x06, 0x29, 0x74, 0x9b, 0x50, 0xe0, 0x59, 0x28, 0xa1, 0xa2, 0xdf, 0x86, 0x02, 0x66,
-	0x19, 0x2e, 0xd2, 0xb9, 0x84, 0x32, 0x9f, 0xea, 0x23, 0xc8, 0x4f, 0xa0, 0xc0, 0x13, 0x02, 0xba,
-	0x02, 0xd9, 0x11, 0xc9, 0xb2, 0x42, 0xe8, 0x58, 0xd7, 0x4f, 0x16, 0x14, 0xb2, 0x10, 0xe3, 0xdf,
-	0x09, 0x50, 0xf4, 0x63, 0x03, 0x7d, 0x2f, 0x74, 0x5e, 0xb7, 0x1c, 0x09, 0x7c, 0x7e, 0x62, 0x97,
-	0xd8, 0x84, 0x2c, 0x5c, 0x5c, 0xef, 0x42, 0xc9, 0x1c, 0xb9, 0x7d, 0xfa, 0xff, 0x6e, 0x1a, 0xd1,
-	0xc5, 0x9f, 0xca, 0x13, 0xcd, 0x91, 0xbb, 0xe3, 0xe0, 0xc3, 0xb6, 0x21, 0x3f, 0x07, 0x29, 0x1c,
-	0xc3, 0xa4, 0x59, 0x3a, 0x69, 0x87, 0x44, 0x94, 0x1b, 0xd3, 0xc3, 0xd9, 0x63, 0x95, 0xe3, 0x28,
-	0x8a, 0x27, 0xbf, 0x4a, 0x43, 0x39, 0x2c, 0x6c, 0xfe, 0xa2, 0x28, 0x91, 0xb6, 0x91, 0x1d, 0x19,
-	0x5f, 0x9d, 0xd9, 0x78, 0xc7, 0xf6, 0x8c, 0xe7, 0xc2, 0x67, 0x2e, 0x47, 0xac, 0x6b, 0x76, 0xd1,
-	0x75, 0xcd, 0xcd, 0x5b, 0xd7, 0x5a, 0xef, 0x24, 0x8d, 0xe7, 0x07, 0xd1, 0xa6, 0x70, 0x65, 0xc6,
-	0x32, 0xc2, 0x22, 0xd4, 0x8f, 0xca, 0x3d, 0x80, 0xa9, 0xb8, 0x85, 0xbb, 0xba, 0x55, 0xc8, 0x5b,
-	0x7b, 0x7b, 0x2e, 0x66, 0xb1, 0x9b, 0x53, 0xf9, 0x48, 0xfe, 0x85, 0x00, 0x45, 0xff, 0x7c, 0x9d,
-	0xac, 0x97, 0x3e, 0xb0, 0xf4, 0x03, 0xca, 0x2f, 0xa7, 0xb2, 0x01, 0xe9, 0x58, 0x08, 0x94, 0xbb,
-	0x80, 0x9d, 0x10, 0xfa, 0x24, 0x6b, 0x0d, 0xcd, 0xd3, 0xd8, 0xc2, 0x53, 0xa4, 0xda, 0x03, 0x10,
-	0x83, 0xa9, 0x45, 0xda, 0x6d, 0xb9, 0x0e, 0x79, 0x76, 0x6d, 0x80, 0x2a, 0x41, 0x64, 0x94, 0x69,
-	0x20, 0xdc, 0x82, 0xe2, 0x90, 0x8b, 0x8b, 0x5c, 0x1f, 0x05, 0xd7, 0x02, 0x01, 0x58, 0xbe, 0x07,
-	0x05, 0x7e, 0x15, 0x43, 0x8f, 0xe4, 0xd9, 0x27, 0x4f, 0xda, 0x91, 0xab, 0x09, 0x1f, 0x26, 0xb7,
-	0xa1, 0x14, 0xba, 0x22, 0x40, 0x97, 0x01, 0x74, 0x6b, 0x30, 0xc0, 0x7a, 0x70, 0xf3, 0x25, 0xaa,
-	0xa1, 0x19, 0x54, 0x83, 0xa2, 0x7f, 0x89, 0xc0, 0x4d, 0x08, 0xc6, 0x72, 0x07, 0x60, 0x7a, 0x75,
-	0x80, 0xae, 0x02, 0xb8, 0xd8, 0x39, 0xc4, 0x4e, 0x70, 0x5e, 0xce, 0xce, 0xc4, 0x45, 0x36, 0xdb,
-	0xc5, 0x2f, 0x62, 0x47, 0xea, 0xe9, 0xd8, 0x91, 0xba, 0xfc, 0x73, 0x28, 0x85, 0x7e, 0xa5, 0xbe,
-	0x2e, 0x8f, 0xa3, 0x1b, 0xb0, 0xec, 0xe0, 0x81, 0x46, 0x9a, 0x8c, 0x3e, 0x47, 0xc8, 0x50, 0x84,
-	0x8a, 0x3f, 0xbd, 0xcd, 0x42, 0x43, 0x07, 0x98, 0x72, 0x0e, 0x1f, 0xf0, 0x0b, 0xb3, 0x07, 0xfc,
-	0x17, 0x41, 0x34, 0xf0, 0x80, 0xf4, 0x2e, 0xd8, 0xf1, 0x2d, 0x09, 0x26, 0x8e, 0x3b, 0xfe, 0xff,
-	0x95, 0x00, 0x45, 0xff, 0x1e, 0x10, 0x5d, 0x8f, 0x54, 0xa9, 0x33, 0x91, 0x4b, 0xc2, 0x50, 0xa1,
-	0xba, 0x05, 0x62, 0xf0, 0x46, 0x80, 0x47, 0x44, 0xc4, 0xb9, 0x53, 0xe8, 0xec, 0xd5, 0x53, 0xe6,
-	0x24, 0x57, 0x4f, 0xb7, 0xbf, 0x12, 0x40, 0x0c, 0xca, 0x23, 0x2a, 0x42, 0xb6, 0xf3, 0xf8, 0xd1,
-	0x23, 0x29, 0x85, 0x4a, 0x50, 0xd8, 0xd8, 0xde, 0x7e, 0xd4, 0x54, 0x3a, 0x92, 0x40, 0x06, 0xed,
-	0x4e, 0xaf, 0xb9, 0xd9, 0x54, 0xa5, 0x34, 0xc1, 0x79, 0xb4, 0xdd, 0xd9, 0x94, 0x32, 0x08, 0x20,
-	0xdf, 0xd8, 0x7e, 0xbc, 0xf1, 0xa8, 0x29, 0x65, 0xc9, 0x77, 0xb7, 0xa7, 0xb6, 0x3b, 0x9b, 0x52,
-	0x0e, 0x89, 0x90, 0xdb, 0x78, 0xda, 0x6b, 0x76, 0xa5, 0x3c, 0x41, 0x6e, 0x28, 0xbd, 0xa6, 0x54,
-	0x40, 0xcb, 0xec, 0xaf, 0xa6, 0xbf, 0xbd, 0xf1, 0x79, 0xb3, 0xde, 0x93, 0x8a, 0xa8, 0xc2, 0x1a,
-	0xf0, 0xbe, 0xa2, 0xaa, 0xca, 0x53, 0x49, 0x24, 0xa8, 0xbd, 0xe6, 0x4f, 0x7a, 0x12, 0xa0, 0x25,
-	0x10, 0xd5, 0x76, 0xbd, 0xd5, 0xa7, 0xc3, 0x12, 0xa1, 0xe4, 0xd2, 0xfb, 0xf5, 0x4e, 0x4f, 0x2a,
-	0xa3, 0x32, 0x14, 0x89, 0x06, 0x74, 0xb4, 0x44, 0xf8, 0x30, 0x2d, 0xe8, 0xb8, 0x72, 0xfb, 0x00,
-	0xca, 0xe1, 0x95, 0x44, 0x2b, 0x70, 0xa6, 0xb1, 0x5d, 0x7f, 0xbc, 0xd5, 0xec, 0xf4, 0xba, 0xfd,
-	0x7a, 0x4b, 0xe9, 0x6c, 0x36, 0x1b, 0x52, 0x2a, 0x3a, 0xfd, 0x44, 0xe9, 0xd5, 0x5b, 0xcd, 0x86,
-	0x24, 0xa0, 0xf3, 0x70, 0x76, 0x3a, 0xfd, 0xb8, 0xe3, 0x03, 0xd2, 0xe8, 0x1c, 0x48, 0x5b, 0xcd,
-	0x9e, 0xd2, 0x50, 0x7a, 0x4a, 0xc0, 0x25, 0xb3, 0xfe, 0xdb, 0x2c, 0xe4, 0x9f, 0xd2, 0x77, 0x20,
-	0xe8, 0x21, 0x54, 0xa2, 0x2f, 0x29, 0x10, 0xfb, 0x53, 0x4a, 0x7c, 0x96, 0x51, 0xbb, 0x90, 0x08,
-	0xe3, 0xb7, 0x7e, 0x29, 0xf4, 0x63, 0x90, 0xe2, 0x0f, 0x21, 0xd0, 0x45, 0xe6, 0xca, 0xe4, 0x77,
-	0x15, 0xb5, 0x4b, 0x47, 0x40, 0x03, 0x96, 0x44, 0xbf, 0xc8, 0xd3, 0x05, 0x5f, 0xbf, 0xa4, 0x77,
-	0x13, 0xbe, 0x7e, 0x89, 0x6f, 0x1d, 0x18, 0xb3, 0xe8, 0xb3, 0x01, 0xce, 0x2c, 0xf1, 0xcd, 0x02,
-	0x67, 0x96, 0xfc, 0xce, 0x40, 0x4e, 0xa1, 0x2d, 0xa8, 0x44, 0xef, 0xb6, 0x39, 0xb3, 0xc4, 0xd7,
-	0x02, 0x9c, 0x59, 0xf2, 0x65, 0xb8, 0x9c, 0xba, 0x27, 0xa0, 0x1f, 0x42, 0xd1, 0xbf, 0x25, 0x46,
-	0xec, 0x5a, 0x28, 0x76, 0x2d, 0x5d, 0x5b, 0x89, 0xcd, 0x86, 0xcd, 0x8a, 0x5e, 0xc4, 0x72, 0x4d,
-	0x12, 0xaf, 0x84, 0xb9, 0x26, 0x47, 0xdc, 0xdc, 0xa6, 0xd6, 0xbf, 0x20, 0x29, 0x7a, 0xec, 0x92,
-	0xb4, 0xf0, 0x10, 0x2a, 0xd1, 0x77, 0x3b, 0x9c, 0x6f, 0xe2, 0x6b, 0x21, 0xce, 0xf7, 0x88, 0x87,
-	0x3e, 0xa9, 0x0d, 0xe9, 0xf5, 0x9b, 0xcb, 0xc2, 0x5f, 0xdf, 0x5c, 0x16, 0xfe, 0xf5, 0xe6, 0xb2,
-	0xf0, 0x9b, 0x7f, 0x5f, 0x4e, 0xed, 0xe6, 0xe9, 0x1b, 0xa4, 0x0f, 0xff, 0x17, 0x00, 0x00, 0xff,
-	0xff, 0x43, 0x66, 0xb0, 0xc7, 0x97, 0x24, 0x00, 0x00,
+	0x55, 0xd4, 0x37, 0x9f, 0x64, 0x99, 0x99, 0xc4, 0x8e, 0x56, 0x9b, 0xa4, 0x09, 0xb3, 0x69, 0x3e,
+	0x36, 0x70, 0x02, 0x6f, 0x37, 0xd9, 0xee, 0x22, 0x05, 0x68, 0x49, 0xb5, 0xb4, 0x89, 0x65, 0x97,
+	0x52, 0x36, 0xcd, 0x49, 0xa5, 0xc9, 0x71, 0xcc, 0x58, 0x12, 0x19, 0x92, 0x32, 0xa2, 0x1e, 0x7a,
+	0xec, 0xa1, 0xd7, 0xf6, 0xd0, 0x73, 0x51, 0x60, 0xff, 0x40, 0x81, 0x1e, 0x5a, 0x20, 0x87, 0x5e,
+	0x72, 0xdb, 0xf6, 0x58, 0x14, 0x28, 0x16, 0xe9, 0xa5, 0xe7, 0xfe, 0x82, 0x62, 0x3e, 0x48, 0x91,
+	0x14, 0x6d, 0x59, 0xcd, 0x66, 0xd7, 0xe8, 0x8d, 0x33, 0xef, 0x7b, 0xde, 0x9b, 0x79, 0x8f, 0xf3,
+	0x06, 0x24, 0xcd, 0x36, 0xef, 0x4c, 0x2c, 0xe7, 0xc0, 0xc4, 0x6b, 0xb6, 0x63, 0x79, 0x16, 0xca,
+	0x68, 0xb6, 0x29, 0xf7, 0x61, 0x65, 0xc3, 0xb1, 0x34, 0x43, 0xd7, 0x5c, 0xaf, 0x79, 0x88, 0x47,
+	0x9e, 0x8a, 0x5f, 0x8c, 0xb1, 0xeb, 0xa1, 0x2b, 0x50, 0xb6, 0xc7, 0xbb, 0x03, 0xd3, 0xdd, 0xc7,
+	0x4e, 0xdf, 0x34, 0xaa, 0xc2, 0x65, 0xe1, 0x46, 0x59, 0x2d, 0x05, 0x73, 0x6d, 0x03, 0x5d, 0x85,
+	0x1c, 0x26, 0x24, 0xd5, 0xf4, 0x65, 0xe1, 0x46, 0x69, 0x7d, 0x69, 0x4d, 0xb3, 0xcd, 0xb5, 0x86,
+	0xa5, 0x33, 0x3e, 0x0c, 0x26, 0x57, 0x61, 0x35, 0x2e, 0xc0, 0xb5, 0xad, 0x91, 0x8b, 0xe5, 0x7b,
+	0xb0, 0xa2, 0xe8, 0x9e, 0x79, 0xa8, 0x79, 0xb8, 0x3e, 0x30, 0x43, 0xa2, 0x2f, 0x02, 0xe8, 0x74,
+	0xa2, 0x7f, 0x80, 0x27, 0x54, 0xb0, 0xa8, 0x8a, 0x6c, 0xe6, 0x21, 0x9e, 0xc8, 0x3d, 0x58, 0x8d,
+	0xd3, 0x31, 0x8e, 0x73, 0x08, 0xd1, 0xfb, 0xc0, 0x07, 0xc4, 0x9e, 0x34, 0xb5, 0xa7, 0xc8, 0x26,
+	0xda, 0x86, 0x7c, 0x0f, 0xce, 0x37, 0xb0, 0x96, 0xa8, 0x4f, 0x84, 0x4e, 0x88, 0xd1, 0xdd, 0x87,
+	0xea, 0x2c, 0x1d, 0xd7, 0xe7, 0x58, 0xc2, 0x3d, 0x58, 0x51, 0x3c, 0x4f, 0xd3, 0xf7, 0x1b, 0x96,
+	0x3e, 0x1e, 0x9e, 0x50, 0x1c, 0xba, 0x0b, 0x25, 0x7d, 0x5f, 0x1b, 0x3d, 0xc3, 0x7d, 0x5b, 0xd3,
+	0x0f, 0xf8, 0xca, 0x2f, 0xd3, 0x95, 0xaf, 0xd3, 0xf9, 0x1d, 0x4d, 0x3f, 0x50, 0x41, 0x0f, 0xbe,
+	0xe5, 0x67, 0xb0, 0x1a, 0x97, 0x73, 0x02, 0xf5, 0xfe, 0x07, 0x41, 0x7b, 0xb0, 0xd2, 0xc0, 0xdf,
+	0x82, 0x41, 0x26, 0xac, 0xc6, 0xe5, 0x9c, 0xcc, 0xff, 0x8b, 0x8b, 0x72, 0x61, 0xe5, 0x89, 0xe6,
+	0x4d, 0x25, 0xb9, 0xbe, 0x49, 0x57, 0x21, 0xcf, 0xf8, 0x52, 0x29, 0xa5, 0xf5, 0x12, 0xe3, 0xc2,
+	0xdc, 0xcf, 0x41, 0xe8, 0x63, 0x58, 0x32, 0x38, 0x21, 0x51, 0xc8, 0xad, 0xa6, 0x2f, 0x67, 0x6e,
+	0x94, 0xd6, 0x25, 0x7f, 0x9f, 0x50, 0xc8, 0x43, 0x3c, 0x51, 0xcb, 0xc6, 0x74, 0xe0, 0xca, 0xff,
+	0x4e, 0xc3, 0x6a, 0x5c, 0x2a, 0x37, 0xb0, 0x07, 0x15, 0x73, 0x64, 0x7a, 0xa6, 0x36, 0x30, 0x7f,
+	0xae, 0x79, 0xa6, 0x35, 0xe2, 0xe2, 0x6f, 0x51, 0x96, 0xc9, 0x44, 0x6b, 0xed, 0x08, 0x45, 0x2b,
+	0xa5, 0xc6, 0x78, 0xa0, 0x6b, 0xc7, 0xed, 0xe3, 0x56, 0x8a, 0xef, 0xe4, 0xda, 0x6b, 0x01, 0x2a,
+	0x51, 0x5e, 0x68, 0x0f, 0x24, 0x1b, 0x63, 0xc7, 0xed, 0x0f, 0x35, 0xbb, 0xbf, 0x3b, 0xe9, 0x1b,
+	0x96, 0x5e, 0x15, 0xa8, 0x91, 0x0f, 0x4e, 0xae, 0xd1, 0xda, 0x0e, 0x61, 0xb1, 0xa5, 0xd9, 0x1b,
+	0x13, 0x22, 0x74, 0xe4, 0x39, 0x13, 0x75, 0xc9, 0x0e, 0xcf, 0xd5, 0x3a, 0x80, 0x66, 0x91, 0x90,
+	0x04, 0x99, 0xa9, 0x9f, 0xc9, 0x27, 0x92, 0x21, 0x77, 0xa8, 0x0d, 0xc6, 0x98, 0x5b, 0x52, 0x0e,
+	0x79, 0xc5, 0x55, 0x19, 0xe8, 0xd3, 0xf4, 0x27, 0xc2, 0x46, 0x1e, 0xb2, 0xbb, 0x96, 0x31, 0x91,
+	0x7f, 0x06, 0xcb, 0x3b, 0x63, 0x77, 0x7f, 0x67, 0x3c, 0x18, 0xbc, 0xa3, 0x60, 0xd5, 0x40, 0x9a,
+	0x4a, 0x78, 0x37, 0xfb, 0xce, 0x85, 0x95, 0xc7, 0xb6, 0xa1, 0x79, 0x78, 0x0b, 0x7b, 0x9a, 0xa1,
+	0x79, 0xda, 0xb7, 0x11, 0xa4, 0x55, 0x58, 0x8d, 0x0b, 0xe5, 0xc7, 0xfa, 0x33, 0x38, 0xfb, 0x63,
+	0xec, 0xe9, 0xfb, 0x2d, 0xd3, 0xf5, 0x2c, 0x67, 0x72, 0xa2, 0x75, 0xfd, 0x08, 0xca, 0x61, 0x25,
+	0xb8, 0xd5, 0xb3, 0x3a, 0x94, 0x42, 0x3a, 0xc8, 0x0f, 0xe0, 0x5c, 0x54, 0x10, 0x5f, 0xde, 0x6b,
+	0x50, 0x60, 0xab, 0xe3, 0xf2, 0x58, 0x2c, 0x85, 0x56, 0x4f, 0xf5, 0x61, 0xf2, 0x7f, 0x04, 0x80,
+	0xe9, 0x8a, 0xce, 0xa8, 0x20, 0x9c, 0x40, 0x05, 0x74, 0x07, 0x40, 0xdf, 0xc7, 0xfa, 0x81, 0x6d,
+	0x99, 0xc1, 0xf6, 0xf1, 0x7d, 0xe5, 0x4f, 0xab, 0x21, 0x14, 0x54, 0x83, 0xa2, 0x3b, 0xd2, 0x6c,
+	0x77, 0xdf, 0xf2, 0xaa, 0x19, 0xb6, 0x08, 0xfe, 0x38, 0xac, 0x77, 0xf6, 0x68, 0xbd, 0xd1, 0x67,
+	0x70, 0x66, 0x68, 0x8e, 0xfa, 0xee, 0x64, 0xa4, 0x63, 0xa3, 0xef, 0x99, 0xfa, 0x01, 0xf6, 0xaa,
+	0xb9, 0x90, 0xe8, 0x9e, 0x39, 0xc4, 0x3d, 0x3a, 0xad, 0x2e, 0x0f, 0xcd, 0x51, 0x97, 0x22, 0xb2,
+	0x09, 0xf9, 0x05, 0xe4, 0x19, 0x3f, 0x74, 0x11, 0xd2, 0xdc, 0x11, 0xfe, 0x8e, 0x67, 0x80, 0x76,
+	0x43, 0x4d, 0x9b, 0x06, 0xaa, 0x42, 0x61, 0x88, 0x5d, 0x57, 0x7b, 0xc6, 0xf6, 0x92, 0xa8, 0xfa,
+	0x43, 0xb4, 0x06, 0x60, 0xd9, 0xd8, 0xa1, 0x5b, 0xd7, 0xad, 0x66, 0xa8, 0xa6, 0x15, 0xca, 0x60,
+	0xdb, 0x9f, 0x56, 0x43, 0x18, 0xf2, 0x2e, 0x14, 0x7d, 0xce, 0xa1, 0x03, 0xda, 0xc5, 0x2f, 0xa8,
+	0xf0, 0x25, 0xff, 0x80, 0xee, 0xe2, 0x17, 0xe8, 0x02, 0x14, 0x06, 0xda, 0xd0, 0xb6, 0x1c, 0xb6,
+	0x96, 0xd9, 0x8d, 0xf4, 0x5d, 0x41, 0xf5, 0xa7, 0xd0, 0x7b, 0x50, 0xd4, 0x74, 0xcf, 0xa2, 0xd5,
+	0x08, 0x5b, 0xbb, 0x02, 0x1d, 0xb7, 0x0d, 0xf9, 0xf5, 0x2a, 0x88, 0x81, 0x74, 0xf4, 0x7d, 0xc8,
+	0xb8, 0xd8, 0x0f, 0x7a, 0x14, 0x55, 0x6d, 0xad, 0x8b, 0xc9, 0x91, 0x46, 0x10, 0x08, 0x9e, 0x66,
+	0x18, 0xdc, 0x6d, 0x71, 0x3c, 0xc5, 0x30, 0x08, 0x9e, 0x66, 0x18, 0xe8, 0x26, 0x64, 0x87, 0xd6,
+	0x21, 0xa6, 0x42, 0x4b, 0xeb, 0x67, 0x63, 0x88, 0x5b, 0xd6, 0x21, 0x6e, 0xa5, 0x54, 0x8a, 0x82,
+	0xee, 0x40, 0xde, 0xc1, 0x14, 0x39, 0x4b, 0x91, 0x57, 0x62, 0xc8, 0x2a, 0x05, 0xb6, 0x52, 0x2a,
+	0x47, 0x23, 0xbc, 0xb1, 0x61, 0xfa, 0x0e, 0x8c, 0xf3, 0x6e, 0x1a, 0x26, 0xd1, 0x96, 0xa2, 0x10,
+	0xde, 0x2e, 0x1e, 0x60, 0xdd, 0xab, 0xe6, 0x13, 0x79, 0x77, 0x29, 0x90, 0xf0, 0x66, 0x68, 0xe8,
+	0x1e, 0x88, 0x8e, 0xa9, 0xef, 0xf7, 0xa9, 0x80, 0x02, 0xa5, 0x39, 0x1f, 0xd7, 0xc7, 0xd4, 0xf7,
+	0xb9, 0x90, 0xa2, 0xc3, 0xbf, 0xd1, 0x6d, 0xc8, 0xb9, 0xde, 0x64, 0x80, 0xab, 0x45, 0x4a, 0x73,
+	0x2e, 0x2e, 0x87, 0xc0, 0x48, 0x5a, 0xa0, 0x48, 0xe8, 0x63, 0x28, 0x9a, 0x23, 0xdd, 0xc1, 0x9a,
+	0x8b, 0xab, 0x62, 0xa2, 0x90, 0x36, 0x07, 0x13, 0x21, 0x3e, 0x6a, 0xed, 0x0f, 0x02, 0x64, 0xba,
+	0xd8, 0x23, 0xe1, 0x6c, 0x6b, 0x0e, 0x09, 0x09, 0x02, 0xf0, 0xb0, 0xd1, 0xd7, 0x7c, 0xd7, 0xcd,
+	0x86, 0x33, 0xc3, 0xac, 0x33, 0x44, 0xc5, 0xf3, 0x33, 0x40, 0x7a, 0x9a, 0x01, 0x6e, 0xfb, 0x19,
+	0x80, 0x39, 0x6b, 0x95, 0xb2, 0xf8, 0xbc, 0xbb, 0xdd, 0x69, 0x0e, 0x30, 0xd9, 0xb5, 0x5d, 0x73,
+	0x68, 0x0f, 0x30, 0xcf, 0x05, 0xe4, 0xb0, 0xc5, 0x2f, 0xb1, 0x3e, 0xe6, 0x62, 0xb3, 0xc9, 0x62,
+	0xc1, 0xc7, 0x51, 0xbc, 0xda, 0x3f, 0x04, 0xc8, 0x28, 0x86, 0xf1, 0x76, 0x6a, 0xdf, 0x87, 0x65,
+	0xdb, 0xc1, 0x87, 0x61, 0xd2, 0x74, 0x32, 0xe9, 0x12, 0xc1, 0x9b, 0x12, 0xbe, 0x6b, 0xeb, 0xfe,
+	0x29, 0x40, 0x96, 0xc4, 0xf3, 0x77, 0x64, 0xde, 0x1a, 0x40, 0x88, 0x26, 0x93, 0x4c, 0x23, 0xea,
+	0x01, 0xfe, 0xe2, 0x06, 0x7e, 0x29, 0x40, 0x9e, 0xed, 0xc1, 0xb7, 0x33, 0x31, 0xaa, 0x69, 0x7a,
+	0x51, 0x4d, 0x33, 0xf3, 0x35, 0xfd, 0x4d, 0x06, 0xb2, 0x74, 0x37, 0xbe, 0x95, 0x9e, 0x1f, 0x40,
+	0x76, 0xcf, 0xb1, 0x86, 0x91, 0x84, 0xda, 0xc3, 0x2f, 0xbd, 0x8e, 0x65, 0xe0, 0x1d, 0xcb, 0x55,
+	0x29, 0x14, 0x5d, 0x86, 0xb4, 0x67, 0x71, 0xa5, 0x66, 0x71, 0xd2, 0x9e, 0x85, 0x76, 0xe1, 0xfc,
+	0x54, 0xba, 0x5f, 0xed, 0xd1, 0xd3, 0x97, 0xe7, 0xaa, 0xdb, 0x09, 0x27, 0xd7, 0x5a, 0xa0, 0x07,
+	0xad, 0xdb, 0x14, 0x82, 0xce, 0xca, 0xbb, 0xb3, 0xfa, 0x2c, 0x84, 0xa4, 0x1c, 0xdd, 0x1a, 0x79,
+	0xa4, 0x5e, 0xc9, 0xb1, 0x94, 0xc3, 0x87, 0xf1, 0xd5, 0xcb, 0xcf, 0x5f, 0xbd, 0x27, 0x50, 0x3d,
+	0x4a, 0x78, 0x42, 0xd9, 0x78, 0x2d, 0x5a, 0x36, 0xce, 0x70, 0x9e, 0x56, 0x8e, 0xb5, 0x57, 0x02,
+	0xe4, 0xd9, 0x41, 0x7b, 0x3a, 0x1c, 0xb3, 0xf8, 0x16, 0xf8, 0x7d, 0x16, 0x8a, 0xfe, 0xb1, 0x7f,
+	0x3a, 0x6c, 0xd8, 0x9b, 0x17, 0x5c, 0x77, 0x8f, 0xc8, 0x5a, 0xdf, 0x58, 0x80, 0x6d, 0x02, 0x68,
+	0x9e, 0xe7, 0x98, 0xbb, 0x63, 0x0f, 0xbb, 0xd5, 0x3c, 0x15, 0x7a, 0xfd, 0x28, 0xa1, 0x4a, 0x80,
+	0xc9, 0x64, 0x85, 0x48, 0xe3, 0xee, 0x28, 0x7c, 0x87, 0x91, 0xfa, 0x00, 0x96, 0x63, 0x9a, 0x26,
+	0xf0, 0x3b, 0x17, 0xe6, 0x27, 0x86, 0xc9, 0xff, 0x92, 0x86, 0x1c, 0xcd, 0xf4, 0xa7, 0x23, 0x46,
+	0x1a, 0x11, 0x0f, 0xb1, 0xb0, 0xf8, 0x20, 0xa9, 0x30, 0x59, 0xc4, 0x3d, 0xb9, 0xf9, 0xee, 0x79,
+	0xcb, 0x55, 0xfc, 0x52, 0x80, 0xa2, 0x5f, 0xfe, 0xbc, 0xdd, 0x42, 0xde, 0x8e, 0x7a, 0x7e, 0xb1,
+	0xd4, 0x3f, 0x3f, 0xdf, 0x04, 0xbf, 0xc4, 0x7f, 0x17, 0xe0, 0xcc, 0x0c, 0xdb, 0x58, 0xbe, 0x13,
+	0xe6, 0xe6, 0xbb, 0x5b, 0x50, 0x24, 0x49, 0xf6, 0xb8, 0xec, 0x58, 0xa0, 0x08, 0x2c, 0x97, 0xb2,
+	0x62, 0xf8, 0xd8, 0xac, 0xcf, 0x51, 0x14, 0x0f, 0xc9, 0x90, 0xf5, 0x26, 0x36, 0xab, 0xb0, 0x2b,
+	0xfc, 0xd7, 0xe3, 0x0b, 0x62, 0x75, 0x6f, 0x62, 0x63, 0x95, 0xc2, 0xa6, 0x1e, 0xc9, 0xd1, 0x1f,
+	0x05, 0x36, 0x90, 0x7f, 0x55, 0x86, 0x52, 0xc8, 0x36, 0xf4, 0x23, 0x28, 0x3d, 0x77, 0xad, 0x51,
+	0xdf, 0xda, 0x7d, 0x4e, 0xca, 0x6a, 0x66, 0xd6, 0xfb, 0xf1, 0x95, 0xa5, 0xdf, 0xdb, 0x14, 0xa5,
+	0x95, 0x52, 0x81, 0x50, 0xb0, 0x11, 0xfa, 0x0c, 0xe8, 0xa8, 0xaf, 0x39, 0x8e, 0xe6, 0xff, 0xb4,
+	0xd6, 0x12, 0xc9, 0x15, 0x82, 0xd1, 0x4a, 0xa9, 0x22, 0xc1, 0xa7, 0x03, 0xf4, 0x29, 0x88, 0xb6,
+	0x63, 0x0e, 0x4d, 0xcf, 0x0c, 0x7e, 0x2d, 0x66, 0x69, 0x77, 0x7c, 0x0c, 0x42, 0x1b, 0xa0, 0xa3,
+	0x0f, 0x21, 0xeb, 0xe1, 0x97, 0x5e, 0xe4, 0x27, 0x23, 0x4c, 0x46, 0x76, 0x0f, 0xf9, 0x6f, 0x20,
+	0x48, 0xe8, 0x13, 0xfe, 0x1b, 0x40, 0x29, 0x58, 0xc8, 0xbf, 0x37, 0x43, 0x41, 0x4e, 0x37, 0x4e,
+	0x45, 0x7f, 0x04, 0xc8, 0x37, 0xfa, 0x01, 0x39, 0x30, 0xc7, 0x23, 0x0f, 0x3b, 0x3c, 0xe7, 0x56,
+	0x67, 0xe8, 0xea, 0x0c, 0xde, 0x4a, 0xa9, 0x3e, 0x6a, 0xed, 0xcf, 0x02, 0xc0, 0x74, 0xc9, 0x90,
+	0x0c, 0xb9, 0x91, 0x65, 0x04, 0x3f, 0xe3, 0xec, 0x4e, 0x46, 0x6d, 0xf5, 0xc8, 0xee, 0x56, 0x19,
+	0x68, 0xe1, 0x72, 0x2a, 0x1c, 0x5e, 0x99, 0x85, 0xc2, 0x2b, 0x3b, 0x2f, 0xbc, 0x6a, 0x7f, 0x12,
+	0x40, 0x0c, 0x5c, 0x76, 0x84, 0xf6, 0x9b, 0xca, 0x69, 0xd5, 0xfe, 0x6f, 0x02, 0x88, 0x41, 0xd0,
+	0x04, 0x5b, 0x45, 0x38, 0xc9, 0x56, 0x49, 0x87, 0xb6, 0xca, 0xc2, 0xa5, 0x78, 0xd8, 0xa6, 0xec,
+	0x42, 0x36, 0xe5, 0xe6, 0xda, 0xf4, 0x47, 0x01, 0xb2, 0x34, 0x1e, 0xaf, 0x46, 0x9d, 0xb1, 0x14,
+	0xc9, 0x14, 0xa7, 0xd1, 0x1b, 0xaf, 0x04, 0x56, 0x6b, 0x51, 0xed, 0xaf, 0x47, 0xb5, 0x3f, 0xc3,
+	0x42, 0x89, 0x43, 0x4f, 0xab, 0x05, 0x5f, 0x09, 0x50, 0xe0, 0x7b, 0xfc, 0xff, 0x23, 0x9a, 0x48,
+	0xa2, 0xdb, 0x20, 0x89, 0x6e, 0x13, 0x0a, 0xfc, 0x14, 0x4a, 0xc8, 0xe8, 0xb7, 0xa0, 0x80, 0xd9,
+	0x09, 0x17, 0xa9, 0x5c, 0x42, 0x27, 0x9f, 0xea, 0x23, 0xc8, 0x4f, 0xa0, 0xc0, 0x0f, 0x04, 0x74,
+	0x19, 0xb2, 0x23, 0x72, 0xca, 0x0a, 0xa1, 0xeb, 0x67, 0xff, 0xb0, 0xa0, 0x90, 0x85, 0x18, 0xff,
+	0x4e, 0x80, 0xa2, 0x1f, 0x1b, 0xe8, 0x7b, 0xa1, 0xfb, 0xba, 0xe5, 0x48, 0xe0, 0xf3, 0x1b, 0xbb,
+	0xc4, 0x22, 0x64, 0xe1, 0xe4, 0x7a, 0x07, 0x4a, 0xe6, 0xc8, 0xed, 0xd3, 0xff, 0x77, 0xd3, 0x88,
+	0x2e, 0xfe, 0x54, 0x9e, 0x68, 0x8e, 0xdc, 0x1d, 0x07, 0x1f, 0xb6, 0x0d, 0xf9, 0x39, 0x48, 0xe1,
+	0x18, 0x26, 0xc5, 0xd2, 0x49, 0x2b, 0x24, 0xa2, 0xdc, 0x98, 0x5e, 0x22, 0x1f, 0xab, 0x1c, 0x47,
+	0x51, 0x3c, 0xf9, 0x55, 0x1a, 0xca, 0x61, 0x61, 0xf3, 0x17, 0x45, 0x89, 0x94, 0x8d, 0xec, 0x6a,
+	0xfb, 0xca, 0xcc, 0xc6, 0x3b, 0xb6, 0x66, 0x3c, 0x17, 0xbe, 0x73, 0x39, 0x62, 0x5d, 0xb3, 0x8b,
+	0xae, 0x6b, 0x6e, 0xde, 0xba, 0xd6, 0x7a, 0x27, 0x29, 0x3c, 0x3f, 0x8c, 0x16, 0x85, 0x2b, 0x33,
+	0x96, 0x11, 0x16, 0xa1, 0x7a, 0x54, 0xee, 0x01, 0x4c, 0xc5, 0x2d, 0x5c, 0xd5, 0xad, 0x42, 0xde,
+	0xda, 0xdb, 0x73, 0x31, 0x8b, 0xdd, 0x9c, 0xca, 0x47, 0xf2, 0x2f, 0x05, 0x28, 0xfa, 0x7d, 0x00,
+	0xb2, 0x5e, 0xfa, 0xc0, 0xd2, 0x0f, 0x28, 0xbf, 0x9c, 0xca, 0x06, 0xa4, 0x62, 0x21, 0x50, 0xee,
+	0x02, 0x76, 0x43, 0xe8, 0x93, 0xac, 0x35, 0x34, 0x4f, 0x63, 0x0b, 0x4f, 0x91, 0x6a, 0xf7, 0x41,
+	0x0c, 0xa6, 0x16, 0x29, 0xb7, 0xe5, 0x3a, 0xe4, 0x59, 0x7b, 0x03, 0x55, 0x82, 0xc8, 0x28, 0xd3,
+	0x40, 0xb8, 0x09, 0xc5, 0x21, 0x17, 0x17, 0x69, 0x73, 0x05, 0xed, 0x8b, 0x00, 0x2c, 0xdf, 0x85,
+	0x02, 0x6f, 0x19, 0xd1, 0x2b, 0x79, 0xf6, 0x19, 0x6d, 0x25, 0xb0, 0x16, 0x8a, 0x0f, 0x93, 0xdb,
+	0x50, 0x0a, 0xb5, 0x08, 0xd0, 0x25, 0x00, 0xdd, 0x1a, 0x0c, 0xb0, 0x1e, 0x74, 0xe8, 0x44, 0x35,
+	0x34, 0x83, 0x6a, 0x50, 0xf4, 0x9b, 0x08, 0xdc, 0x84, 0x60, 0x2c, 0x77, 0x00, 0xa6, 0xad, 0x03,
+	0x74, 0x05, 0xc0, 0xc5, 0xce, 0x21, 0x76, 0x82, 0xfb, 0x72, 0x76, 0x27, 0x2e, 0xb2, 0xd9, 0x2e,
+	0x7e, 0x11, 0xbb, 0x52, 0x4f, 0xc7, 0xae, 0xd4, 0xe5, 0x5f, 0x40, 0x29, 0xf4, 0x2b, 0xf5, 0x4d,
+	0x79, 0x1c, 0x5d, 0x87, 0x65, 0x07, 0x0f, 0x34, 0x52, 0x64, 0xf4, 0x39, 0x42, 0x86, 0x22, 0x54,
+	0xfc, 0xe9, 0x6d, 0x16, 0x1a, 0x3a, 0xc0, 0x94, 0x73, 0xf8, 0x82, 0x5f, 0x98, 0xbd, 0xe0, 0xbf,
+	0x00, 0xa2, 0x81, 0x07, 0xa4, 0x76, 0xc1, 0x8e, 0x6f, 0x49, 0x30, 0x71, 0xdc, 0xf5, 0xff, 0xaf,
+	0x05, 0x28, 0xfa, 0xfd, 0x4a, 0x74, 0x2d, 0x92, 0xa5, 0xce, 0x44, 0x9a, 0x99, 0xa1, 0x44, 0x75,
+	0x13, 0xc4, 0xe0, 0x2d, 0x03, 0x8f, 0x88, 0x88, 0x73, 0xa7, 0xd0, 0xd9, 0x16, 0x59, 0xe6, 0x24,
+	0x2d, 0xb2, 0x5b, 0x5f, 0x09, 0x20, 0x06, 0xe9, 0x11, 0x15, 0x21, 0xdb, 0x79, 0xfc, 0xe8, 0x91,
+	0x94, 0x42, 0x25, 0x28, 0x6c, 0x6c, 0x6f, 0x3f, 0x6a, 0x2a, 0x1d, 0x49, 0x20, 0x83, 0x76, 0xa7,
+	0xd7, 0xdc, 0x6c, 0xaa, 0x52, 0x9a, 0xe0, 0x3c, 0xda, 0xee, 0x6c, 0x4a, 0x19, 0x04, 0x90, 0x6f,
+	0x6c, 0x3f, 0xde, 0x78, 0xd4, 0x94, 0xb2, 0xe4, 0xbb, 0xdb, 0x53, 0xdb, 0x9d, 0x4d, 0x29, 0x87,
+	0x44, 0xc8, 0x6d, 0x3c, 0xed, 0x35, 0xbb, 0x52, 0x9e, 0x20, 0x37, 0x94, 0x5e, 0x53, 0x2a, 0xa0,
+	0x65, 0xf6, 0x57, 0xd3, 0xdf, 0xde, 0xf8, 0xbc, 0x59, 0xef, 0x49, 0x45, 0x54, 0x61, 0x05, 0x78,
+	0x5f, 0x51, 0x55, 0xe5, 0xa9, 0x24, 0x12, 0xd4, 0x5e, 0xf3, 0xa7, 0x3d, 0x09, 0xd0, 0x12, 0x88,
+	0x6a, 0xbb, 0xde, 0xea, 0xd3, 0x61, 0x89, 0x50, 0x72, 0xe9, 0xfd, 0x7a, 0xa7, 0x27, 0x95, 0x51,
+	0x19, 0x8a, 0x44, 0x03, 0x3a, 0x5a, 0x22, 0x7c, 0x98, 0x16, 0x74, 0x5c, 0xb9, 0x75, 0x00, 0xe5,
+	0xf0, 0x4a, 0xa2, 0x15, 0x38, 0xd3, 0xd8, 0xae, 0x3f, 0xde, 0x6a, 0x76, 0x7a, 0xdd, 0x7e, 0xbd,
+	0xa5, 0x74, 0x36, 0x9b, 0x0d, 0x29, 0x15, 0x9d, 0x7e, 0xa2, 0xf4, 0xea, 0xad, 0x66, 0x43, 0x12,
+	0xd0, 0x79, 0x38, 0x3b, 0x9d, 0x7e, 0xdc, 0xf1, 0x01, 0x69, 0x74, 0x0e, 0xa4, 0xad, 0x66, 0x4f,
+	0x69, 0x28, 0x3d, 0x25, 0xe0, 0x92, 0x59, 0xff, 0x3a, 0x0b, 0xf9, 0xa7, 0xf4, 0xbd, 0x0a, 0x7a,
+	0x08, 0x95, 0xe8, 0x8b, 0x0f, 0xc4, 0xfe, 0x94, 0x12, 0x9f, 0x8f, 0xd4, 0xde, 0x4f, 0x84, 0xf1,
+	0xee, 0x64, 0x0a, 0xfd, 0x04, 0xa4, 0xf8, 0x83, 0x0d, 0x74, 0x81, 0xb9, 0x32, 0xf9, 0xfd, 0x47,
+	0xed, 0xe2, 0x11, 0xd0, 0x80, 0xe5, 0x43, 0xa8, 0x44, 0x9b, 0xa1, 0x5c, 0xbf, 0xc4, 0xb6, 0x2c,
+	0xd7, 0xef, 0x88, 0xee, 0x29, 0x65, 0x16, 0x7d, 0xaf, 0xe1, 0x1b, 0x9b, 0xf4, 0x58, 0xc4, 0x37,
+	0x36, 0xf1, 0x81, 0x07, 0x63, 0x16, 0x7d, 0x2b, 0xc1, 0x99, 0x25, 0x3e, 0xd4, 0xe0, 0xcc, 0x92,
+	0x1f, 0x57, 0xc8, 0x29, 0xb4, 0x05, 0x95, 0x68, 0x43, 0x9f, 0x33, 0x4b, 0x7c, 0x22, 0xc1, 0x99,
+	0x25, 0xbf, 0x00, 0x90, 0x53, 0x77, 0x05, 0xf4, 0x43, 0x28, 0xfa, 0xad, 0x71, 0xc4, 0x7a, 0x4c,
+	0xb1, 0x5e, 0x7c, 0x6d, 0x25, 0x36, 0x1b, 0x68, 0xd2, 0x84, 0x72, 0xb8, 0xf5, 0x8b, 0xd8, 0x7f,
+	0x69, 0x42, 0xdb, 0xb9, 0xf6, 0x5e, 0x02, 0xc4, 0x67, 0xb3, 0xfe, 0x05, 0x39, 0xe9, 0xc7, 0x2e,
+	0x39, 0x5d, 0x1e, 0x42, 0x25, 0xfa, 0x4c, 0x89, 0xdb, 0x96, 0xf8, 0x38, 0x8a, 0xdb, 0x76, 0xc4,
+	0xbb, 0xa6, 0xd4, 0x86, 0xf4, 0xfa, 0xcd, 0x25, 0xe1, 0xaf, 0x6f, 0x2e, 0x09, 0x5f, 0xbf, 0xb9,
+	0x24, 0xfc, 0xf6, 0x5f, 0x97, 0x52, 0xbb, 0x79, 0xfa, 0xe4, 0xea, 0xa3, 0xff, 0x06, 0x00, 0x00,
+	0xff, 0xff, 0x12, 0xcc, 0x2a, 0xa2, 0x86, 0x25, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -3811,11 +3918,12 @@ const _ = grpc.SupportPackageIsVersion4
 type YorkieClient interface {
 	ActivateClient(ctx context.Context, in *ActivateClientRequest, opts ...grpc.CallOption) (*ActivateClientResponse, error)
 	DeactivateClient(ctx context.Context, in *DeactivateClientRequest, opts ...grpc.CallOption) (*DeactivateClientResponse, error)
+	UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error)
 	AttachDocument(ctx context.Context, in *AttachDocumentRequest, opts ...grpc.CallOption) (*AttachDocumentResponse, error)
 	DetachDocument(ctx context.Context, in *DetachDocumentRequest, opts ...grpc.CallOption) (*DetachDocumentResponse, error)
 	WatchDocuments(ctx context.Context, in *WatchDocumentsRequest, opts ...grpc.CallOption) (Yorkie_WatchDocumentsClient, error)
 	PushPull(ctx context.Context, in *PushPullRequest, opts ...grpc.CallOption) (*PushPullResponse, error)
-	UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error)
+	FetchHistory(ctx context.Context, in *FetchHistoryRequest, opts ...grpc.CallOption) (*FetchHistoryResponse, error)
 }
 
 type yorkieClient struct {
@@ -3844,6 +3952,15 @@ func (c *yorkieClient) DeactivateClient(ctx context.Context, in *DeactivateClien
 	return out, nil
 }
 
+func (c *yorkieClient) UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) {
+	out := new(UpdateMetadataResponse)
+	err := c.cc.Invoke(ctx, "/api.Yorkie/UpdateMetadata", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 func (c *yorkieClient) AttachDocument(ctx context.Context, in *AttachDocumentRequest, opts ...grpc.CallOption) (*AttachDocumentResponse, error) {
 	out := new(AttachDocumentResponse)
 	err := c.cc.Invoke(ctx, "/api.Yorkie/AttachDocument", in, out, opts...)
@@ -3903,9 +4020,9 @@ func (c *yorkieClient) PushPull(ctx context.Context, in *PushPullRequest, opts .
 	return out, nil
 }
 
-func (c *yorkieClient) UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) {
-	out := new(UpdateMetadataResponse)
-	err := c.cc.Invoke(ctx, "/api.Yorkie/UpdateMetadata", in, out, opts...)
+func (c *yorkieClient) FetchHistory(ctx context.Context, in *FetchHistoryRequest, opts ...grpc.CallOption) (*FetchHistoryResponse, error) {
+	out := new(FetchHistoryResponse)
+	err := c.cc.Invoke(ctx, "/api.Yorkie/FetchHistory", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3916,11 +4033,12 @@ func (c *yorkieClient) UpdateMetadata(ctx context.Context, in *UpdateMetadataReq
 type YorkieServer interface {
 	ActivateClient(context.Context, *ActivateClientRequest) (*ActivateClientResponse, error)
 	DeactivateClient(context.Context, *DeactivateClientRequest) (*DeactivateClientResponse, error)
+	UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error)
 	AttachDocument(context.Context, *AttachDocumentRequest) (*AttachDocumentResponse, error)
 	DetachDocument(context.Context, *DetachDocumentRequest) (*DetachDocumentResponse, error)
 	WatchDocuments(*WatchDocumentsRequest, Yorkie_WatchDocumentsServer) error
 	PushPull(context.Context, *PushPullRequest) (*PushPullResponse, error)
-	UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error)
+	FetchHistory(context.Context, *FetchHistoryRequest) (*FetchHistoryResponse, error)
 }
 
 // UnimplementedYorkieServer can be embedded to have forward compatible implementations.
@@ -3933,6 +4051,9 @@ func (*UnimplementedYorkieServer) ActivateClient(ctx context.Context, req *Activ
 func (*UnimplementedYorkieServer) DeactivateClient(ctx context.Context, req *DeactivateClientRequest) (*DeactivateClientResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method DeactivateClient not implemented")
 }
+func (*UnimplementedYorkieServer) UpdateMetadata(ctx context.Context, req *UpdateMetadataRequest) (*UpdateMetadataResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UpdateMetadata not implemented")
+}
 func (*UnimplementedYorkieServer) AttachDocument(ctx context.Context, req *AttachDocumentRequest) (*AttachDocumentResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method AttachDocument not implemented")
 }
@@ -3945,8 +4066,8 @@ func (*UnimplementedYorkieServer) WatchDocuments(req *WatchDocumentsRequest, srv
 func (*UnimplementedYorkieServer) PushPull(ctx context.Context, req *PushPullRequest) (*PushPullResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method PushPull not implemented")
 }
-func (*UnimplementedYorkieServer) UpdateMetadata(ctx context.Context, req *UpdateMetadataRequest) (*UpdateMetadataResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method UpdateMetadata not implemented")
+func (*UnimplementedYorkieServer) FetchHistory(ctx context.Context, req *FetchHistoryRequest) (*FetchHistoryResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method FetchHistory not implemented")
 }
 
 func RegisterYorkieServer(s *grpc.Server, srv YorkieServer) {
@@ -3989,6 +4110,24 @@ func _Yorkie_DeactivateClient_Handler(srv interface{}, ctx context.Context, dec
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Yorkie_UpdateMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(UpdateMetadataRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(YorkieServer).UpdateMetadata(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/api.Yorkie/UpdateMetadata",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(YorkieServer).UpdateMetadata(ctx, req.(*UpdateMetadataRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 func _Yorkie_AttachDocument_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(AttachDocumentRequest)
 	if err := dec(in); err != nil {
@@ -4064,20 +4203,20 @@ func _Yorkie_PushPull_Handler(srv interface{}, ctx context.Context, dec func(int
 	return interceptor(ctx, in, info, handler)
 }
 
-func _Yorkie_UpdateMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(UpdateMetadataRequest)
+func _Yorkie_FetchHistory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(FetchHistoryRequest)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
 	if interceptor == nil {
-		return srv.(YorkieServer).UpdateMetadata(ctx, in)
+		return srv.(YorkieServer).FetchHistory(ctx, in)
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/api.Yorkie/UpdateMetadata",
+		FullMethod: "/api.Yorkie/FetchHistory",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(YorkieServer).UpdateMetadata(ctx, req.(*UpdateMetadataRequest))
+		return srv.(YorkieServer).FetchHistory(ctx, req.(*FetchHistoryRequest))
 	}
 	return interceptor(ctx, in, info, handler)
 }
@@ -4094,6 +4233,10 @@ var _Yorkie_serviceDesc = grpc.ServiceDesc{
 			MethodName: "DeactivateClient",
 			Handler:    _Yorkie_DeactivateClient_Handler,
 		},
+		{
+			MethodName: "UpdateMetadata",
+			Handler:    _Yorkie_UpdateMetadata_Handler,
+		},
 		{
 			MethodName: "AttachDocument",
 			Handler:    _Yorkie_AttachDocument_Handler,
@@ -4107,8 +4250,8 @@ var _Yorkie_serviceDesc = grpc.ServiceDesc{
 			Handler:    _Yorkie_PushPull_Handler,
 		},
 		{
-			MethodName: "UpdateMetadata",
-			Handler:    _Yorkie_UpdateMetadata_Handler,
+			MethodName: "FetchHistory",
+			Handler:    _Yorkie_FetchHistory_Handler,
 		},
 	},
 	Streams: []grpc.StreamDesc{
@@ -4949,6 +5092,93 @@ func (m *UpdateMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error)
 	return len(dAtA) - i, nil
 }
 
+func (m *FetchHistoryRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *FetchHistoryRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *FetchHistoryRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.DocumentKey != nil {
+		{
+			size, err := m.DocumentKey.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintYorkie(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.ClientId) > 0 {
+		i -= len(m.ClientId)
+		copy(dAtA[i:], m.ClientId)
+		i = encodeVarintYorkie(dAtA, i, uint64(len(m.ClientId)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *FetchHistoryResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *FetchHistoryResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *FetchHistoryResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Changes) > 0 {
+		for iNdEx := len(m.Changes) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Changes[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintYorkie(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
 func (m *ChangePack) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -7885,6 +8115,44 @@ func (m *UpdateMetadataResponse) Size() (n int) {
 	return n
 }
 
+func (m *FetchHistoryRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ClientId)
+	if l > 0 {
+		n += 1 + l + sovYorkie(uint64(l))
+	}
+	if m.DocumentKey != nil {
+		l = m.DocumentKey.Size()
+		n += 1 + l + sovYorkie(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *FetchHistoryResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Changes) > 0 {
+		for _, e := range m.Changes {
+			l = e.Size()
+			n += 1 + l + sovYorkie(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
 func (m *ChangePack) Size() (n int) {
 	if m == nil {
 		return 0
@@ -10921,6 +11189,218 @@ func (m *UpdateMetadataResponse) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *FetchHistoryRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowYorkie
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: FetchHistoryRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: FetchHistoryRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowYorkie
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ClientId = append(m.ClientId[:0], dAtA[iNdEx:postIndex]...)
+			if m.ClientId == nil {
+				m.ClientId = []byte{}
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field DocumentKey", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowYorkie
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.DocumentKey == nil {
+				m.DocumentKey = &DocumentKey{}
+			}
+			if err := m.DocumentKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipYorkie(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *FetchHistoryResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowYorkie
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: FetchHistoryResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: FetchHistoryResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Changes", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowYorkie
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Changes = append(m.Changes, &Change{})
+			if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipYorkie(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthYorkie
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *ChangePack) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
@@ -11869,7 +12349,7 @@ func (m *Operation_Set) Unmarshal(dAtA []byte) error {
 			iNdEx = postIndex
 		case 2:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field CombinedKey", wireType)
 			}
 			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
@@ -15808,7 +16288,7 @@ func (m *RHTNode) Unmarshal(dAtA []byte) error {
 		switch fieldNum {
 		case 1:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field CombinedKey", wireType)
 			}
 			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
@@ -16250,7 +16730,7 @@ func (m *RichTextNodeAttr) Unmarshal(dAtA []byte) error {
 		switch fieldNum {
 		case 1:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field CombinedKey", wireType)
 			}
 			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
diff --git a/api/yorkie.proto b/api/yorkie.proto
index 52852691..dfa847e0 100644
--- a/api/yorkie.proto
+++ b/api/yorkie.proto
@@ -21,11 +21,13 @@ package api;
 service Yorkie {
     rpc ActivateClient (ActivateClientRequest) returns (ActivateClientResponse) {}
     rpc DeactivateClient (DeactivateClientRequest) returns (DeactivateClientResponse) {}
+    rpc UpdateMetadata (UpdateMetadataRequest) returns (UpdateMetadataResponse) {}
+
     rpc AttachDocument (AttachDocumentRequest) returns (AttachDocumentResponse) {}
     rpc DetachDocument (DetachDocumentRequest) returns (DetachDocumentResponse) {}
     rpc WatchDocuments (WatchDocumentsRequest) returns (stream WatchDocumentsResponse) {}
     rpc PushPull (PushPullRequest) returns (PushPullResponse) {}
-    rpc UpdateMetadata (UpdateMetadataRequest) returns (UpdateMetadataResponse) {}
+    rpc FetchHistory (FetchHistoryRequest) returns (FetchHistoryResponse) {}
 }
 
 service Cluster {
@@ -117,6 +119,15 @@ message UpdateMetadataRequest {
 
 message UpdateMetadataResponse {}
 
+message FetchHistoryRequest {
+    bytes client_id = 1;
+    DocumentKey document_key = 2;
+}
+
+message FetchHistoryResponse {
+    repeated Change changes = 1;
+}
+
 /////////////////////////////////////////
 // Messages for ChangePack             //
 /////////////////////////////////////////
diff --git a/client/client.go b/client/client.go
index a2d0a14e..bd9549c9 100644
--- a/client/client.go
+++ b/client/client.go
@@ -89,7 +89,7 @@ const (
 // WatchResponse is a structure representing response of Watch.
 type WatchResponse struct {
 	Type          WatchResponseType
-	Keys          []*key.Key
+	Keys          []key.Key
 	PeersMapByDoc map[string]map[string]types.Metadata
 	Err           error
 }
@@ -212,7 +212,7 @@ func (c *Client) Activate(ctx context.Context) error {
 	}
 
 	c.status = activated
-	c.id = clientID
+	c.id = &clientID
 
 	return nil
 }
@@ -242,7 +242,7 @@ func (c *Client) Attach(ctx context.Context, doc *document.Document) error {
 		return ErrClientNotActivated
 	}
 
-	doc.SetActor(c.id)
+	doc.SetActor(*c.id)
 
 	pbChangePack, err := converter.ToChangePack(doc.CreateChangePack())
 	if err != nil {
@@ -275,7 +275,7 @@ func (c *Client) Attach(ctx context.Context, doc *document.Document) error {
 	}
 
 	doc.SetStatus(document.Attached)
-	c.attachments[doc.Key().BSONKey()] = &Attachment{
+	c.attachments[doc.Key().CombinedKey()] = &Attachment{
 		doc:   doc,
 		peers: make(map[string]types.MetadataInfo),
 	}
@@ -294,7 +294,7 @@ func (c *Client) Detach(ctx context.Context, doc *document.Document) error {
 		return ErrClientNotActivated
 	}
 
-	if _, ok := c.attachments[doc.Key().BSONKey()]; !ok {
+	if _, ok := c.attachments[doc.Key().CombinedKey()]; !ok {
 		return ErrDocumentNotAttached
 	}
 
@@ -321,7 +321,7 @@ func (c *Client) Detach(ctx context.Context, doc *document.Document) error {
 	}
 
 	doc.SetStatus(document.Detached)
-	delete(c.attachments, doc.Key().BSONKey())
+	delete(c.attachments, doc.Key().CombinedKey())
 
 	return nil
 }
@@ -329,7 +329,7 @@ func (c *Client) Detach(ctx context.Context, doc *document.Document) error {
 // Sync pushes local changes of the attached documents to the Agent and
 // receives changes of the remote replica from the agent then apply them to
 // local documents.
-func (c *Client) Sync(ctx context.Context, keys ...*key.Key) error {
+func (c *Client) Sync(ctx context.Context, keys ...key.Key) error {
 	if len(keys) == 0 {
 		for _, attachment := range c.attachments {
 			keys = append(keys, attachment.doc.Key())
@@ -354,7 +354,7 @@ func (c *Client) Watch(
 	ctx context.Context,
 	docs ...*document.Document,
 ) (<-chan WatchResponse, error) {
-	var keys []*key.Key
+	var keys []key.Key
 	for _, doc := range docs {
 		keys = append(keys, doc.Key())
 	}
@@ -362,7 +362,7 @@ func (c *Client) Watch(
 	rch := make(chan WatchResponse)
 	stream, err := c.client.WatchDocuments(ctx, &api.WatchDocumentsRequest{
 		Client: converter.ToClient(types.Client{
-			ID:           c.id,
+			ID:           *c.id,
 			MetadataInfo: c.metadataInfo,
 		}),
 		DocumentKeys: converter.ToDocumentKeys(keys),
@@ -406,7 +406,7 @@ func (c *Client) Watch(
 						return nil, err
 					}
 
-					attachment := c.attachments[k.BSONKey()]
+					attachment := c.attachments[k.CombinedKey()]
 					if eventType == types.DocumentsWatchedEvent ||
 						eventType == types.MetadataChangedEvent {
 						if info, ok := attachment.peers[cli.ID.String()]; ok {
@@ -468,7 +468,7 @@ func (c *Client) UpdateMetadata(ctx context.Context, k, v string) error {
 		return nil
 	}
 
-	var keys []*key.Key
+	var keys []key.Key
 	for _, attachment := range c.attachments {
 		keys = append(keys, attachment.doc.Key())
 	}
@@ -479,7 +479,7 @@ func (c *Client) UpdateMetadata(ctx context.Context, k, v string) error {
 	// following.
 	if _, err := c.client.UpdateMetadata(ctx, &api.UpdateMetadataRequest{
 		Client: converter.ToClient(types.Client{
-			ID:           c.id,
+			ID:           *c.id,
 			MetadataInfo: c.metadataInfo,
 		}),
 		DocumentKeys: converter.ToDocumentKeys(keys),
@@ -490,6 +490,40 @@ func (c *Client) UpdateMetadata(ctx context.Context, k, v string) error {
 	return nil
 }
 
+// FetchHistory returns the history of the given document.
+func (c *Client) FetchHistory(ctx context.Context, key key.Key) ([]*types.ChangeSummary, error) {
+	resp, err := c.client.FetchHistory(ctx, &api.FetchHistoryRequest{
+		ClientId:    c.id.Bytes(),
+		DocumentKey: converter.ToDocumentKey(key),
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	changes, err := converter.FromChanges(resp.Changes)
+	if err != nil {
+		return nil, err
+	}
+
+	doc := document.NewInternalDocument(key)
+
+	var summaries []*types.ChangeSummary
+	for _, c := range changes {
+		if err := doc.ApplyChanges(c); err != nil {
+			return nil, err
+		}
+
+		// TODO(hackerwins): doc.Marshal is expensive function. We need to optimize it.
+		summaries = append(summaries, &types.ChangeSummary{
+			ID:       c.ID(),
+			Message:  c.Message(),
+			Snapshot: doc.Marshal(),
+		})
+	}
+
+	return summaries, nil
+}
+
 // ID returns the ID of this client.
 func (c *Client) ID() *time.ActorID {
 	return c.id
@@ -528,12 +562,12 @@ func (c *Client) IsActive() bool {
 	return c.status == activated
 }
 
-func (c *Client) sync(ctx context.Context, key *key.Key) error {
+func (c *Client) sync(ctx context.Context, key key.Key) error {
 	if c.status != activated {
 		return ErrClientNotActivated
 	}
 
-	attachment, ok := c.attachments[key.BSONKey()]
+	attachment, ok := c.attachments[key.CombinedKey()]
 	if !ok {
 		return ErrDocumentNotAttached
 	}
diff --git a/pkg/document/change/change.go b/pkg/document/change/change.go
index e8e2af50..af4d0b30 100644
--- a/pkg/document/change/change.go
+++ b/pkg/document/change/change.go
@@ -18,24 +18,24 @@ package change
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 	"github.com/yorkie-team/yorkie/pkg/document/time"
 )
 
 // Change represents a unit of modification in the document.
 type Change struct {
 	// id is the unique identifier of the change.
-	id *ID
+	id ID
 
 	// message is used to save a description of the change.
 	message string
 
 	// operations represent a series of user edits.
-	operations []operation.Operation
+	operations []operations.Operation
 }
 
 // New creates a new instance of Change.
-func New(id *ID, message string, operations []operation.Operation) *Change {
+func New(id ID, message string, operations []operations.Operation) *Change {
 	return &Change{
 		id:         id,
 		message:    message,
@@ -54,7 +54,7 @@ func (c *Change) Execute(root *json.Root) error {
 }
 
 // ID returns the ID of this change.
-func (c *Change) ID() *ID {
+func (c *Change) ID() ID {
 	return c.id
 }
 
@@ -64,7 +64,7 @@ func (c *Change) Message() string {
 }
 
 // Operations returns the operations of this change.
-func (c *Change) Operations() []operation.Operation {
+func (c *Change) Operations() []operations.Operation {
 	return c.operations
 }
 
@@ -80,11 +80,11 @@ func (c *Change) ClientSeq() uint32 {
 
 // SetServerSeq sets the given serverSeq.
 func (c *Change) SetServerSeq(serverSeq uint64) {
-	c.id = c.id.SetServerSeq(&serverSeq)
+	c.id = c.id.SetServerSeq(serverSeq)
 }
 
 // SetActor sets the given actorID.
-func (c *Change) SetActor(actor *time.ActorID) {
+func (c *Change) SetActor(actor time.ActorID) {
 	c.id = c.id.SetActor(actor)
 	for _, op := range c.operations {
 		op.SetActor(actor)
diff --git a/pkg/document/change/checkpoint.go b/pkg/document/change/checkpoint.go
index a678ce41..dd5ebf10 100644
--- a/pkg/document/change/checkpoint.go
+++ b/pkg/document/change/checkpoint.go
@@ -38,15 +38,15 @@ type Checkpoint struct {
 }
 
 // NewCheckpoint creates a new instance of Checkpoint.
-func NewCheckpoint(serverSeq uint64, clientSeq uint32) *Checkpoint {
-	return &Checkpoint{
+func NewCheckpoint(serverSeq uint64, clientSeq uint32) Checkpoint {
+	return Checkpoint{
 		ServerSeq: serverSeq,
 		ClientSeq: clientSeq,
 	}
 }
 
 // NextServerSeq creates a new instance with next server sequence.
-func (cp *Checkpoint) NextServerSeq(serverSeq uint64) *Checkpoint {
+func (cp Checkpoint) NextServerSeq(serverSeq uint64) Checkpoint {
 	if cp.ServerSeq == serverSeq {
 		return cp
 	}
@@ -55,12 +55,12 @@ func (cp *Checkpoint) NextServerSeq(serverSeq uint64) *Checkpoint {
 }
 
 // NextClientSeq creates a new instance with next client sequence.
-func (cp *Checkpoint) NextClientSeq() *Checkpoint {
+func (cp Checkpoint) NextClientSeq() Checkpoint {
 	return cp.IncreaseClientSeq(1)
 }
 
 // IncreaseClientSeq creates a new instance with increased client sequence.
-func (cp *Checkpoint) IncreaseClientSeq(inc uint32) *Checkpoint {
+func (cp Checkpoint) IncreaseClientSeq(inc uint32) Checkpoint {
 	if inc == 0 {
 		return cp
 	}
@@ -69,7 +69,7 @@ func (cp *Checkpoint) IncreaseClientSeq(inc uint32) *Checkpoint {
 
 // SyncClientSeq updates the given clientSeq if it is greater than the internal
 // value.
-func (cp *Checkpoint) SyncClientSeq(clientSeq uint32) *Checkpoint {
+func (cp Checkpoint) SyncClientSeq(clientSeq uint32) Checkpoint {
 	if cp.ClientSeq < clientSeq {
 		return NewCheckpoint(cp.ServerSeq, clientSeq)
 	}
@@ -79,7 +79,7 @@ func (cp *Checkpoint) SyncClientSeq(clientSeq uint32) *Checkpoint {
 
 // Forward updates the given checkpoint with those values when it is greater
 // than the values of internal properties.
-func (cp *Checkpoint) Forward(other *Checkpoint) *Checkpoint {
+func (cp Checkpoint) Forward(other Checkpoint) Checkpoint {
 	if cp.Equals(other) {
 		return cp
 	}
@@ -98,12 +98,12 @@ func (cp *Checkpoint) Forward(other *Checkpoint) *Checkpoint {
 }
 
 // Equals returns whether the given checkpoint is equal to this checkpoint or not.
-func (cp *Checkpoint) Equals(other *Checkpoint) bool {
+func (cp *Checkpoint) Equals(other Checkpoint) bool {
 	return cp.ServerSeq == other.ServerSeq &&
 		cp.ClientSeq == other.ClientSeq
 }
 
 // String returns the string of information about this checkpoint.
-func (cp *Checkpoint) String() string {
+func (cp Checkpoint) String() string {
 	return fmt.Sprintf("serverSeq=%d, clientSeq=%d", cp.ServerSeq, cp.ClientSeq)
 }
diff --git a/pkg/document/change/context.go b/pkg/document/change/context.go
index 1701c4f1..af73cfb5 100644
--- a/pkg/document/change/context.go
+++ b/pkg/document/change/context.go
@@ -18,7 +18,7 @@ package change
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 	"github.com/yorkie-team/yorkie/pkg/document/time"
 )
 
@@ -26,15 +26,15 @@ import (
 // Each time we add an operation, a new time ticket is issued.
 // Finally, returns a Change after the modification has been completed.
 type Context struct {
-	id         *ID
+	id         ID
 	message    string
-	operations []operation.Operation
+	operations []operations.Operation
 	delimiter  uint32
 	root       *json.Root
 }
 
 // NewContext creates a new instance of Context.
-func NewContext(id *ID, message string, root *json.Root) *Context {
+func NewContext(id ID, message string, root *json.Root) *Context {
 	return &Context{
 		id:      id,
 		message: message,
@@ -42,8 +42,8 @@ func NewContext(id *ID, message string, root *json.Root) *Context {
 	}
 }
 
-// ID returns ID.
-func (c *Context) ID() *ID {
+// ID returns ID for new change.
+func (c *Context) ID() ID {
 	return c.id
 }
 
@@ -63,8 +63,8 @@ func (c *Context) IssueTimeTicket() *time.Ticket {
 	return c.id.NewTimeTicket(c.delimiter)
 }
 
-// Push pushes a new operation into context queue.
-func (c *Context) Push(op operation.Operation) {
+// Push pushes a new operations into context queue.
+func (c *Context) Push(op operations.Operation) {
 	c.operations = append(c.operations, op)
 }
 
diff --git a/pkg/document/change/id.go b/pkg/document/change/id.go
index fe752ffb..82c047bd 100644
--- a/pkg/document/change/id.go
+++ b/pkg/document/change/id.go
@@ -23,7 +23,7 @@ import (
 var (
 	// InitialID represents the initial state ID. Usually this is used to
 	// represent a state where nothing has been edited.
-	InitialID = NewID(0, 0, time.InitialActorID)
+	InitialID = NewID(0, 0, &time.InitialActorID)
 )
 
 // ID is for identifying the Change. It is immutable.
@@ -48,19 +48,24 @@ func NewID(
 	clientSeq uint32,
 	lamport uint64,
 	actorID *time.ActorID,
-) *ID {
-	id := &ID{
+	serverSeq ...uint64,
+) ID {
+	id := ID{
 		clientSeq: clientSeq,
 		lamport:   lamport,
 		actorID:   actorID,
 	}
 
+	if len(serverSeq) > 0 {
+		id.serverSeq = &serverSeq[0]
+	}
+
 	return id
 }
 
 // Next creates a next ID of this ID.
-func (id *ID) Next() *ID {
-	return &ID{
+func (id ID) Next() ID {
+	return ID{
 		clientSeq: id.clientSeq + 1,
 		lamport:   id.lamport + 1,
 		actorID:   id.actorID,
@@ -68,7 +73,7 @@ func (id *ID) Next() *ID {
 }
 
 // NewTimeTicket creates a ticket of the given delimiter.
-func (id *ID) NewTimeTicket(delimiter uint32) *time.Ticket {
+func (id ID) NewTimeTicket(delimiter uint32) *time.Ticket {
 	return time.NewTicket(
 		id.lamport,
 		delimiter,
@@ -78,7 +83,7 @@ func (id *ID) NewTimeTicket(delimiter uint32) *time.Ticket {
 
 // SyncLamport syncs lamport timestamp with the given ID.
 //  - receiving: https://en.wikipedia.org/wiki/Lamport_timestamps#Algorithm
-func (id *ID) SyncLamport(otherLamport uint64) *ID {
+func (id ID) SyncLamport(otherLamport uint64) ID {
 	if id.lamport < otherLamport {
 		return NewID(id.clientSeq, otherLamport, id.actorID)
 	}
@@ -87,33 +92,31 @@ func (id *ID) SyncLamport(otherLamport uint64) *ID {
 }
 
 // SetActor sets actorID.
-func (id *ID) SetActor(actor *time.ActorID) *ID {
-	return NewID(id.clientSeq, id.lamport, actor)
+func (id ID) SetActor(actor time.ActorID) ID {
+	return NewID(id.clientSeq, id.lamport, &actor)
 }
 
 // SetServerSeq sets server sequence of this ID.
-func (id *ID) SetServerSeq(serverSeq *uint64) *ID {
-	newID := NewID(id.clientSeq, id.lamport, id.actorID)
-	newID.serverSeq = serverSeq
-	return newID
+func (id ID) SetServerSeq(serverSeq uint64) ID {
+	return NewID(id.clientSeq, id.lamport, id.actorID, serverSeq)
 }
 
 // ClientSeq returns the client sequence of this ID.
-func (id *ID) ClientSeq() uint32 {
+func (id ID) ClientSeq() uint32 {
 	return id.clientSeq
 }
 
 // ServerSeq returns the server sequence of this ID.
-func (id *ID) ServerSeq() *uint64 {
+func (id ID) ServerSeq() *uint64 {
 	return id.serverSeq
 }
 
 // Lamport returns the lamport clock of this ID.
-func (id *ID) Lamport() uint64 {
+func (id ID) Lamport() uint64 {
 	return id.lamport
 }
 
 // ActorID returns the actorID of this ID.
-func (id *ID) ActorID() *time.ActorID {
+func (id ID) ActorID() *time.ActorID {
 	return id.actorID
 }
diff --git a/pkg/document/change/pack.go b/pkg/document/change/pack.go
index 453eca77..27a81649 100644
--- a/pkg/document/change/pack.go
+++ b/pkg/document/change/pack.go
@@ -24,10 +24,10 @@ import (
 // Pack is a unit for delivering changes in a document to the remote.
 type Pack struct {
 	// DocumentKey is key of the document.
-	DocumentKey *key.Key
+	DocumentKey key.Key
 
 	// Checkpoint is used to determine the client received changes.
-	Checkpoint *Checkpoint
+	Checkpoint Checkpoint
 
 	// Change represents a unit of modification in the document.
 	Changes []*Change
@@ -42,8 +42,8 @@ type Pack struct {
 
 // NewPack creates a new instance of Pack.
 func NewPack(
-	key *key.Key,
-	cp *Checkpoint,
+	key key.Key,
+	cp Checkpoint,
 	changes []*Change,
 	snapshot []byte,
 ) *Pack {
diff --git a/pkg/document/document.go b/pkg/document/document.go
index 84b25121..265fd4bf 100644
--- a/pkg/document/document.go
+++ b/pkg/document/document.go
@@ -44,8 +44,9 @@ type Document struct {
 
 // New creates a new instance of Document.
 func New(collection, document string) *Document {
+	k := key.Key{Collection: collection, Document: document}
 	return &Document{
-		doc: NewInternalDocument(collection, document),
+		doc: NewInternalDocument(k),
 	}
 }
 
@@ -58,7 +59,7 @@ func (d *Document) Update(
 
 	ctx := change.NewContext(
 		d.doc.changeID.Next(),
-		messageFromMsgAndArgs(msgAndArgs),
+		messageFromMsgAndArgs(msgAndArgs...),
 		d.clone,
 	)
 
@@ -98,7 +99,7 @@ func (d *Document) ApplyChangePack(pack *change.Pack) error {
 			}
 		}
 
-		if err := d.doc.applyChanges(pack.Changes); err != nil {
+		if err := d.doc.ApplyChanges(pack.Changes...); err != nil {
 			return err
 		}
 	}
@@ -127,12 +128,12 @@ func (d *Document) InternalDocument() *InternalDocument {
 }
 
 // Key returns the key of this document.
-func (d *Document) Key() *key.Key {
+func (d *Document) Key() key.Key {
 	return d.doc.key
 }
 
 // Checkpoint returns the checkpoint of this document.
-func (d *Document) Checkpoint() *change.Checkpoint {
+func (d *Document) Checkpoint() change.Checkpoint {
 	return d.doc.checkpoint
 }
 
@@ -153,7 +154,7 @@ func (d *Document) CreateChangePack() *change.Pack {
 
 // SetActor sets actor into this document. This is also applied in the local
 // changes the document has.
-func (d *Document) SetActor(actor *time.ActorID) {
+func (d *Document) SetActor(actor time.ActorID) {
 	d.doc.SetActor(actor)
 }
 
diff --git a/pkg/document/internal_document.go b/pkg/document/internal_document.go
index c041678b..aba192f9 100644
--- a/pkg/document/internal_document.go
+++ b/pkg/document/internal_document.go
@@ -38,20 +38,20 @@ const (
 
 // InternalDocument represents a document in MongoDB and contains logical clocks.
 type InternalDocument struct {
-	key          *key.Key
+	key          key.Key
 	status       statusType
 	root         *json.Root
-	checkpoint   *change.Checkpoint
-	changeID     *change.ID
+	checkpoint   change.Checkpoint
+	changeID     change.ID
 	localChanges []*change.Change
 }
 
 // NewInternalDocument creates a new instance of InternalDocument.
-func NewInternalDocument(collection, document string) *InternalDocument {
+func NewInternalDocument(k key.Key) *InternalDocument {
 	root := json.NewObject(json.NewRHTPriorityQueueMap(), time.InitialTicket)
 
 	return &InternalDocument{
-		key:        &key.Key{Collection: collection, Document: document},
+		key:        k,
 		status:     Detached,
 		root:       json.NewRoot(root),
 		checkpoint: change.InitialCheckpoint,
@@ -61,8 +61,7 @@ func NewInternalDocument(collection, document string) *InternalDocument {
 
 // NewInternalDocumentFromSnapshot creates a new instance of InternalDocument with the snapshot.
 func NewInternalDocumentFromSnapshot(
-	collection string,
-	document string,
+	k key.Key,
 	serverSeq uint64,
 	snapshot []byte,
 ) (*InternalDocument, error) {
@@ -72,7 +71,7 @@ func NewInternalDocumentFromSnapshot(
 	}
 
 	return &InternalDocument{
-		key:        &key.Key{Collection: collection, Document: document},
+		key:        k,
 		status:     Detached,
 		root:       json.NewRoot(obj),
 		checkpoint: change.InitialCheckpoint.NextServerSeq(serverSeq),
@@ -81,12 +80,12 @@ func NewInternalDocumentFromSnapshot(
 }
 
 // Key returns the key of this document.
-func (d *InternalDocument) Key() *key.Key {
+func (d *InternalDocument) Key() key.Key {
 	return d.key
 }
 
 // Checkpoint returns the checkpoint of this document.
-func (d *InternalDocument) Checkpoint() *change.Checkpoint {
+func (d *InternalDocument) Checkpoint() change.Checkpoint {
 	return d.checkpoint
 }
 
@@ -103,7 +102,7 @@ func (d *InternalDocument) ApplyChangePack(pack *change.Pack) error {
 			return err
 		}
 	} else {
-		if err := d.applyChanges(pack.Changes); err != nil {
+		if err := d.ApplyChanges(pack.Changes...); err != nil {
 			return err
 		}
 	}
@@ -152,7 +151,7 @@ func (d *InternalDocument) CreateChangePack() *change.Pack {
 
 // SetActor sets actor into this document. This is also applied in the local
 // changes the document has.
-func (d *InternalDocument) SetActor(actor *time.ActorID) {
+func (d *InternalDocument) SetActor(actor time.ActorID) {
 	for _, c := range d.localChanges {
 		c.SetActor(actor)
 	}
@@ -204,8 +203,8 @@ func (d *InternalDocument) applySnapshot(snapshot []byte, serverSeq uint64) erro
 	return nil
 }
 
-// applyChanges applies remote changes to both the clone and the document.
-func (d *InternalDocument) applyChanges(changes []*change.Change) error {
+// ApplyChanges applies remote changes to the document.
+func (d *InternalDocument) ApplyChanges(changes ...*change.Change) error {
 	for _, c := range changes {
 		if err := c.Execute(d.root); err != nil {
 			return err
diff --git a/pkg/document/key/key.go b/pkg/document/key/key.go
index 803bbf7b..9e6f8221 100644
--- a/pkg/document/key/key.go
+++ b/pkg/document/key/key.go
@@ -23,13 +23,13 @@ import (
 )
 
 const (
-	// BSONSplitter is used to separate collection and document in a string.
-	BSONSplitter = "$"
-	tokenLen     = 2
+	// Splitter is used to separate collection and document in a string.
+	Splitter = "$"
+	tokenLen = 2
 )
 
-// ErrInvalidBSONKey is returned when the given bsonKey is invalid.
-var ErrInvalidBSONKey = errors.New("invalid bson key")
+// ErrInvalidCombinedKey is returned when the given combined key is invalid.
+var ErrInvalidCombinedKey = errors.New("invalid combined key")
 
 // Key represents the key of the Document.
 type Key struct {
@@ -37,17 +37,17 @@ type Key struct {
 	Document   string
 }
 
-// FromBSONKey creates an instance of Key from the received bsonKey.
-func FromBSONKey(bsonKey string) (*Key, error) {
-	splits := strings.Split(bsonKey, BSONSplitter)
+// FromCombinedKey creates an instance of Key from the given combined key.
+func FromCombinedKey(k string) (Key, error) {
+	splits := strings.Split(k, Splitter)
 	if len(splits) != tokenLen {
-		return nil, fmt.Errorf("%s: %w", bsonKey, ErrInvalidBSONKey)
+		return Key{}, fmt.Errorf("%s: %w", k, ErrInvalidCombinedKey)
 	}
 
-	return &Key{Collection: splits[0], Document: splits[1]}, nil
+	return Key{Collection: splits[0], Document: splits[1]}, nil
 }
 
-// BSONKey returns the string of this key.
-func (k *Key) BSONKey() string {
-	return k.Collection + BSONSplitter + k.Document
+// CombinedKey returns the string of this key.
+func (k Key) CombinedKey() string {
+	return k.Collection + Splitter + k.Document
 }
diff --git a/pkg/document/operation/add.go b/pkg/document/operations/add.go
similarity index 95%
rename from pkg/document/operation/add.go
rename to pkg/document/operations/add.go
index c4909169..6fc65af1 100644
--- a/pkg/document/operation/add.go
+++ b/pkg/document/operations/add.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -29,7 +29,7 @@ type Add struct {
 	// prevCreatedAt is the creation time of the previous element.
 	prevCreatedAt *time.Ticket
 
-	// value is an element added by the insert operation.
+	// value is an element added by the insert operations.
 	value json.Element
 
 	// executedAt is the time the operation was executed.
@@ -83,7 +83,7 @@ func (o *Add) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (o *Add) SetActor(actorID *time.ActorID) {
+func (o *Add) SetActor(actorID time.ActorID) {
 	o.executedAt = o.executedAt.SetActorID(actorID)
 }
 
diff --git a/pkg/document/operation/edit.go b/pkg/document/operations/edit.go
similarity index 98%
rename from pkg/document/operation/edit.go
rename to pkg/document/operations/edit.go
index 16d33313..28c2f9d9 100644
--- a/pkg/document/operation/edit.go
+++ b/pkg/document/operations/edit.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -95,7 +95,7 @@ func (e *Edit) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (e *Edit) SetActor(actorID *time.ActorID) {
+func (e *Edit) SetActor(actorID time.ActorID) {
 	e.executedAt = e.executedAt.SetActorID(actorID)
 }
 
diff --git a/pkg/document/operation/increase.go b/pkg/document/operations/increase.go
similarity index 96%
rename from pkg/document/operation/increase.go
rename to pkg/document/operations/increase.go
index 10644fae..0e47a92d 100644
--- a/pkg/document/operation/increase.go
+++ b/pkg/document/operations/increase.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -72,6 +72,6 @@ func (o *Increase) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (o *Increase) SetActor(actorID *time.ActorID) {
+func (o *Increase) SetActor(actorID time.ActorID) {
 	o.executedAt = o.executedAt.SetActorID(actorID)
 }
diff --git a/pkg/document/operation/move.go b/pkg/document/operations/move.go
similarity index 97%
rename from pkg/document/operation/move.go
rename to pkg/document/operations/move.go
index b29ffbdc..3676a677 100644
--- a/pkg/document/operation/move.go
+++ b/pkg/document/operations/move.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -81,7 +81,7 @@ func (o *Move) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (o *Move) SetActor(actorID *time.ActorID) {
+func (o *Move) SetActor(actorID time.ActorID) {
 	o.executedAt = o.executedAt.SetActorID(actorID)
 }
 
diff --git a/pkg/document/operation/operation.go b/pkg/document/operations/operation.go
similarity index 96%
rename from pkg/document/operation/operation.go
rename to pkg/document/operations/operation.go
index 14cbb421..b1416987 100644
--- a/pkg/document/operation/operation.go
+++ b/pkg/document/operations/operation.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"errors"
@@ -38,7 +38,7 @@ type Operation interface {
 	ExecutedAt() *time.Ticket
 
 	// SetActor sets the given actor to this operation.
-	SetActor(id *time.ActorID)
+	SetActor(id time.ActorID)
 
 	// ParentCreatedAt returns the creation time of the target element to
 	// execute the operation.
diff --git a/pkg/document/operation/remove.go b/pkg/document/operations/remove.go
similarity index 97%
rename from pkg/document/operation/remove.go
rename to pkg/document/operations/remove.go
index 3bb57534..f794b1a5 100644
--- a/pkg/document/operation/remove.go
+++ b/pkg/document/operations/remove.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -75,7 +75,7 @@ func (o *Remove) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (o *Remove) SetActor(actorID *time.ActorID) {
+func (o *Remove) SetActor(actorID time.ActorID) {
 	o.executedAt = o.executedAt.SetActorID(actorID)
 }
 
diff --git a/pkg/document/operation/rich_edit.go b/pkg/document/operations/rich_edit.go
similarity index 98%
rename from pkg/document/operation/rich_edit.go
rename to pkg/document/operations/rich_edit.go
index 735f65d1..9b27702f 100644
--- a/pkg/document/operation/rich_edit.go
+++ b/pkg/document/operations/rich_edit.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -102,7 +102,7 @@ func (e *RichEdit) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (e *RichEdit) SetActor(actorID *time.ActorID) {
+func (e *RichEdit) SetActor(actorID time.ActorID) {
 	e.executedAt = e.executedAt.SetActorID(actorID)
 }
 
diff --git a/pkg/document/operation/select.go b/pkg/document/operations/select.go
similarity index 97%
rename from pkg/document/operation/select.go
rename to pkg/document/operations/select.go
index 5abb6fd6..52a7520c 100644
--- a/pkg/document/operation/select.go
+++ b/pkg/document/operations/select.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -83,7 +83,7 @@ func (s *Select) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (s *Select) SetActor(actorID *time.ActorID) {
+func (s *Select) SetActor(actorID time.ActorID) {
 	s.executedAt = s.executedAt.SetActorID(actorID)
 }
 
diff --git a/pkg/document/operation/set.go b/pkg/document/operations/set.go
similarity index 97%
rename from pkg/document/operation/set.go
rename to pkg/document/operations/set.go
index 12e1fc17..3dfa1ce6 100644
--- a/pkg/document/operation/set.go
+++ b/pkg/document/operations/set.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -81,7 +81,7 @@ func (o *Set) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (o *Set) SetActor(actorID *time.ActorID) {
+func (o *Set) SetActor(actorID time.ActorID) {
 	o.executedAt = o.executedAt.SetActorID(actorID)
 }
 
diff --git a/pkg/document/operation/style.go b/pkg/document/operations/style.go
similarity index 97%
rename from pkg/document/operation/style.go
rename to pkg/document/operations/style.go
index ac08a55c..c6b83878 100644
--- a/pkg/document/operation/style.go
+++ b/pkg/document/operations/style.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package operation
+package operations
 
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/json"
@@ -84,7 +84,7 @@ func (e *Style) ExecutedAt() *time.Ticket {
 }
 
 // SetActor sets the given actor to this operation.
-func (e *Style) SetActor(actorID *time.ActorID) {
+func (e *Style) SetActor(actorID time.ActorID) {
 	e.executedAt = e.executedAt.SetActorID(actorID)
 }
 
diff --git a/pkg/document/proxy/array_proxy.go b/pkg/document/proxy/array_proxy.go
index 5144011f..46293f63 100644
--- a/pkg/document/proxy/array_proxy.go
+++ b/pkg/document/proxy/array_proxy.go
@@ -21,7 +21,7 @@ import (
 
 	"github.com/yorkie-team/yorkie/pkg/document/change"
 	"github.com/yorkie-team/yorkie/pkg/document/json"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 	"github.com/yorkie-team/yorkie/pkg/document/time"
 )
 
@@ -157,7 +157,7 @@ func (p *ArrayProxy) Delete(idx int) json.Element {
 
 	ticket := p.context.IssueTimeTicket()
 	deleted := p.Array.Delete(idx, ticket)
-	p.context.Push(operation.NewRemove(
+	p.context.Push(operations.NewRemove(
 		p.CreatedAt(),
 		deleted.CreatedAt(),
 		ticket,
@@ -185,7 +185,7 @@ func (p *ArrayProxy) insertAfterInternal(
 	proxy := creator(ticket)
 	value := toOriginal(proxy)
 
-	p.context.Push(operation.NewAdd(
+	p.context.Push(operations.NewAdd(
 		p.Array.CreatedAt(),
 		prevCreatedAt,
 		value.DeepCopy(),
@@ -203,7 +203,7 @@ func (p *ArrayProxy) moveBeforeInternal(nextCreatedAt, createdAt *time.Ticket) {
 
 	prevCreatedAt := p.FindPrevCreatedAt(nextCreatedAt)
 
-	p.context.Push(operation.NewMove(
+	p.context.Push(operations.NewMove(
 		p.Array.CreatedAt(),
 		prevCreatedAt,
 		createdAt,
diff --git a/pkg/document/proxy/counter_proxy.go b/pkg/document/proxy/counter_proxy.go
index c576ef28..57ef3c17 100644
--- a/pkg/document/proxy/counter_proxy.go
+++ b/pkg/document/proxy/counter_proxy.go
@@ -21,7 +21,7 @@ import (
 
 	"github.com/yorkie-team/yorkie/pkg/document/change"
 	"github.com/yorkie-team/yorkie/pkg/document/json"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 )
 
 // CounterProxy is a proxy representing counter.
@@ -41,7 +41,7 @@ func NewCounterProxy(ctx *change.Context, counter *json.Counter) *CounterProxy {
 	}
 }
 
-// Increase adds an increase operation.
+// Increase adds an increase operations.
 // Only numeric types are allowed as operand values, excluding
 // uint64 and uintptr.
 func (p *CounterProxy) Increase(v interface{}) *CounterProxy {
@@ -76,7 +76,7 @@ func (p *CounterProxy) Increase(v interface{}) *CounterProxy {
 		panic("unsupported type")
 	}
 
-	p.context.Push(operation.NewIncrease(
+	p.context.Push(operations.NewIncrease(
 		p.CreatedAt(),
 		primitive,
 		ticket,
diff --git a/pkg/document/proxy/object_proxy.go b/pkg/document/proxy/object_proxy.go
index 79de7322..d90ae9c3 100644
--- a/pkg/document/proxy/object_proxy.go
+++ b/pkg/document/proxy/object_proxy.go
@@ -21,7 +21,7 @@ import (
 
 	"github.com/yorkie-team/yorkie/pkg/document/change"
 	"github.com/yorkie-team/yorkie/pkg/document/json"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 	"github.com/yorkie-team/yorkie/pkg/document/time"
 )
 
@@ -173,7 +173,7 @@ func (p *ObjectProxy) Delete(k string) json.Element {
 
 	ticket := p.context.IssueTimeTicket()
 	deleted := p.Object.Delete(k, ticket)
-	p.context.Push(operation.NewRemove(
+	p.context.Push(operations.NewRemove(
 		p.CreatedAt(),
 		deleted.CreatedAt(),
 		ticket,
@@ -275,7 +275,7 @@ func (p *ObjectProxy) setInternal(
 	proxy := creator(ticket)
 	value := toOriginal(proxy)
 
-	p.context.Push(operation.NewSet(
+	p.context.Push(operations.NewSet(
 		p.CreatedAt(),
 		k,
 		value.DeepCopy(),
diff --git a/pkg/document/proxy/rich_text_proxy.go b/pkg/document/proxy/rich_text_proxy.go
index 452e76e3..ee0b0251 100644
--- a/pkg/document/proxy/rich_text_proxy.go
+++ b/pkg/document/proxy/rich_text_proxy.go
@@ -19,7 +19,7 @@ package proxy
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/change"
 	"github.com/yorkie-team/yorkie/pkg/document/json"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 )
 
 // RichTextProxy is a proxy representing RichText.
@@ -53,7 +53,7 @@ func (p *RichTextProxy) Edit(from, to int, content string, attributes map[string
 		ticket,
 	)
 
-	p.context.Push(operation.NewRichEdit(
+	p.context.Push(operations.NewRichEdit(
 		p.CreatedAt(),
 		fromPos,
 		toPos,
@@ -84,7 +84,7 @@ func (p *RichTextProxy) SetStyle(from, to int, attributes map[string]string) *Ri
 		ticket,
 	)
 
-	p.context.Push(operation.NewStyle(
+	p.context.Push(operations.NewStyle(
 		p.CreatedAt(),
 		fromPos,
 		toPos,
diff --git a/pkg/document/proxy/text_proxy.go b/pkg/document/proxy/text_proxy.go
index 54c2e86c..17cbaf3d 100644
--- a/pkg/document/proxy/text_proxy.go
+++ b/pkg/document/proxy/text_proxy.go
@@ -19,7 +19,7 @@ package proxy
 import (
 	"github.com/yorkie-team/yorkie/pkg/document/change"
 	"github.com/yorkie-team/yorkie/pkg/document/json"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 )
 
 // TextProxy is a proxy representing Text.
@@ -52,7 +52,7 @@ func (p *TextProxy) Edit(from, to int, content string) *TextProxy {
 		ticket,
 	)
 
-	p.context.Push(operation.NewEdit(
+	p.context.Push(operations.NewEdit(
 		p.CreatedAt(),
 		fromPos,
 		toPos,
@@ -80,7 +80,7 @@ func (p *TextProxy) Select(from, to int) *TextProxy {
 		ticket,
 	)
 
-	p.context.Push(operation.NewSelect(
+	p.context.Push(operations.NewSelect(
 		p.CreatedAt(),
 		fromPos,
 		toPos,
diff --git a/pkg/document/time/actor_id.go b/pkg/document/time/actor_id.go
index aa63fc83..3a62444e 100644
--- a/pkg/document/time/actor_id.go
+++ b/pkg/document/time/actor_id.go
@@ -28,10 +28,10 @@ const actorIDSize = 12
 
 var (
 	// InitialActorID represents the initial value of ActorID.
-	InitialActorID = &ActorID{}
+	InitialActorID = ActorID{}
 
 	// MaxActorID represents the maximum value of ActorID.
-	MaxActorID = &ActorID{
+	MaxActorID = ActorID{
 		math.MaxUint8,
 		math.MaxUint8,
 		math.MaxUint8,
@@ -48,6 +48,9 @@ var (
 
 	// ErrInvalidHexString is returned when the given string is not valid hex.
 	ErrInvalidHexString = errors.New("invalid hex string")
+
+	// ErrInvalidActorID is returned when the given ID is not valid.
+	ErrInvalidActorID = errors.New("invalid actor id")
 )
 
 // ActorID is bytes represented by the hexadecimal string.
@@ -55,67 +58,57 @@ var (
 type ActorID [actorIDSize]byte
 
 // ActorIDFromHex returns the bytes represented by the hexadecimal string str.
-func ActorIDFromHex(str string) (*ActorID, error) {
+func ActorIDFromHex(str string) (ActorID, error) {
+	actorID := ActorID{}
+
 	if str == "" {
-		return nil, nil
+		return actorID, fmt.Errorf("%s: %w", str, ErrInvalidHexString)
 	}
 
-	actorID := ActorID{}
 	decoded, err := hex.DecodeString(str)
 	if err != nil {
-		return nil, fmt.Errorf("%s: %w", str, ErrInvalidHexString)
+		return actorID, fmt.Errorf("%s: %w", str, ErrInvalidHexString)
 	}
 
 	if len(decoded) != actorIDSize {
-		return nil, fmt.Errorf("decoded length %d: %w", len(decoded), ErrInvalidHexString)
+		return actorID, fmt.Errorf("decoded length %d: %w", len(decoded), ErrInvalidHexString)
 	}
 
 	copy(actorID[:], decoded[:actorIDSize])
-	return &actorID, nil
+	return actorID, nil
 }
 
 // ActorIDFromBytes returns the bytes represented by the bytes of decoded hexadecimal string itself.
-func ActorIDFromBytes(bytes []byte) (*ActorID, error) {
+func ActorIDFromBytes(bytes []byte) (ActorID, error) {
+	actorID := ActorID{}
+
 	if len(bytes) == 0 {
-		return nil, nil
+		return actorID, fmt.Errorf("bytes length %d: %w", len(bytes), ErrInvalidActorID)
 	}
 
 	if len(bytes) != actorIDSize {
-		return nil, fmt.Errorf("bytes length %d: %w", len(bytes), ErrInvalidHexString)
+		return actorID, fmt.Errorf("bytes length %d: %w", len(bytes), ErrInvalidActorID)
 	}
 
-	actorID := ActorID{}
 	copy(actorID[:], bytes)
-	return &actorID, nil
+	return actorID, nil
 }
 
 // String returns the hexadecimal encoding of ActorID.
 // If the receiver is nil, it would return empty string.
-func (id *ActorID) String() string {
-	if id == nil {
-		return ""
-	}
-
+func (id ActorID) String() string {
 	return hex.EncodeToString(id[:])
 }
 
 // Bytes returns the bytes of ActorID itself.
 // If the receiver is nil, it would return empty array of byte.
-func (id *ActorID) Bytes() []byte {
-	if id == nil {
-		return nil
-	}
-
+func (id ActorID) Bytes() []byte {
 	return id[:]
 }
 
 // Compare returns an integer comparing two ActorID lexicographically.
 // The result will be 0 if id==other, -1 if id < other, and +1 if id > other.
 // If the receiver or argument is nil, it would panic at runtime.
-func (id *ActorID) Compare(other *ActorID) int {
-	if id == nil || other == nil {
-		panic("actorID cannot be null")
-	}
-
+func (id ActorID) Compare(other ActorID) int {
 	return bytes.Compare(id[:], other[:])
 }
diff --git a/pkg/document/time/ticket.go b/pkg/document/time/ticket.go
index 193dbe85..22567aac 100644
--- a/pkg/document/time/ticket.go
+++ b/pkg/document/time/ticket.go
@@ -35,14 +35,14 @@ var (
 	InitialTicket = NewTicket(
 		0,
 		0,
-		InitialActorID,
+		&InitialActorID,
 	)
 
 	// MaxTicket is the maximum value of Ticket.
 	MaxTicket = NewTicket(
 		MaxLamport,
 		MaxDelimiter,
-		MaxActorID,
+		&MaxActorID,
 	)
 )
 
@@ -135,7 +135,7 @@ func (t *Ticket) Compare(other *Ticket) int {
 		return -1
 	}
 
-	compare := t.actorID.Compare(other.ActorID())
+	compare := t.actorID.Compare(*other.ActorID())
 	if compare != 0 {
 		return compare
 	}
@@ -150,10 +150,10 @@ func (t *Ticket) Compare(other *Ticket) int {
 }
 
 // SetActorID creates a new instance of Ticket with the given actorID.
-func (t *Ticket) SetActorID(actorID *ActorID) *Ticket {
+func (t *Ticket) SetActorID(actorID ActorID) *Ticket {
 	return &Ticket{
 		lamport:   t.lamport,
 		delimiter: t.delimiter,
-		actorID:   actorID,
+		actorID:   &actorID,
 	}
 }
diff --git a/pkg/types/auth_webhook.go b/pkg/types/auth_webhook.go
index f7e0d46f..06a096c4 100644
--- a/pkg/types/auth_webhook.go
+++ b/pkg/types/auth_webhook.go
@@ -54,6 +54,7 @@ const (
 	DetachDocument   Method = "DetachDocument"
 	PushPull         Method = "PushPull"
 	WatchDocuments   Method = "WatchDocuments"
+	FetchHistory     Method = "FetchHistory"
 )
 
 // IsAuthMethod returns whether the given method can be used for authorization.
@@ -75,6 +76,7 @@ func AuthMethods() []Method {
 		DetachDocument,
 		PushPull,
 		WatchDocuments,
+		FetchHistory,
 	}
 }
 
diff --git a/pkg/types/change_summary.go b/pkg/types/change_summary.go
new file mode 100644
index 00000000..ac6e21c5
--- /dev/null
+++ b/pkg/types/change_summary.go
@@ -0,0 +1,15 @@
+package types
+
+import "github.com/yorkie-team/yorkie/pkg/document/change"
+
+// ChangeSummary represents a summary of change.
+type ChangeSummary struct {
+	// ID is the unique identifier of the change.
+	ID change.ID
+
+	// Message is the message of the change.
+	Message string
+
+	// Snapshot is the snapshot of the document.
+	Snapshot string
+}
diff --git a/pkg/types/client.go b/pkg/types/client.go
index 2390a5bb..e5911864 100644
--- a/pkg/types/client.go
+++ b/pkg/types/client.go
@@ -8,7 +8,7 @@ import (
 
 // Client represents the Client that communicates with the Agent.
 type Client struct {
-	ID           *time.ActorID
+	ID           time.ActorID
 	MetadataInfo MetadataInfo
 }
 
diff --git a/yorkie/auth/webhook.go b/yorkie/auth/webhook.go
index f46acfb0..d53f67cb 100644
--- a/yorkie/auth/webhook.go
+++ b/yorkie/auth/webhook.go
@@ -54,7 +54,7 @@ func AccessAttributes(pack *change.Pack) []types.AccessAttribute {
 	// NOTE(hackerwins): In the future, methods such as bulk PushPull can be
 	// added, so we declare it as an array.
 	return []types.AccessAttribute{{
-		Key:  pack.DocumentKey.BSONKey(),
+		Key:  pack.DocumentKey.CombinedKey(),
 		Verb: verb,
 	}}
 }
diff --git a/yorkie/backend/db/change_info.go b/yorkie/backend/db/change_info.go
index 20241aee..86024985 100644
--- a/yorkie/backend/db/change_info.go
+++ b/yorkie/backend/db/change_info.go
@@ -22,12 +22,12 @@ import (
 	"github.com/yorkie-team/yorkie/api"
 	"github.com/yorkie-team/yorkie/api/converter"
 	"github.com/yorkie-team/yorkie/pkg/document/change"
-	"github.com/yorkie-team/yorkie/pkg/document/operation"
+	"github.com/yorkie-team/yorkie/pkg/document/operations"
 	"github.com/yorkie-team/yorkie/pkg/document/time"
 )
 
-// ErrEncodeOperationFailed is returned when encoding operation failed.
-var ErrEncodeOperationFailed = errors.New("encode operation failed")
+// ErrEncodeOperationFailed is returned when encoding operations failed.
+var ErrEncodeOperationFailed = errors.New("encode operations failed")
 
 // ChangeInfo is a structure representing information of a change.
 type ChangeInfo struct {
@@ -42,7 +42,7 @@ type ChangeInfo struct {
 }
 
 // EncodeOperations encodes the given operations into bytes array.
-func EncodeOperations(operations []operation.Operation) ([][]byte, error) {
+func EncodeOperations(operations []operations.Operation) ([][]byte, error) {
 	var encodedOps [][]byte
 
 	changes, err := converter.ToOperations(operations)
@@ -68,7 +68,7 @@ func (i *ChangeInfo) ToChange() (*change.Change, error) {
 		return nil, err
 	}
 
-	changeID := change.NewID(i.ClientSeq, i.Lamport, actorID)
+	changeID := change.NewID(i.ClientSeq, i.Lamport, &actorID, i.ServerSeq)
 
 	var pbOps []*api.Operation
 	for _, bytesOp := range i.Operations {
diff --git a/yorkie/backend/db/client_info.go b/yorkie/backend/db/client_info.go
index ca49ebb9..5ef867c3 100644
--- a/yorkie/backend/db/client_info.go
+++ b/yorkie/backend/db/client_info.go
@@ -121,7 +121,7 @@ func (i *ClientInfo) IsAttached(docID ID) (bool, error) {
 }
 
 // Checkpoint returns the checkpoint of the given document.
-func (i *ClientInfo) Checkpoint(docID ID) *change.Checkpoint {
+func (i *ClientInfo) Checkpoint(docID ID) change.Checkpoint {
 	clientDocInfo := i.Documents[docID]
 	if clientDocInfo == nil {
 		return change.InitialCheckpoint
@@ -133,7 +133,7 @@ func (i *ClientInfo) Checkpoint(docID ID) *change.Checkpoint {
 // UpdateCheckpoint updates the checkpoint of the given document.
 func (i *ClientInfo) UpdateCheckpoint(
 	docID ID,
-	cp *change.Checkpoint,
+	cp change.Checkpoint,
 ) error {
 	if !i.hasDocument(docID) {
 		return ErrDocumentNeverAttached
diff --git a/yorkie/backend/db/doc_info.go b/yorkie/backend/db/doc_info.go
index 2080f74e..1437baac 100644
--- a/yorkie/backend/db/doc_info.go
+++ b/yorkie/backend/db/doc_info.go
@@ -24,13 +24,13 @@ import (
 
 // DocInfo is a structure representing information of the document.
 type DocInfo struct {
-	ID         ID        `bson:"_id"`
-	Key        string    `bson:"key"`
-	ServerSeq  uint64    `bson:"server_seq"`
-	Owner      ID        `bson:"owner"`
-	CreatedAt  time.Time `bson:"created_at"`
-	AccessedAt time.Time `bson:"accessed_at"`
-	UpdatedAt  time.Time `bson:"updated_at"`
+	ID          ID        `bson:"_id"`
+	CombinedKey string    `bson:"key"`
+	ServerSeq   uint64    `bson:"server_seq"`
+	Owner       ID        `bson:"owner"`
+	CreatedAt   time.Time `bson:"created_at"`
+	AccessedAt  time.Time `bson:"accessed_at"`
+	UpdatedAt   time.Time `bson:"updated_at"`
 }
 
 // IncreaseServerSeq increases server sequence of the document.
@@ -39,11 +39,11 @@ func (info *DocInfo) IncreaseServerSeq() uint64 {
 	return info.ServerSeq
 }
 
-// GetKey creates Key instance of this DocInfo.
-func (info *DocInfo) GetKey() (*key.Key, error) {
-	docKey, err := key.FromBSONKey(info.Key)
+// Key creates Key instance of this DocInfo.
+func (info *DocInfo) Key() (key.Key, error) {
+	docKey, err := key.FromCombinedKey(info.CombinedKey)
 	if err != nil {
-		return nil, err
+		return key.Key{}, err
 	}
 
 	return docKey, nil
@@ -56,12 +56,12 @@ func (info *DocInfo) DeepCopy() *DocInfo {
 	}
 
 	return &DocInfo{
-		ID:         info.ID,
-		Key:        info.Key,
-		ServerSeq:  info.ServerSeq,
-		Owner:      info.Owner,
-		CreatedAt:  info.CreatedAt,
-		AccessedAt: info.AccessedAt,
-		UpdatedAt:  info.UpdatedAt,
+		ID:          info.ID,
+		CombinedKey: info.CombinedKey,
+		ServerSeq:   info.ServerSeq,
+		Owner:       info.Owner,
+		CreatedAt:   info.CreatedAt,
+		AccessedAt:  info.AccessedAt,
+		UpdatedAt:   info.UpdatedAt,
 	}
 }
diff --git a/yorkie/backend/db/memory/db.go b/yorkie/backend/db/memory/db.go
index f578daa9..e5547c95 100644
--- a/yorkie/backend/db/memory/db.go
+++ b/yorkie/backend/db/memory/db.go
@@ -260,12 +260,12 @@ func (d *DB) FindDocInfoByKey(
 	var docInfo *db.DocInfo
 	if raw == nil {
 		docInfo = &db.DocInfo{
-			ID:         newID(),
-			Key:        bsonDocKey,
-			Owner:      clientInfo.ID,
-			ServerSeq:  0,
-			CreatedAt:  now,
-			AccessedAt: now,
+			ID:          newID(),
+			CombinedKey: bsonDocKey,
+			Owner:       clientInfo.ID,
+			ServerSeq:   0,
+			CreatedAt:   now,
+			AccessedAt:  now,
 		}
 		if err := txn.Insert(tblDocuments, docInfo); err != nil {
 			return nil, err
@@ -308,12 +308,12 @@ func (d *DB) CreateChangeInfos(
 		}
 	}
 
-	raw, err := txn.First(tblDocuments, "key", docInfo.Key)
+	raw, err := txn.First(tblDocuments, "key", docInfo.CombinedKey)
 	if err != nil {
 		return err
 	}
 	if raw == nil {
-		return fmt.Errorf("%s: %w", docInfo.Key, db.ErrDocumentNotFound)
+		return fmt.Errorf("%s: %w", docInfo.CombinedKey, db.ErrDocumentNotFound)
 	}
 	loadedDocInfo := raw.(*db.DocInfo).DeepCopy()
 	if loadedDocInfo.ServerSeq != initialServerSeq {
@@ -493,7 +493,7 @@ func (d *DB) UpdateAndFindMinSyncedTicket(
 	return time.NewTicket(
 		syncedSeqInfo.Lamport,
 		time.MaxDelimiter,
-		actorID,
+		&actorID,
 	), nil
 }
 
@@ -597,7 +597,7 @@ func (d *DB) findTicketByServerSeq(
 	return time.NewTicket(
 		changeInfo.Lamport,
 		time.MaxDelimiter,
-		actorID,
+		&actorID,
 	), nil
 }
 
diff --git a/yorkie/backend/db/memory/indexes.go b/yorkie/backend/db/memory/indexes.go
index fed74906..b8d159da 100644
--- a/yorkie/backend/db/memory/indexes.go
+++ b/yorkie/backend/db/memory/indexes.go
@@ -63,7 +63,7 @@ var schema = &memdb.DBSchema{
 				"key": {
 					Name:    "key",
 					Unique:  true,
-					Indexer: &memdb.StringFieldIndex{Field: "Key"},
+					Indexer: &memdb.StringFieldIndex{Field: "CombinedKey"},
 				},
 			},
 		},
diff --git a/yorkie/backend/db/mongo/client.go b/yorkie/backend/db/mongo/client.go
index a8d7f4b8..cb766f42 100644
--- a/yorkie/backend/db/mongo/client.go
+++ b/yorkie/backend/db/mongo/client.go
@@ -544,7 +544,7 @@ func (c *Client) UpdateAndFindMinSyncedTicket(
 	return time.NewTicket(
 		syncedSeqInfo.Lamport,
 		time.MaxDelimiter,
-		actorID,
+		&actorID,
 	), nil
 }
 
@@ -648,7 +648,7 @@ func (c *Client) findTicketByServerSeq(
 	return time.NewTicket(
 		changeInfo.Lamport,
 		time.MaxDelimiter,
-		actorID,
+		&actorID,
 	), nil
 }
 
diff --git a/yorkie/backend/sync/coordinator.go b/yorkie/backend/sync/coordinator.go
index e24279f6..fdf03830 100644
--- a/yorkie/backend/sync/coordinator.go
+++ b/yorkie/backend/sync/coordinator.go
@@ -48,27 +48,27 @@ type Coordinator interface {
 	Subscribe(
 		ctx context.Context,
 		subscriber types.Client,
-		docKeys []*key.Key,
+		docKeys []key.Key,
 	) (*Subscription, map[string][]types.Client, error)
 
 	// Unsubscribe unsubscribes from the given documents.
 	Unsubscribe(
 		ctx context.Context,
-		docKeys []*key.Key,
+		docKeys []key.Key,
 		sub *Subscription,
 	) error
 
 	// Publish publishes the given event.
-	Publish(ctx context.Context, publisherID *time.ActorID, event DocEvent)
+	Publish(ctx context.Context, publisherID time.ActorID, event DocEvent)
 
 	// PublishToLocal publishes the given event.
-	PublishToLocal(ctx context.Context, publisherID *time.ActorID, event DocEvent)
+	PublishToLocal(ctx context.Context, publisherID time.ActorID, event DocEvent)
 
 	// UpdateMetadata updates the metadata of the given client.
 	UpdateMetadata(
 		ctx context.Context,
 		publisher *types.Client,
-		keys []*key.Key,
+		keys []key.Key,
 	) (*DocEvent, error)
 
 	// Members returns the members of this cluster.
diff --git a/yorkie/backend/sync/etcd/pubsub.go b/yorkie/backend/sync/etcd/pubsub.go
index 06be93fe..5726e7ff 100644
--- a/yorkie/backend/sync/etcd/pubsub.go
+++ b/yorkie/backend/sync/etcd/pubsub.go
@@ -41,7 +41,7 @@ const (
 func (c *Client) Subscribe(
 	ctx context.Context,
 	subscriber types.Client,
-	keys []*key.Key,
+	keys []key.Key,
 ) (*sync.Subscription, map[string][]types.Client, error) {
 	sub, err := c.localPubSub.Subscribe(ctx, subscriber, keys)
 	if err != nil {
@@ -62,7 +62,7 @@ func (c *Client) Subscribe(
 			return nil, nil, err
 		}
 
-		peersMap[k.BSONKey()] = subs
+		peersMap[k.CombinedKey()] = subs
 	}
 
 	return sub, peersMap, nil
@@ -71,7 +71,7 @@ func (c *Client) Subscribe(
 // Unsubscribe unsubscribes the given keys.
 func (c *Client) Unsubscribe(
 	ctx context.Context,
-	keys []*key.Key,
+	keys []key.Key,
 	sub *sync.Subscription,
 ) error {
 	c.localPubSub.Unsubscribe(ctx, keys, sub)
@@ -81,7 +81,7 @@ func (c *Client) Unsubscribe(
 // Publish publishes the given event.
 func (c *Client) Publish(
 	ctx context.Context,
-	publisherID *time.ActorID,
+	publisherID time.ActorID,
 	event sync.DocEvent,
 ) {
 	c.localPubSub.Publish(ctx, publisherID, event)
@@ -91,7 +91,7 @@ func (c *Client) Publish(
 // PublishToLocal publishes the given event.
 func (c *Client) PublishToLocal(
 	ctx context.Context,
-	publisherID *time.ActorID,
+	publisherID time.ActorID,
 	event sync.DocEvent,
 ) {
 	c.localPubSub.Publish(ctx, publisherID, event)
@@ -101,7 +101,7 @@ func (c *Client) PublishToLocal(
 func (c *Client) UpdateMetadata(
 	ctx context.Context,
 	publisher *types.Client,
-	keys []*key.Key,
+	keys []key.Key,
 ) (*sync.DocEvent, error) {
 	if sub := c.localPubSub.UpdateMetadata(publisher, keys); sub != nil {
 		if err := c.putSubscriptions(ctx, keys, sub); err != nil {
@@ -184,7 +184,7 @@ func (c *Client) removeClusterClient(id string) {
 func (c *Client) publishToMember(
 	ctx context.Context,
 	clientInfo *clusterClientInfo,
-	publisherID *time.ActorID,
+	publisherID time.ActorID,
 	event sync.DocEvent,
 ) error {
 	docEvent, err := converter.ToDocEvent(event)
@@ -207,7 +207,7 @@ func (c *Client) publishToMember(
 // putSubscriptions puts the given subscriptions in etcd.
 func (c *Client) putSubscriptions(
 	ctx context.Context,
-	keys []*key.Key,
+	keys []key.Key,
 	sub *sync.Subscription,
 ) error {
 	cli := sub.Subscriber()
@@ -217,7 +217,7 @@ func (c *Client) putSubscriptions(
 	}
 
 	for _, k := range keys {
-		k := path.Join(subscriptionsPath, k.BSONKey(), sub.ID())
+		k := path.Join(subscriptionsPath, k.CombinedKey(), sub.ID())
 		if _, err = c.client.Put(ctx, k, encoded); err != nil {
 			logging.From(ctx).Error(err)
 			return fmt.Errorf("put %s: %w", k, err)
@@ -230,11 +230,11 @@ func (c *Client) putSubscriptions(
 // pullSubscriptions pulls the subscriptions of the given document key.
 func (c *Client) pullSubscriptions(
 	ctx context.Context,
-	k *key.Key,
+	k key.Key,
 ) ([]types.Client, error) {
 	getResponse, err := c.client.Get(
 		ctx,
-		path.Join(subscriptionsPath, k.BSONKey()),
+		path.Join(subscriptionsPath, k.CombinedKey()),
 		clientv3.WithPrefix(),
 	)
 	if err != nil {
@@ -257,11 +257,11 @@ func (c *Client) pullSubscriptions(
 // removeSubscriptions removes the given subscription in etcd.
 func (c *Client) removeSubscriptions(
 	ctx context.Context,
-	keys []*key.Key,
+	keys []key.Key,
 	sub *sync.Subscription,
 ) error {
 	for _, docKey := range keys {
-		k := path.Join(subscriptionsPath, docKey.BSONKey(), sub.ID())
+		k := path.Join(subscriptionsPath, docKey.CombinedKey(), sub.ID())
 		if _, err := c.client.Delete(ctx, k); err != nil {
 			logging.From(ctx).Error(err)
 			return err
diff --git a/yorkie/backend/sync/memory/coordinator.go b/yorkie/backend/sync/memory/coordinator.go
index 87614de5..e2f16f2f 100644
--- a/yorkie/backend/sync/memory/coordinator.go
+++ b/yorkie/backend/sync/memory/coordinator.go
@@ -59,7 +59,7 @@ func (c *Coordinator) NewLocker(
 func (c *Coordinator) Subscribe(
 	ctx context.Context,
 	subscriber types.Client,
-	keys []*key.Key,
+	keys []key.Key,
 ) (*sync.Subscription, map[string][]types.Client, error) {
 	sub, err := c.pubSub.Subscribe(ctx, subscriber, keys)
 	if err != nil {
@@ -73,7 +73,7 @@ func (c *Coordinator) Subscribe(
 // Unsubscribe unsubscribes the given documents.
 func (c *Coordinator) Unsubscribe(
 	ctx context.Context,
-	keys []*key.Key,
+	keys []key.Key,
 	sub *sync.Subscription,
 ) error {
 	c.pubSub.Unsubscribe(ctx, keys, sub)
@@ -83,7 +83,7 @@ func (c *Coordinator) Unsubscribe(
 // Publish publishes the given event.
 func (c *Coordinator) Publish(
 	ctx context.Context,
-	publisherID *time.ActorID,
+	publisherID time.ActorID,
 	event sync.DocEvent,
 ) {
 	c.pubSub.Publish(ctx, publisherID, event)
@@ -92,7 +92,7 @@ func (c *Coordinator) Publish(
 // PublishToLocal publishes the given event.
 func (c *Coordinator) PublishToLocal(
 	ctx context.Context,
-	publisherID *time.ActorID,
+	publisherID time.ActorID,
 	event sync.DocEvent,
 ) {
 	c.pubSub.Publish(ctx, publisherID, event)
@@ -102,7 +102,7 @@ func (c *Coordinator) PublishToLocal(
 func (c *Coordinator) UpdateMetadata(
 	_ context.Context,
 	publisher *types.Client,
-	keys []*key.Key,
+	keys []key.Key,
 ) (*sync.DocEvent, error) {
 	c.pubSub.UpdateMetadata(publisher, keys)
 
diff --git a/yorkie/backend/sync/memory/pubsub.go b/yorkie/backend/sync/memory/pubsub.go
index 694b0eb3..8864d1e3 100644
--- a/yorkie/backend/sync/memory/pubsub.go
+++ b/yorkie/backend/sync/memory/pubsub.go
@@ -84,7 +84,7 @@ func NewPubSub() *PubSub {
 func (m *PubSub) Subscribe(
 	ctx context.Context,
 	subscriber types.Client,
-	keys []*key.Key,
+	keys []key.Key,
 ) (*sync.Subscription, error) {
 	if len(keys) == 0 {
 		return nil, sync.ErrEmptyDocKeys
@@ -93,7 +93,7 @@ func (m *PubSub) Subscribe(
 	if logging.Enabled(zap.DebugLevel) {
 		logging.From(ctx).Debugf(
 			`Subscribe(%s,%s) Start`,
-			keys[0].BSONKey(),
+			keys[0].CombinedKey(),
 			subscriber.ID.String(),
 		)
 	}
@@ -105,17 +105,17 @@ func (m *PubSub) Subscribe(
 	m.subscriptionMapBySubscriber[sub.SubscriberID()] = sub
 
 	for _, docKey := range keys {
-		bsonKey := docKey.BSONKey()
-		if _, ok := m.subscriptionsMapByDocKey[bsonKey]; !ok {
-			m.subscriptionsMapByDocKey[bsonKey] = newSubscriptions()
+		combinedKey := docKey.CombinedKey()
+		if _, ok := m.subscriptionsMapByDocKey[combinedKey]; !ok {
+			m.subscriptionsMapByDocKey[combinedKey] = newSubscriptions()
 		}
-		m.subscriptionsMapByDocKey[bsonKey].Add(sub)
+		m.subscriptionsMapByDocKey[combinedKey].Add(sub)
 	}
 
 	if logging.Enabled(zap.DebugLevel) {
 		logging.From(ctx).Debugf(
 			`Subscribe(%s,%s) End`,
-			keys[0].BSONKey(),
+			keys[0].CombinedKey(),
 			subscriber.ID.String(),
 		)
 	}
@@ -123,15 +123,15 @@ func (m *PubSub) Subscribe(
 }
 
 // BuildPeersMap builds the peers map of the given keys.
-func (m *PubSub) BuildPeersMap(keys []*key.Key) map[string][]types.Client {
+func (m *PubSub) BuildPeersMap(keys []key.Key) map[string][]types.Client {
 	peersMap := make(map[string][]types.Client)
 	for _, docKey := range keys {
-		bsonKey := docKey.BSONKey()
+		combinedKey := docKey.CombinedKey()
 		var peers []types.Client
-		for _, sub := range m.subscriptionsMapByDocKey[bsonKey].Map() {
+		for _, sub := range m.subscriptionsMapByDocKey[combinedKey].Map() {
 			peers = append(peers, sub.Subscriber())
 		}
-		peersMap[bsonKey] = peers
+		peersMap[combinedKey] = peers
 	}
 	return peersMap
 }
@@ -139,7 +139,7 @@ func (m *PubSub) BuildPeersMap(keys []*key.Key) map[string][]types.Client {
 // Unsubscribe unsubscribes the given docKeys.
 func (m *PubSub) Unsubscribe(
 	ctx context.Context,
-	docKeys []*key.Key,
+	docKeys []key.Key,
 	sub *sync.Subscription,
 ) {
 	m.subscriptionsMapMu.Lock()
@@ -148,7 +148,7 @@ func (m *PubSub) Unsubscribe(
 	if logging.Enabled(zap.DebugLevel) {
 		logging.From(ctx).Debugf(
 			`Unsubscribe(%s,%s) Start`,
-			docKeys[0].BSONKey(),
+			docKeys[0].CombinedKey(),
 			sub.SubscriberID(),
 		)
 	}
@@ -157,7 +157,7 @@ func (m *PubSub) Unsubscribe(
 
 	delete(m.subscriptionMapBySubscriber, sub.SubscriberID())
 	for _, docKey := range docKeys {
-		k := docKey.BSONKey()
+		k := docKey.CombinedKey()
 		if subs, ok := m.subscriptionsMapByDocKey[k]; ok {
 			subs.Delete(sub.ID())
 
@@ -170,7 +170,7 @@ func (m *PubSub) Unsubscribe(
 	if logging.Enabled(zap.DebugLevel) {
 		logging.From(ctx).Debugf(
 			`Unsubscribe(%s,%s) End`,
-			docKeys[0].BSONKey(),
+			docKeys[0].CombinedKey(),
 			sub.SubscriberID(),
 		)
 	}
@@ -179,14 +179,14 @@ func (m *PubSub) Unsubscribe(
 // Publish publishes the given event.
 func (m *PubSub) Publish(
 	ctx context.Context,
-	publisherID *time.ActorID,
+	publisherID time.ActorID,
 	event sync.DocEvent,
 ) {
 	m.subscriptionsMapMu.RLock()
 	defer m.subscriptionsMapMu.RUnlock()
 
 	for _, docKey := range event.DocumentKeys {
-		k := docKey.BSONKey()
+		k := docKey.CombinedKey()
 
 		if logging.Enabled(zap.DebugLevel) {
 			logging.From(ctx).Debugf(`Publish(%s,%s) Start`, k, publisherID.String())
@@ -230,7 +230,7 @@ func (m *PubSub) Publish(
 // UpdateMetadata updates the metadata of the given client.
 func (m *PubSub) UpdateMetadata(
 	publisher *types.Client,
-	keys []*key.Key,
+	keys []key.Key,
 ) *sync.Subscription {
 	m.subscriptionsMapMu.Lock()
 	defer m.subscriptionsMapMu.Unlock()
diff --git a/yorkie/backend/sync/pubsub.go b/yorkie/backend/sync/pubsub.go
index f9f45fbb..e3784092 100644
--- a/yorkie/backend/sync/pubsub.go
+++ b/yorkie/backend/sync/pubsub.go
@@ -49,7 +49,7 @@ func (s *Subscription) ID() string {
 type DocEvent struct {
 	Type         types.DocEventType
 	Publisher    types.Client
-	DocumentKeys []*key.Key
+	DocumentKeys []key.Key
 }
 
 // Events returns the DocEvent channel of this subscription.
diff --git a/yorkie/clients/clients.go b/yorkie/clients/clients.go
index 7d7e19d9..c015e3e7 100644
--- a/yorkie/clients/clients.go
+++ b/yorkie/clients/clients.go
@@ -21,6 +21,7 @@ import (
 	"errors"
 
 	"github.com/yorkie-team/yorkie/pkg/document/key"
+	"github.com/yorkie-team/yorkie/pkg/document/time"
 	"github.com/yorkie-team/yorkie/yorkie/backend"
 	"github.com/yorkie-team/yorkie/yorkie/backend/db"
 )
@@ -46,20 +47,32 @@ func Activate(
 func Deactivate(
 	ctx context.Context,
 	be *backend.Backend,
-	clientID db.ID,
+	actorID time.ActorID,
 ) (*db.ClientInfo, error) {
-	return be.DB.DeactivateClient(ctx, clientID)
+	return be.DB.DeactivateClient(ctx, db.IDFromActorID(actorID))
+}
+
+// FindClient finds the client with the given id.
+func FindClient(
+	ctx context.Context,
+	be *backend.Backend,
+	clientID time.ActorID,
+) (*db.ClientInfo, error) {
+	return be.DB.FindClientInfoByID(
+		ctx,
+		db.IDFromActorID(clientID),
+	)
 }
 
 // FindClientAndDocument finds the client and the document.
 func FindClientAndDocument(
 	ctx context.Context,
 	be *backend.Backend,
-	clientID db.ID,
-	docKey *key.Key,
+	actorID time.ActorID,
+	docKey key.Key,
 	createDocIfNotExist bool,
 ) (*db.ClientInfo, *db.DocInfo, error) {
-	clientInfo, err := be.DB.FindClientInfoByID(ctx, clientID)
+	clientInfo, err := be.DB.FindClientInfoByID(ctx, db.IDFromActorID(actorID))
 	if err != nil {
 		return nil, nil, err
 	}
@@ -67,7 +80,7 @@ func FindClientAndDocument(
 	docInfo, err := be.DB.FindDocInfoByKey(
 		ctx,
 		clientInfo,
-		docKey.BSONKey(),
+		docKey.CombinedKey(),
 		createDocIfNotExist,
 	)
 	if err != nil {
diff --git a/yorkie/packs/history.go b/yorkie/packs/history.go
new file mode 100644
index 00000000..5add90d2
--- /dev/null
+++ b/yorkie/packs/history.go
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022 The Yorkie Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package packs
+
+import (
+	"context"
+
+	"github.com/yorkie-team/yorkie/pkg/document/change"
+	"github.com/yorkie-team/yorkie/yorkie/backend"
+	"github.com/yorkie-team/yorkie/yorkie/backend/db"
+)
+
+// FindAllChanges fetches all changes of the given document.
+func FindAllChanges(
+	ctx context.Context,
+	be *backend.Backend,
+	docInfo *db.DocInfo,
+) ([]*change.Change, error) {
+	changes, err := be.DB.FindChangesBetweenServerSeqs(
+		ctx,
+		docInfo.ID,
+		0,
+		docInfo.ServerSeq,
+	)
+	return changes, err
+}
diff --git a/yorkie/packs/packs.go b/yorkie/packs/packs.go
index c62bb175..396f426b 100644
--- a/yorkie/packs/packs.go
+++ b/yorkie/packs/packs.go
@@ -32,13 +32,13 @@ import (
 )
 
 // NewPushPullKey creates a new sync.Key of PushPull for the given document.
-func NewPushPullKey(documentKey *key.Key) sync.Key {
-	return sync.NewKey(fmt.Sprintf("pushpull-%s", documentKey.BSONKey()))
+func NewPushPullKey(docKey key.Key) sync.Key {
+	return sync.NewKey(fmt.Sprintf("pushpull-%s", docKey.CombinedKey()))
 }
 
 // NewSnapshotKey creates a new sync.Key of Snapshot for the given document.
-func NewSnapshotKey(documentKey *key.Key) sync.Key {
-	return sync.NewKey(fmt.Sprintf("snapshot-%s", documentKey.BSONKey()))
+func NewSnapshotKey(docKey key.Key) sync.Key {
+	return sync.NewKey(fmt.Sprintf("snapshot-%s", docKey.CombinedKey()))
 }
 
 // PushPull stores the given changes and returns accumulated changes of the
@@ -141,7 +141,7 @@ func PushPull(
 				sync.DocEvent{
 					Type:         types.DocumentsChangedEvent,
 					Publisher:    types.Client{ID: publisherID},
-					DocumentKeys: []*key.Key{reqPack.DocumentKey},
+					DocumentKeys: []key.Key{reqPack.DocumentKey},
 				},
 			)
 
diff --git a/yorkie/packs/pushpull.go b/yorkie/packs/pushpull.go
index 2c521be0..d65debb2 100644
--- a/yorkie/packs/pushpull.go
+++ b/yorkie/packs/pushpull.go
@@ -44,7 +44,7 @@ func pushChanges(
 	docInfo *db.DocInfo,
 	pack *change.Pack,
 	initialServerSeq uint64,
-) (*change.Checkpoint, []*change.Change, error) {
+) (change.Checkpoint, []*change.Change, error) {
 	cp := clientInfo.Checkpoint(docInfo.ID)
 
 	var pushedChanges []*change.Change
@@ -66,7 +66,7 @@ func pushChanges(
 			"PUSH: '%s' pushes %d changes into '%s', rejected %d changes, serverSeq: %d -> %d, cp: %s",
 			clientInfo.ID,
 			len(pushedChanges),
-			docInfo.Key,
+			docInfo.CombinedKey,
 			len(pack.Changes)-len(pushedChanges),
 			initialServerSeq,
 			docInfo.ServerSeq,
@@ -83,10 +83,10 @@ func pullPack(
 	clientInfo *db.ClientInfo,
 	docInfo *db.DocInfo,
 	requestPack *change.Pack,
-	pushedCP *change.Checkpoint,
+	pushedCP change.Checkpoint,
 	initialServerSeq uint64,
 ) (*ServerPack, error) {
-	docKey, err := docInfo.GetKey()
+	docKey, err := docInfo.Key()
 	if err != nil {
 		return nil, err
 	}
@@ -122,9 +122,9 @@ func pullChangeInfos(
 	clientInfo *db.ClientInfo,
 	docInfo *db.DocInfo,
 	requestPack *change.Pack,
-	pushedCP *change.Checkpoint,
+	pushedCP change.Checkpoint,
 	initialServerSeq uint64,
-) (*change.Checkpoint, []*db.ChangeInfo, error) {
+) (change.Checkpoint, []*db.ChangeInfo, error) {
 	pulledChanges, err := be.DB.FindChangeInfosBetweenServerSeqs(
 		ctx,
 		docInfo.ID,
@@ -132,7 +132,7 @@ func pullChangeInfos(
 		initialServerSeq,
 	)
 	if err != nil {
-		return nil, nil, err
+		return change.InitialCheckpoint, nil, err
 	}
 
 	pulledCP := pushedCP.NextServerSeq(docInfo.ServerSeq)
@@ -144,7 +144,7 @@ func pullChangeInfos(
 			len(pulledChanges),
 			pulledChanges[0].ServerSeq,
 			pulledChanges[len(pulledChanges)-1].ServerSeq,
-			docInfo.Key,
+			docInfo.CombinedKey,
 			pulledCP.String(),
 		)
 	}
@@ -158,12 +158,12 @@ func pullSnapshot(
 	clientInfo *db.ClientInfo,
 	docInfo *db.DocInfo,
 	pack *change.Pack,
-	pushedCP *change.Checkpoint,
+	pushedCP change.Checkpoint,
 	initialServerSeq uint64,
-) (*change.Checkpoint, []byte, error) {
+) (change.Checkpoint, []byte, error) {
 	snapshotInfo, err := be.DB.FindLastSnapshotInfo(ctx, docInfo.ID)
 	if err != nil {
-		return nil, nil, err
+		return change.InitialCheckpoint, nil, err
 	}
 
 	if snapshotInfo.ServerSeq >= initialServerSeq {
@@ -171,25 +171,24 @@ func pullSnapshot(
 		logging.From(ctx).Infof(
 			"PULL: '%s' pulls snapshot without changes from '%s', cp: %s",
 			clientInfo.ID,
-			docInfo.Key,
+			docInfo.CombinedKey,
 			pulledCP.String(),
 		)
 		return pushedCP.NextServerSeq(docInfo.ServerSeq), snapshotInfo.Snapshot, nil
 	}
 
-	docKey, err := docInfo.GetKey()
+	docKey, err := docInfo.Key()
 	if err != nil {
-		return nil, nil, err
+		return change.InitialCheckpoint, nil, err
 	}
 
 	doc, err := document.NewInternalDocumentFromSnapshot(
-		docKey.Collection,
-		docKey.Document,
+		docKey,
 		snapshotInfo.ServerSeq,
 		snapshotInfo.Snapshot,
 	)
 	if err != nil {
-		return nil, nil, err
+		return change.InitialCheckpoint, nil, err
 	}
 
 	// TODO(hackerwins): If the Snapshot is missing, we may have a very large
@@ -202,7 +201,7 @@ func pullSnapshot(
 		initialServerSeq,
 	)
 	if err != nil {
-		return nil, nil, err
+		return change.InitialCheckpoint, nil, err
 	}
 
 	if err := doc.ApplyChangePack(change.NewPack(
@@ -211,7 +210,7 @@ func pullSnapshot(
 		changes,
 		nil,
 	)); err != nil {
-		return nil, nil, err
+		return change.InitialCheckpoint, nil, err
 	}
 
 	if logging.Enabled(zap.DebugLevel) {
@@ -231,13 +230,13 @@ func pullSnapshot(
 		clientInfo.ID,
 		pack.Checkpoint.ServerSeq+1,
 		initialServerSeq,
-		docInfo.Key,
+		docInfo.CombinedKey,
 		pulledCP.String(),
 	)
 
 	snapshot, err := converter.ObjectToBytes(doc.RootObject())
 	if err != nil {
-		return nil, nil, err
+		return change.InitialCheckpoint, nil, err
 	}
 
 	return pulledCP, snapshot, nil
diff --git a/yorkie/packs/serverpacks.go b/yorkie/packs/serverpacks.go
index 85f882e6..2916aa49 100644
--- a/yorkie/packs/serverpacks.go
+++ b/yorkie/packs/serverpacks.go
@@ -30,10 +30,10 @@ import (
 // to reduce type conversion in Agent.
 type ServerPack struct {
 	// DocumentKey is key of the document.
-	DocumentKey *key.Key
+	DocumentKey key.Key
 
 	// Checkpoint is used to determine the client received changes.
-	Checkpoint *change.Checkpoint
+	Checkpoint change.Checkpoint
 
 	// ChangeInfos represents a unit of modification in the document.
 	ChangeInfos []*db.ChangeInfo
@@ -48,8 +48,8 @@ type ServerPack struct {
 
 // NewServerPack creates a new instance of ServerPack.
 func NewServerPack(
-	key *key.Key,
-	cp *change.Checkpoint,
+	key key.Key,
+	cp change.Checkpoint,
 	changeInfos []*db.ChangeInfo,
 	snapshot []byte,
 ) *ServerPack {
@@ -88,7 +88,7 @@ func (p *ServerPack) ToPBChangePack() (*api.ChangePack, error) {
 		if err != nil {
 			return nil, err
 		}
-		changeID := change.NewID(changeInfo.ClientSeq, changeInfo.Lamport, actorID)
+		changeID := change.NewID(changeInfo.ClientSeq, changeInfo.Lamport, &actorID)
 
 		var pbOps []*api.Operation
 		for _, bytesOp := range changeInfo.Operations {
diff --git a/yorkie/packs/snapshots.go b/yorkie/packs/snapshots.go
index b8e21918..3ef91a6f 100644
--- a/yorkie/packs/snapshots.go
+++ b/yorkie/packs/snapshots.go
@@ -59,14 +59,13 @@ func storeSnapshot(
 	}
 
 	// 03. create document instance of the docInfo
-	docKey, err := docInfo.GetKey()
+	docKey, err := docInfo.Key()
 	if err != nil {
 		return err
 	}
 
 	doc, err := document.NewInternalDocumentFromSnapshot(
-		docKey.Collection,
-		docKey.Document,
+		docKey,
 		snapshotInfo.ServerSeq,
 		snapshotInfo.Snapshot,
 	)
@@ -93,7 +92,7 @@ func storeSnapshot(
 
 	logging.From(ctx).Infof(
 		"SNAP: '%s', serverSeq: %d",
-		docInfo.Key,
+		docInfo.CombinedKey,
 		doc.Checkpoint().ServerSeq,
 	)
 	return nil
diff --git a/yorkie/rpc/interceptors/default.go b/yorkie/rpc/interceptors/default.go
index 888594b1..e50ed5e8 100644
--- a/yorkie/rpc/interceptors/default.go
+++ b/yorkie/rpc/interceptors/default.go
@@ -100,6 +100,7 @@ func toStatusError(err error) error {
 	if errors.Is(err, converter.ErrPackRequired) ||
 		errors.Is(err, converter.ErrCheckpointRequired) ||
 		errors.Is(err, time.ErrInvalidHexString) ||
+		errors.Is(err, time.ErrInvalidActorID) ||
 		errors.Is(err, db.ErrInvalidID) ||
 		errors.Is(err, clients.ErrInvalidClientID) ||
 		errors.Is(err, clients.ErrInvalidClientKey) {
diff --git a/yorkie/rpc/yorkie_server.go b/yorkie/rpc/yorkie_server.go
index d1698295..d1efd1ea 100644
--- a/yorkie/rpc/yorkie_server.go
+++ b/yorkie/rpc/yorkie_server.go
@@ -22,10 +22,10 @@ import (
 	"github.com/yorkie-team/yorkie/api"
 	"github.com/yorkie-team/yorkie/api/converter"
 	"github.com/yorkie-team/yorkie/pkg/document/key"
+	"github.com/yorkie-team/yorkie/pkg/document/time"
 	"github.com/yorkie-team/yorkie/pkg/types"
 	"github.com/yorkie-team/yorkie/yorkie/auth"
 	"github.com/yorkie-team/yorkie/yorkie/backend"
-	"github.com/yorkie-team/yorkie/yorkie/backend/db"
 	"github.com/yorkie-team/yorkie/yorkie/backend/sync"
 	"github.com/yorkie-team/yorkie/yorkie/clients"
 	"github.com/yorkie-team/yorkie/yorkie/logging"
@@ -60,18 +60,18 @@ func (s *yorkieServer) ActivateClient(
 		return nil, err
 	}
 
-	client, err := clients.Activate(ctx, s.backend, req.ClientKey)
+	cli, err := clients.Activate(ctx, s.backend, req.ClientKey)
 	if err != nil {
 		return nil, err
 	}
 
-	pbClientID, err := client.ID.Bytes()
+	pbClientID, err := cli.ID.Bytes()
 	if err != nil {
 		return nil, err
 	}
 
 	return &api.ActivateClientResponse{
-		ClientKey: client.Key,
+		ClientKey: cli.Key,
 		ClientId:  pbClientID,
 	}, nil
 }
@@ -81,8 +81,9 @@ func (s *yorkieServer) DeactivateClient(
 	ctx context.Context,
 	req *api.DeactivateClientRequest,
 ) (*api.DeactivateClientResponse, error) {
-	if len(req.ClientId) == 0 {
-		return nil, clients.ErrInvalidClientID
+	actorID, err := time.ActorIDFromBytes(req.ClientId)
+	if err != nil {
+		return nil, err
 	}
 
 	if err := auth.VerifyAccess(ctx, s.backend, &types.AccessInfo{
@@ -91,12 +92,12 @@ func (s *yorkieServer) DeactivateClient(
 		return nil, err
 	}
 
-	client, err := clients.Deactivate(ctx, s.backend, db.IDFromBytes(req.ClientId))
+	cli, err := clients.Deactivate(ctx, s.backend, actorID)
 	if err != nil {
 		return nil, err
 	}
 
-	pbClientID, err := client.ID.Bytes()
+	pbClientID, err := cli.ID.Bytes()
 	if err != nil {
 		return nil, err
 	}
@@ -111,6 +112,11 @@ func (s *yorkieServer) AttachDocument(
 	ctx context.Context,
 	req *api.AttachDocumentRequest,
 ) (*api.AttachDocumentResponse, error) {
+	actorID, err := time.ActorIDFromBytes(req.ClientId)
+	if err != nil {
+		return nil, err
+	}
+
 	pack, err := converter.FromChangePack(req.ChangePack)
 	if err != nil {
 		return nil, err
@@ -145,7 +151,7 @@ func (s *yorkieServer) AttachDocument(
 	clientInfo, docInfo, err := clients.FindClientAndDocument(
 		ctx,
 		s.backend,
-		db.IDFromBytes(req.ClientId),
+		actorID,
 		pack.DocumentKey,
 		true,
 	)
@@ -176,6 +182,11 @@ func (s *yorkieServer) DetachDocument(
 	ctx context.Context,
 	req *api.DetachDocumentRequest,
 ) (*api.DetachDocumentResponse, error) {
+	actorID, err := time.ActorIDFromBytes(req.ClientId)
+	if err != nil {
+		return nil, err
+	}
+
 	pack, err := converter.FromChangePack(req.ChangePack)
 	if err != nil {
 		return nil, err
@@ -210,7 +221,7 @@ func (s *yorkieServer) DetachDocument(
 	clientInfo, docInfo, err := clients.FindClientAndDocument(
 		ctx,
 		s.backend,
-		db.IDFromBytes(req.ClientId),
+		actorID,
 		pack.DocumentKey,
 		false,
 	)
@@ -245,6 +256,11 @@ func (s *yorkieServer) PushPull(
 	ctx context.Context,
 	req *api.PushPullRequest,
 ) (*api.PushPullResponse, error) {
+	actorID, err := time.ActorIDFromBytes(req.ClientId)
+	if err != nil {
+		return nil, err
+	}
+
 	pack, err := converter.FromChangePack(req.ChangePack)
 	if err != nil {
 		return nil, err
@@ -280,7 +296,7 @@ func (s *yorkieServer) PushPull(
 	clientInfo, docInfo, err := clients.FindClientAndDocument(
 		ctx,
 		s.backend,
-		db.IDFromBytes(req.ClientId),
+		actorID,
 		pack.DocumentKey,
 		false,
 	)
@@ -312,7 +328,7 @@ func (s *yorkieServer) WatchDocuments(
 	req *api.WatchDocumentsRequest,
 	stream api.Yorkie_WatchDocumentsServer,
 ) error {
-	client, err := converter.FromClient(req.Client)
+	cli, err := converter.FromClient(req.Client)
 	if err != nil {
 		return err
 	}
@@ -321,14 +337,15 @@ func (s *yorkieServer) WatchDocuments(
 	var attrs []types.AccessAttribute
 	for _, k := range docKeys {
 		attrs = append(attrs, types.AccessAttribute{
-			Key:  k.BSONKey(),
+			Key:  k.CombinedKey(),
 			Verb: types.Read,
 		})
 	}
 
-	if _, err = s.backend.DB.FindClientInfoByID(
+	if _, err = clients.FindClient(
 		stream.Context(),
-		db.IDFromActorID(*client.ID),
+		s.backend,
+		cli.ID,
 	); err != nil {
 		return err
 	}
@@ -342,7 +359,7 @@ func (s *yorkieServer) WatchDocuments(
 
 	subscription, peersMap, err := s.watchDocs(
 		stream.Context(),
-		*client,
+		*cli,
 		docKeys,
 	)
 	if err != nil {
@@ -398,13 +415,13 @@ func (s *yorkieServer) UpdateMetadata(
 	ctx context.Context,
 	req *api.UpdateMetadataRequest,
 ) (*api.UpdateMetadataResponse, error) {
-	client, err := converter.FromClient(req.Client)
+	cli, err := converter.FromClient(req.Client)
 	if err != nil {
 		return nil, err
 	}
 	keys := converter.FromDocumentKeys(req.DocumentKeys)
 
-	docEvent, err := s.backend.Coordinator.UpdateMetadata(ctx, client, keys)
+	docEvent, err := s.backend.Coordinator.UpdateMetadata(ctx, cli, keys)
 	if err != nil {
 		return nil, err
 	}
@@ -414,10 +431,61 @@ func (s *yorkieServer) UpdateMetadata(
 	return &api.UpdateMetadataResponse{}, nil
 }
 
+// FetchHistory fetches the history of the given document.
+func (s *yorkieServer) FetchHistory(
+	ctx context.Context,
+	req *api.FetchHistoryRequest,
+) (*api.FetchHistoryResponse, error) {
+	actorID, err := time.ActorIDFromBytes(req.ClientId)
+	if err != nil {
+		return nil, err
+	}
+	docKey := converter.FromDocumentKey(req.DocumentKey)
+
+	if err := auth.VerifyAccess(ctx, s.backend, &types.AccessInfo{
+		Method: types.FetchHistory,
+		Attributes: []types.AccessAttribute{{
+			Key:  docKey.CombinedKey(),
+			Verb: types.Read,
+		}},
+	}); err != nil {
+		return nil, err
+	}
+
+	_, docInfo, err := clients.FindClientAndDocument(
+		ctx,
+		s.backend,
+		actorID,
+		docKey,
+		false,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	changes, err := packs.FindAllChanges(
+		ctx,
+		s.backend,
+		docInfo,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	pbChanges, err := converter.ToChanges(changes)
+	if err != nil {
+		return nil, err
+	}
+
+	return &api.FetchHistoryResponse{
+		Changes: pbChanges,
+	}, nil
+}
+
 func (s *yorkieServer) watchDocs(
 	ctx context.Context,
 	client types.Client,
-	docKeys []*key.Key,
+	docKeys []key.Key,
 ) (*sync.Subscription, map[string][]types.Client, error) {
 	subscription, peersMap, err := s.backend.Coordinator.Subscribe(
 		ctx,
@@ -443,7 +511,7 @@ func (s *yorkieServer) watchDocs(
 }
 
 func (s *yorkieServer) unwatchDocs(
-	docKeys []*key.Key,
+	docKeys []key.Key,
 	subscription *sync.Subscription,
 ) {
 	ctx := context.Background()


Test patch:
diff --git a/pkg/document/json/primitive_test.go b/pkg/document/json/primitive_test.go
index b65acefc..36016a51 100644
--- a/pkg/document/json/primitive_test.go
+++ b/pkg/document/json/primitive_test.go
@@ -57,7 +57,7 @@ func TestPrimitive(t *testing.T) {
 			assert.Equal(t, prim.Marshal(), copied.Marshal())
 
 			actorID, _ := time.ActorIDFromHex("0")
-			prim.SetMovedAt(time.NewTicket(0, 0, actorID))
+			prim.SetMovedAt(time.NewTicket(0, 0, &actorID))
 			assert.NotEqual(t, prim.MovedAt(), copied.MovedAt())
 		}
 		longPrim := json.NewPrimitive(math.MaxInt32+1, time.InitialTicket)
diff --git a/pkg/document/time/actor_id_test.go b/pkg/document/time/actor_id_test.go
index 800801d0..cd066f45 100644
--- a/pkg/document/time/actor_id_test.go
+++ b/pkg/document/time/actor_id_test.go
@@ -54,6 +54,6 @@ func TestActorID(t *testing.T) {
 	t.Run("get ActorID from bytes on invalid length test", func(t *testing.T) {
 		invalidBytes := make([]byte, 5)
 		_, err := time.ActorIDFromBytes(invalidBytes)
-		assert.ErrorIs(t, err, time.ErrInvalidHexString)
+		assert.ErrorIs(t, err, time.ErrInvalidActorID)
 	})
 }
diff --git a/pkg/document/time/ticket_test.go b/pkg/document/time/ticket_test.go
index 24f69d22..12f6b901 100644
--- a/pkg/document/time/ticket_test.go
+++ b/pkg/document/time/ticket_test.go
@@ -11,48 +11,45 @@ import (
 func TestTicket(t *testing.T) {
 	t.Run("get hex from actorId of ticket test", func(t *testing.T) {
 		actorID, _ := time.ActorIDFromHex("0123456789abcdef01234567")
-		ticket := time.NewTicket(0, 0, actorID)
+		ticket := time.NewTicket(0, 0, &actorID)
 		assert.Equal(t, actorID.String(), ticket.ActorIDHex())
 	})
 
 	t.Run("get bytes from actorId of ticket test", func(t *testing.T) {
 		hexString := "0123456789abcdef01234567"
 		actorID, _ := time.ActorIDFromHex(hexString)
-		ticket := time.NewTicket(0, 0, actorID)
+		ticket := time.NewTicket(0, 0, &actorID)
 		assert.Equal(t, actorID.Bytes(), ticket.ActorIDBytes())
 	})
 
 	t.Run("constructor and getter method test", func(t *testing.T) {
 		actorID, _ := time.ActorIDFromHex("0123456789abcdef01234567")
-		ticket := time.NewTicket(0, 1, actorID)
+		ticket := time.NewTicket(0, 1, &actorID)
 		assert.Equal(t, uint64(0), ticket.Lamport())
 		assert.Equal(t, uint32(1), ticket.Delimiter())
-		assert.Equal(t, actorID, ticket.ActorID())
+		assert.Equal(t, actorID, *ticket.ActorID())
 
 		assert.Equal(t, "0:1:"+ticket.ActorIDHex(), ticket.Key())
 		assert.Equal(t, "0:1:"+ticket.ActorIDHex()[22:24],
 			ticket.AnnotatedString())
-		ticket = ticket.SetActorID(nil)
-		assert.Equal(t, "0:1:", ticket.Key())
-		assert.Equal(t, "0:1:nil", ticket.AnnotatedString())
 	})
 
 	t.Run("ticket comparing test", func(t *testing.T) {
 		beforeActorID, _ := time.ActorIDFromHex("0000000000abcdef01234567")
 		afterActorID, _ := time.ActorIDFromHex("0123456789abcdef01234567")
 
-		before := time.NewTicket(0, 0, beforeActorID)
-		after := time.NewTicket(1, 0, afterActorID)
+		before := time.NewTicket(0, 0, &beforeActorID)
+		after := time.NewTicket(1, 0, &afterActorID)
 		assert.True(t, after.After(before))
 		assert.False(t, before.After(after))
 
-		before = time.NewTicket(0, 0, beforeActorID)
-		after = time.NewTicket(0, 0, afterActorID)
+		before = time.NewTicket(0, 0, &beforeActorID)
+		after = time.NewTicket(0, 0, &afterActorID)
 		assert.True(t, after.After(before))
 		assert.False(t, before.After(after))
 
-		before = time.NewTicket(0, 0, beforeActorID)
-		after = time.NewTicket(0, 1, beforeActorID)
+		before = time.NewTicket(0, 0, &beforeActorID)
+		after = time.NewTicket(0, 1, &beforeActorID)
 		assert.True(t, after.After(before))
 		assert.False(t, before.After(after))
 
diff --git a/test/integration/agent_test.go b/test/integration/agent_test.go
index c3ad6ade..a6734246 100644
--- a/test/integration/agent_test.go
+++ b/test/integration/agent_test.go
@@ -58,7 +58,7 @@ func TestAgent(t *testing.T) {
 					return
 				case wr := <-wrch:
 					if wr.Err == io.EOF || status.Code(wr.Err) == codes.Canceled {
-						peers := wr.PeersMapByDoc[doc.Key().BSONKey()]
+						peers := wr.PeersMapByDoc[doc.Key().CombinedKey()]
 						assert.Len(t, peers, 0)
 						wg.Done()
 						return
diff --git a/test/integration/cluster_mode_test.go b/test/integration/cluster_mode_test.go
index 602e5800..54a37f1a 100644
--- a/test/integration/cluster_mode_test.go
+++ b/test/integration/cluster_mode_test.go
@@ -143,7 +143,7 @@ func TestClusterMode(t *testing.T) {
 						assert.NoError(t, wr.Err)
 
 						if wr.Type == client.PeersChanged {
-							peers := wr.PeersMapByDoc[d1.Key().BSONKey()]
+							peers := wr.PeersMapByDoc[d1.Key().CombinedKey()]
 							responsePairs = append(responsePairs, watchResponsePair{
 								Type:  wr.Type,
 								Peers: peers,
diff --git a/test/integration/history_test.go b/test/integration/history_test.go
new file mode 100644
index 00000000..2bde9dc2
--- /dev/null
+++ b/test/integration/history_test.go
@@ -0,0 +1,77 @@
+//go:build integration
+
+/*
+ * Copyright 2022 The Yorkie Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package integration
+
+import (
+	"context"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/yorkie-team/yorkie/pkg/document"
+	"github.com/yorkie-team/yorkie/pkg/document/proxy"
+	"github.com/yorkie-team/yorkie/test/helper"
+)
+
+func TestHistory(t *testing.T) {
+	clients := createActivatedClients(t, 2)
+	c1 := clients[0]
+	c2 := clients[1]
+	defer cleanupClients(t, clients)
+
+	t.Run("history test", func(t *testing.T) {
+		ctx := context.Background()
+
+		d1 := document.New(helper.Collection, t.Name())
+		assert.NoError(t, c1.Attach(ctx, d1))
+		defer func() { assert.NoError(t, c1.Detach(ctx, d1)) }()
+
+		assert.NoError(t, d1.Update(func(root *proxy.ObjectProxy) error {
+			root.SetNewArray("todos")
+			return nil
+		}, "create todos"))
+		assert.Equal(t, `{"todos":[]}`, d1.Marshal())
+
+		assert.NoError(t, d1.Update(func(root *proxy.ObjectProxy) error {
+			root.GetArray("todos").AddString("buy coffee")
+			return nil
+		}, "buy coffee"))
+		assert.Equal(t, `{"todos":["buy coffee"]}`, d1.Marshal())
+
+		assert.NoError(t, d1.Update(func(root *proxy.ObjectProxy) error {
+			root.GetArray("todos").AddString("buy bread")
+			return nil
+		}, "buy bread"))
+		assert.Equal(t, `{"todos":["buy coffee","buy bread"]}`, d1.Marshal())
+
+		assert.NoError(t, c1.Sync(ctx))
+
+		changes, err := c2.FetchHistory(ctx, d1.Key())
+		assert.NoError(t, err)
+		assert.Len(t, changes, 3)
+
+		assert.Equal(t, "create todos", changes[0].Message)
+		assert.Equal(t, "buy coffee", changes[1].Message)
+		assert.Equal(t, "buy bread", changes[2].Message)
+
+		assert.Equal(t, `{"todos":[]}`, changes[0].Snapshot)
+		assert.Equal(t, `{"todos":["buy coffee"]}`, changes[1].Snapshot)
+		assert.Equal(t, `{"todos":["buy coffee","buy bread"]}`, changes[2].Snapshot)
+	})
+}
diff --git a/test/integration/peer_awareness_test.go b/test/integration/peer_awareness_test.go
index 29fa86d8..4d43a9ce 100644
--- a/test/integration/peer_awareness_test.go
+++ b/test/integration/peer_awareness_test.go
@@ -74,7 +74,7 @@ func TestPeerAwareness(t *testing.T) {
 					}
 
 					if wr.Type == client.PeersChanged {
-						peers := wr.PeersMapByDoc[d1.Key().BSONKey()]
+						peers := wr.PeersMapByDoc[d1.Key().CombinedKey()]
 						responsePairs = append(responsePairs, watchResponsePair{
 							Type:  wr.Type,
 							Peers: peers,
diff --git a/yorkie/backend/db/memory/db_test.go b/yorkie/backend/db/memory/db_test.go
index 0e86446e..e703b1a5 100644
--- a/yorkie/backend/db/memory/db_test.go
+++ b/yorkie/backend/db/memory/db_test.go
@@ -91,7 +91,7 @@ func TestDB(t *testing.T) {
 
 		docInfo, err := memdb.FindDocInfoByKey(ctx, clientInfo, bsonDocKey, true)
 		assert.NoError(t, err)
-		assert.Equal(t, bsonDocKey, docInfo.Key)
+		assert.Equal(t, bsonDocKey, docInfo.CombinedKey)
 	})
 
 	t.Run("update clientInfo after PushPull test", func(t *testing.T) {
diff --git a/yorkie/backend/sync/memory/pubsub_test.go b/yorkie/backend/sync/memory/pubsub_test.go
index 5136eaff..5e419970 100644
--- a/yorkie/backend/sync/memory/pubsub_test.go
+++ b/yorkie/backend/sync/memory/pubsub_test.go
@@ -32,12 +32,12 @@ import (
 )
 
 func TestPubSub(t *testing.T) {
-	actorA := types.Client{ID: &time.ActorID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
-	actorB := types.Client{ID: &time.ActorID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}
+	actorA := types.Client{ID: time.ActorID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
+	actorB := types.Client{ID: time.ActorID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}
 
 	t.Run("publish subscribe test", func(t *testing.T) {
 		pubSub := memory.NewPubSub()
-		docKeys := []*key.Key{
+		docKeys := []key.Key{
 			{
 				Collection: helper.Collection,
 				Document:   t.Name(),
@@ -72,7 +72,7 @@ func TestPubSub(t *testing.T) {
 
 	t.Run("subscriptions map test", func(t *testing.T) {
 		pubSub := memory.NewPubSub()
-		docKeys := []*key.Key{
+		docKeys := []key.Key{
 			{
 				Collection: helper.Collection,
 				Document:   t.Name(),
@@ -86,7 +86,7 @@ func TestPubSub(t *testing.T) {
 			assert.NoError(t, err)
 
 			subs := pubSub.BuildPeersMap(docKeys)
-			assert.Len(t, subs[docKeys[0].BSONKey()], i+1)
+			assert.Len(t, subs[docKeys[0].CombinedKey()], i+1)
 		}
 	})
 }