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 이유진 연구원
Add comment