From b0540b83fe1720ac5d338fd9073454ccb85e439b Mon Sep 17 00:00:00 2001 From: jiae Date: Wed, 7 Apr 2021 20:58:17 +0900 Subject: [PATCH] =?UTF-8?q?[#85]=20=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...74\353\235\274_\352\271\200\354\247\200\354\225\240.md" | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git "a/12\354\236\245/85_\354\236\220\353\260\224 \354\247\201\353\240\254\355\231\224\354\235\230 \353\214\200\354\225\210\354\235\204 \354\260\276\354\234\274\353\235\274_\352\271\200\354\247\200\354\225\240.md" "b/12\354\236\245/85_\354\236\220\353\260\224 \354\247\201\353\240\254\355\231\224\354\235\230 \353\214\200\354\225\210\354\235\204 \354\260\276\354\234\274\353\235\274_\352\271\200\354\247\200\354\225\240.md" index 8ac0e67..ccb009a 100644 --- "a/12\354\236\245/85_\354\236\220\353\260\224 \354\247\201\353\240\254\355\231\224\354\235\230 \353\214\200\354\225\210\354\235\204 \354\260\276\354\234\274\353\235\274_\352\271\200\354\247\200\354\225\240.md" +++ "b/12\354\236\245/85_\354\236\220\353\260\224 \354\247\201\353\240\254\355\231\224\354\235\230 \353\214\200\354\225\210\354\235\204 \354\260\276\354\234\274\353\235\274_\352\271\200\354\247\200\354\225\240.md" @@ -67,6 +67,7 @@ static byte[] bomb() { return serialize(root); // 간결하게 하기 위해 이 메서드의 코드는 생략함 } ``` + 이 객체 그래프는 201개의 HashSet 인스턴스로 구성되며, 그 각각은 3개 이하의 객체 참조를 갖는다. 스트림의 전체 크기는 5,744바이트지만, 역직렬화는 태양이 불타 식을 때까지도 끝나지 않을 것이다. 문제는 HashSet 인스턴스를 역직렬화하려면 그 원소들의 해시코드를 계산해야 한다는 데 있다. 루트 HashSet에 담긴 두 원소는 각각 (루트와 마찬가지로) 다른 HashSet 2개씩을 원소로 갖는 HashSet이다. 그리고 반복문에 의해 이 구조가 깊이 100단계까지 만들어진다. 따라서 이 HashSet을 역직렬화하려면 hashCode 메서드를 2^100 번 넘게 호출해야 한다. 역직렬화가 영원히 계속된다는 것도 문제지만, 무언가 잘못되었다는 신호조차 주지 않는 다는 것도 큰 문제다. 이 코드는 단 몇 개의 객체만 생성해도 스택 깊이 제한에 걸려버린다. 그렇다면 이 문제들을 어떻게 대처해야 할까? 애초에 신뢰할 수 없는 바이트스트림을 역직렬화하는 일 자체가 스스로를 공격에 노출하는 행위다. 따라서 직렬화 위험을 회피하는 일 자체가 스스로를 공격에 노출하는 행위다. 따라서 `직렬화 위험을 회피하는 가장 좋은 방법은 아무것도 역직렬화하지 않는 것이다.` @@ -80,6 +81,7 @@ static byte[] bomb() { ### 크로스 플랫폼의 대표주자 JSON과 프로토콜 버퍼 크로스-플랫폼 구조화된 데이터 표현의 선두주자는 JSON과 프로토콜 버퍼다. + #### JSON - JSON은 더글라스 크록퍼드가 브라우저와 서버의 통신용으로 설계 - 언어 중립적이지만 자바 스크립트용으로 만들어진 흔적이 있음 @@ -111,7 +113,7 @@ static byte[] bomb() { - 안타깝게도 직렬화는 여전히 자바 생태계 곳곳에 쓰이고 있다. 자바 직렬화를 사용하는 시스템을 관리해야 한다면 시간과 노력을 들여서라도 크로스-플랫폼 구조화된 데이터 표현으로 마이그레이션하는 것을 심각하게 고민해보길 바란다. - 하지만 현실적인 이유로 지금도 직렬화 가능 클래스를 작성하거나 유지보수해야 하는 사람도 있을 수 있다. 직렬화 가능 클래스를 올바르고 안전하고 효율적으로 작성하려면 상당한 주의가 필요하다. -## 핵심 정리 +### 핵심 정리 - 직렬화는 위험하니 피해야 한다. - 시스템을 밑바닥부터 설계하려면 JSON이나 프로토콜버퍼같은 대안을 사용하자. 신뢰할 수 없는 데이터는 역직렬화하지 말자. @@ -119,4 +121,5 @@ static byte[] bomb() { - 클래스가 직렬화를 지원하도록 만들지 말고, 꼭 그렇게 만들어야 한다면 정말 신경써서 작성해야 한다. ### 참고 자료 -- Effective Java 3/E \ No newline at end of file +- Effective Java 3/E +- [rpc vs json 비교 추천글](https://github.com/jiaekim123/posting-review/blob/master/jiaekim/2021-03-18-grpc.md)