더이노베이터스

Progressive Json

1. Progressive JPEG처럼 JSON을 전송할 수 있을까?

Progressive JPEG은 이미지를 위에서 아래로 한 번에 로딩하는 대신, 처음에는 흐릿하게 전체를 보여주고 점점 선명해지는 방식입니다. 그렇다면 JSON 데이터도 같은 방식으로 전송할 수 있을까요?

일반적인 JSON 전송은 다음과 같습니다:

{
  header: '환영합니다.',
  post: {
    content: '내용',
    comments: ['댓글1', '댓글2']
  },
  footer: '감사합니다.'
}

하지만 JSON은 전체가 로드되고 나서야 파싱 가능하므로, 일부만 도착하면 아무것도 할 수 없습니다. 이는 사용자 경험에 좋지 않습니다.


2. Streaming JSON: 일부 데이터를 먼저 보여줄 수 있을까?

스트리밍 JSON 파서는 일부만 도착해도 미완성 객체를 반환합니다.

예시:

{
  header: '환영합니다.',
  post: {
    content: '내용',
    comments: ['댓글1']
  }
}

하지만 이 방식은 “뭐가 완료됐고, 뭐가 아직 안 왔는지”를 알 수 없어서 타입 안정성 부족불확실성이라는 문제가 생깁니다.


3. Progressive JSON: 해결책은 넓이 우선(Breadth-First) 스트리밍

원래 JSON이 로딩될 때는 깊이 우선 방식으로 데이터가 전송되었습니다. 이 대신 전체 JSON 구조를 먼저 스켈레톤 형태로 보내고, 세부 데이터를 나중에 스트리밍할 수도 있습니다:

{
  header: "$1",
  post: "$2",
  footer: "$3"
}

여기서 “$1”, “$2”, “$3” 은 아직 전송되지 않았으며, 플레이스홀더로 볼 수 있습니다. 이는 이후의 스트림에서 점진적으로 채워져 나갑니다 :

/* $1 */
"환영합니다."
/* $3 */
"감사합니다."
/* $2 */
{
  content: "$4",
  comments: "$5"
}
/* $4 */
"내용"
/* $5 */
["$6", "$7"]
/* $6 */
"댓글1"
/* $7 */
"댓글2"

클라이언트는 각 $id를 Promise로 처리해가며 전체 데이터를 점진적으로 구성해 나갈 수 있습니다.


4. Inlining과 Outlining

  • Inlining: 객체를 한 번만 사용할 경우 바로 넣기
  • Outlining: 중복되는 객체는 한 번만 정의하고 참조만 남기기
[
  { type: "header", user: "$1" },
  { type: "footer", user: "$1" }
]
/* $1 */
{ name: "Dan" }

이는 중복 제거 및 순환 참조(serializing cyclic objects) 처리에도 유용합니다.


5. React Server Components와의 관계

이 구조는 React Server Components(RSC)의 핵심 아이디어와 유사합니다. RSC는 컴포넌트 트리의 props를 밖에서 안으로(outside-in) 스트리밍하며, 각 부분은 <Suspense> 경계를 통해 의도적으로 로딩 상태를 제어합니다.

예시:

<Suspense fallback={<Loading />}>
  <Comments />
</Suspense>

이렇게 하면 React는 데이터를 가능한 빨리 스트리밍하지만, 시각적으로는 정해진 단계에 따라 점진적으로 보여주게 됩니다.


정리

  • 기존 JSON은 전부 다 와야 처리 가능
  • 스트리밍 JSON은 데이터 일부만 받아도 처리 가능하지만 불완전함
  • Progressive JSON은 구조를 먼저 보내고 내용을 이후에, Promise처럼 처리
  • React RSC는 Progressive JSON을 이용해 구조적 UI 스트리밍을 구현

TI Tech Lab 이유진 연구원

Source

Avatar

theinnovators

Add comment