diff --git "a/12\354\236\245/90_\354\247\201\353\240\254\355\231\224\353\220\234_\354\235\270\354\212\244\355\204\264\354\212\244_\353\214\200\354\213\240_\354\247\201\353\240\254\355\231\224_\355\224\204\353\241\235\354\213\234_\354\202\254\354\232\251\354\235\204_\352\262\200\355\206\240\355\225\230\353\235\274_\352\271\200\353\263\264\353\260\260.md" "b/12\354\236\245/90_\354\247\201\353\240\254\355\231\224\353\220\234_\354\235\270\354\212\244\355\204\264\354\212\244_\353\214\200\354\213\240_\354\247\201\353\240\254\355\231\224_\355\224\204\353\241\235\354\213\234_\354\202\254\354\232\251\354\235\204_\352\262\200\355\206\240\355\225\230\353\235\274_\352\271\200\353\263\264\353\260\260.md"
new file mode 100644
index 0000000..39f3280
--- /dev/null
+++ "b/12\354\236\245/90_\354\247\201\353\240\254\355\231\224\353\220\234_\354\235\270\354\212\244\355\204\264\354\212\244_\353\214\200\354\213\240_\354\247\201\353\240\254\355\231\224_\355\224\204\353\241\235\354\213\234_\354\202\254\354\232\251\354\235\204_\352\262\200\355\206\240\355\225\230\353\235\274_\352\271\200\353\263\264\353\260\260.md"
@@ -0,0 +1,189 @@
+
+
+# 아이템 90. 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라
+
+Serializable을 구현하기로 결정한 순간, 언어의 생성자 이외의 방법으로도 인스턴스를 생성할 수 있게 된다.
+
+
+- 이전 아이템에서도 계속 언급되지만, 버그 및 보안 문제가 일어날 가능성이 커진다.
+
+직렬화 프록시 패턴 (Serialization Proxy Pattern)을 이용하면 이러한 위험을 크게 줄여줄 수 있다.
+
+- 직렬화 프록시는 일반적으로 이전 아이템에서 나온 `readObject` 의 방어적 복사보다 강력하다.
+
+## 직렬화 프록시 패턴
+
+```java
+class Period implements Serializable {
+ // 불변 가능
+ private final Date start;
+ private final Date end;
+
+ public Period(Date start, Date end) {
+ this.start = start;
+ this.end = end;
+ }
+
+ private static class SerializationProxy implements Serializable {
+ private static final long serialVersionUID = 2123123123;
+ private final Date start;
+ private final Date end;
+
+ public SerializationProxy(Period p) {
+ this.start = p.start;
+ this.end = p.end;
+ }
+
+ // Deserialize -> Object 생성
+ private Object readResolve() {
+ return new Period(start, end);
+ }
+ }
+
+ // Serialize -> 프록시 인스턴스 반환
+ // 결코 바깥 클래스의 직렬화된 인스턴스를 생성해낼 수 없다
+ private Object writeReplace() {
+ return new SerializationProxy(this);
+ }
+
+ // Period 자체의 역직렬화를 방지 -> 역직렬화 시도시, 에러 반환
+ private void readObject(ObjectInputStream stream) throws InvalidObjectException {
+ throw new InvalidObjectException("프록시가 필요해요.");
+ }
+}
+```
+
+
+
+```java
+// Period
+private Object writeReplace() {
+ return new SerializationProxy(this);
+}
+```
+
+- Serialize -> 프록시 인스턴스 반환
+- 결코 바깥 클래스의 직렬화된 인스턴스를 생성해낼 수 없다
+
+
+
+
+```java
+// Period
+private void readObject(ObjectInputStream stream) throws InvalidObjectException {
+ throw new InvalidObjectException("프록시가 필요해요.");
+}
+```
+
+- Period 자체의 역직렬화를 방지 -> 역직렬화 시도시, 에러 반환
+
+
+
+
+```java
+// SerializationProxy
+private Object readResolve() {
+ return new Period(start, end);
+}
+```
+
+- Deserialize -> Object 생성
+- 공개된 API 만을 사용해 바깥 클래스의 인스턴스를 생성 → 생성자, 정적 팩터리 등을 통해 인스턴스를 생성 및 반환이 가능하다!
+ - 즉, 아이템 88에서 나오는 것처럼 불변식을 검사하는 수단이 필요가 없다!
+ - 생성자, 정적 팩터리 메서드에서 불변식 검사를 잘 해주고 있다면.
+
+
+
+
+
+---
+
+## 역직렬화한 인스턴스와 원래의 직렬화된 인스턴스의 클래스가 달라도 정상 작동한다
+
+말이 너무 어렵다....
+
+→ 쉽게 말하면,
+
+- A 클래스의 인스턴스를 직렬화했다.
+- 그 데이터를 가지고 역직렬화를 수행해 B 클래스의 인스턴스를 만들었다. (역직렬화 했다)
+- 근데 정상작동한다 !
+
+처음엔, 이해도 잘 안되고... 이게 왜...? 라는 생각이 들었다.
+
+
+
+예를 보자.
+
+### EnumSet (Item 36)
+
+`EnumSet`은 생성자 없이 정적 팩터리들만 제공
+
+- 단순히 생각하면 `EnumSet` 인스턴스를 반환하는 것 같지만, 열거 타입의 크기에 따라 다르다.
+- 열거 타입의 원소의 개수가
+ - 64개 이하면, `RegularEnumSet` 을 반환
+ - 그보다 크면, `JumboEnumSet` 을 반환
+
+
+![1](https://user-images.githubusercontent.com/37873745/113861202-e6c46b00-97e1-11eb-9806-20c405d4d4a1.png)
+
+
+
+### 시나리오
+
+- 63개의 열거타입을 가진 EnumSet이 있다.
+- 이를 직렬화하자.
+- 그리고 원소 5개를 추가해 역직렬화하자.
+
+
+당연히 처음엔 `RegularEnumSet` 인스턴스 였다가, 나중엔 `JumboEnumSet` 로 하는 것이 더 효율적이고 좋을 것이다.
+
+- 직렬화 프록시를 이용하면, 원하는 방향대로 사용이 가능하다.
+- 아래는 `EnumSet` 의 실제 코드 - 직렬화 프록시 패턴을 이용
+
+```java
+private static class SerializationProxy > implements java.io.Serializable
+{
+ // EnumSet의 원소 타입
+ private final Class elementType;
+
+ // EnumSet 내부 원소
+ private final Enum>[] elements;
+
+ SerializationProxy(EnumSet set) {
+ elementType = set.elementType;
+ elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY);
+ }
+
+ // 새롭게 원소의 크기에 맞는 EnumSet 생성
+ @SuppressWarnings("unchecked")
+ private Object readResolve() {
+ EnumSet result = EnumSet.noneOf(elementType);
+ for (Enum> e : elements)
+ result.add((E)e);
+ return result;
+ }
+
+ private static final long serialVersionUID = 362491234563181265L;
+}
+
+Object writeReplace() {
+ return new SerializationProxy<>(this);
+}
+
+private void readObject(java.io.ObjectInputStream stream)
+ throws java.io.InvalidObjectException {
+ throw new java.io.InvalidObjectException("Proxy required");
+}
+```
+
+
+
+## 직렬화 프록시 패턴의 한계
+
+1. 클라이언트 멋대로 확장할 수 있는 클래스에는 적용할 수 없다.
+
+2. 객체 그래프에 순환이 있는 클래스에는 적용할 수 없다.
+
+3. (책엔 한계라고 적혀있지는 않지만) 속도가 느리다
+
+- 책에서 말하길, `Period` 예제의 경우 방어적 복사를 사용하는 것보다 14% 느려졌다고 한다.
\ No newline at end of file