로블록스 Studio에서 모델이 사라질 때: StreamingEnabled·Atomic 점검법
서버 Explorer에는 모델이 있는데 클라이언트에서 nil이거나, 멀리 갔다 돌아오자 문·NPC·소리가 사라지는 증상은 복제 오류가 아니라 인스턴스 스트리밍의 정상 동작일 수 있습니다. 모든 모델을 Persistent로 바꾸거나 반경을 크게 늘리기 전에 “아직 들어오지 않음”, “이미 빠져나감”, “처음부터 클라이언트에 필요 없음”을 구분해야 메모리 이점을 잃지 않고 고칠 수 있습니다.
2026년 10월 9일 Windows 데스크톱 브라우저에서 Roblox Creator Hub의 Instance streaming 기술 문서와 Techniques and conversion, Player·Workspace·Model API, Studio testing modes를 대조했습니다. “서버에는 있는데 클라이언트에는 없다”는 현상을 초기 미복제, stream out, 로컬 전용 변경으로 나누고, 각 상태에 맞는 Script와 ModelStreamingMode 선택 순서를 다시 구성했습니다. 실제 Roblox Studio Place에서 StreamingEnabled를 켜거나 저메모리 기기·다중 클라이언트·먼 거리 순간이동을 실행하지는 않았습니다. 아래 코드는 공식 동작을 설명하기 위한 뼈대이며, 소유한 테스트 Place에서 거리·메모리·네트워크 조건을 바꾸어 검증해야 합니다.
1. 모델이 없는 순간을 세 상태로 구분합니다
Explorer에서 보이지 않는다는 결과만으로 원인을 정하면 모든 해결책이 “WaitForChild를 더 붙이기” 또는 “Persistent로 바꾸기”가 됩니다. 먼저 언제 없었는지 기록하세요.
| 상태 | 보이는 현상 | 우선 확인 |
|---|---|---|
| 아직 stream in 전 | 입장 직후 먼 모델이 없고 가까이 가면 생김 | 거리, ModelStreamingMode, WaitForChild 위치 |
| stream out 뒤 | 처음에는 있었지만 멀어진 뒤 Parent가 nil이 되거나 이벤트가 다시 발생 | 오래 보관한 참조, 로컬 속성 변경, 재연결 로직 |
| 클라이언트가 볼 필요 없는 서버 객체 | ServerStorage·ServerScriptService 객체가 클라이언트에 없음 | 잘못된 컨테이너 기대, RemoteEvent 경계 |
| 로컬에서만 바꾼 서버 객체 | 클라이언트 삭제·이동·속성 변경이 다시 원래대로 보임 | 서버 소유 객체를 LocalScript에서만 변경했는지 |
공식 문서에 따르면 instance가 stream out될 때 일반적인 Destroy()와 같은 방식으로 완전히 파괴되는 것이 아니라 nil 아래로 이동합니다. 부모와 조상의 ChildRemoved·DescendantRemoving 신호는 발생하지만, 같은 instance가 다시 들어오면 기존 Luau 상태가 재연결될 수 있습니다. 그래서 “없어졌으니 영구 삭제됐다”와 “현재 클라이언트 영역에서 빠졌다”를 구분해야 합니다.
2. 스트리밍은 Workspace 자손에만 적용됩니다
StreamingEnabled는 Workspace의 3D 콘텐츠를 동적으로 복제·해제하는 기능입니다. ReplicatedStorage와 ReplicatedFirst 같은 다른 컨테이너의 객체는 instance streaming 대상이 아닙니다. Atomic 모델을 ReplicatedStorage에 두었다고 해서 그 컨테이너 안 복제가 Atomic 규칙을 따르는 것도 아닙니다.
- Workspace: BasePart와 관련 모델이 거리·설정·기기 상태에 따라 들어오고 나갈 수 있습니다.
- ReplicatedStorage: 클라이언트와 서버가 함께 쓰는 비공간 설정·모듈·RemoteEvent에 적합하지만, 넣는 것마다 클라이언트 메모리를 사용합니다.
- ServerStorage·ServerScriptService: 클라이언트에 복제되지 않는 서버 전용 영역입니다.
- ReplicatedFirst: 로딩 초기에 필요한 제한된 클라이언트 콘텐츠를 위한 영역이지, 거대한 맵을 스트리밍에서 제외하는 우회 수단이 아닙니다.
“사라지지 않게 하려고” 큰 맵을 ReplicatedStorage로 옮기면 스트리밍의 메모리·입장 속도 이점을 잃습니다. 위치가 있는 세계 객체는 Workspace에 두고 LocalScript를 스트리밍에 맞게 고치는 것이 기본입니다. 게임 규칙을 결정하는 비공개 원본은 서버에 두고, 클라이언트에는 필요한 결과만 전달합니다.
Workspace.StreamingEnabled는 새 Place에서 기본 활성화되어 있으며 Script에서 바꾸는 속성이 아닙니다. Studio의 Workspace Properties에서 확인해야 합니다. 실행 중 코드로 켰다 껐다 하며 증상을 비교하는 방법은 사용할 수 없습니다.
3. 점 연산자·FindFirstChild·WaitForChild의 역할이 다릅니다
공식 스트리밍 Techniques 문서는 Workspace 자손을 점 연산자로 바로 찾으면 경로 중 하나가 아직 들어오지 않았을 때 오류가 나고, FindFirstChild() 계열은 같은 상황에서 nil을 돌려준다고 설명합니다. 무엇을 쓸지는 “없어도 진행 가능한가”로 결정합니다.
| 상황 | 패턴 | 실패 처리 |
|---|---|---|
| 이 모델 없이는 화면을 만들 수 없음 | WaitForChild(name, timeout) | 시간 초과 UI·재시도·기능 중단을 명시 |
| 모델이 없으면 해당 효과만 생략 가능 | FindFirstChild() + nil 검사 | 조용히 건너뛰거나 다음 stream in 신호 대기 |
| Atomic 모델의 초기 자손 | 모델만 WaitForChild, 초기 자손은 직접 접근 가능 | 실행 중 추가된 자손은 별도 대기 |
| 게임 판정에 세계 전체가 필요 | 서버 Script에서 계산 | 클라이언트 Workspace만으로 판정하지 않음 |
-- StarterPlayerScripts의 LocalScript 예시
local Workspace = game:GetService("Workspace")
local house = Workspace:WaitForChild("House1", 10)
if not house then
warn("House1이 10초 안에 stream in되지 않았습니다")
return
end
-- House1이 Atomic이고 Door가 초기 자손이라면 모델 도착 때 함께 존재합니다.
local door = house:FindFirstChild("Door")
if not door then
warn("초기 구조가 예상과 다릅니다")
return
end
timeout 없는 WaitForChild는 대상이 범위 안으로 들어오지 않는 동안 무기한 멈출 수 있습니다. 화면 전체 초기화 coroutine이 여기서 멈추면 스트리밍 문제 하나가 다른 UI까지 멈춘 것처럼 보입니다. 필수 대상에도 합리적인 timeout과 실패 상태를 두고, 재시도 버튼이나 대상 근처 이동 같은 복구 경로를 제공합니다.
RemoteEvent 인수로 Workspace instance를 보내도 수신 클라이언트에 그 instance가 아직 복제되지 않았다면 안전하게 사용할 수 있다고 가정할 수 없습니다. 필요한 경우 식별자·좌표 같은 데이터만 보내고 클라이언트가 대상을 기다리거나, 서버가 목적지 주변을 먼저 요청한 뒤 이벤트를 보냅니다. 서버 요청 자체도 전체 콘텐츠 도착을 절대 보장하지 않으므로 nil 처리는 남겨 둡니다.
4. Nonatomic과 Atomic은 “한꺼번에 필요하냐”로 선택합니다
모델의 기본 스트리밍 모드는 Nonatomic입니다. Workspace의 ModelStreamingBehavior가 Legacy이면 Model 컨테이너와 Script 같은 비-BasePart 자손이 먼저 복제되고 BasePart는 나중에 들어올 수 있습니다. Improved에서는 BasePart를 가진 Nonatomic 모델이 해당 BasePart가 들어올 때 모델·비-BasePart 자손과 함께 들어오며, 마지막 BasePart가 나가면 모델도 나갑니다.
한편 Atomic은 모델의 한 BasePart가 들어올 자격을 얻었을 때 초기 자손 전체를 함께 보냅니다. 문 모델의 힌지·클릭 영역·표시 Part를 항상 한 세트로 써야 한다면 Atomic이 적합합니다. 클라이언트는 Atomic 모델 자체가 들어올 때까지 기다려야 하지만, 들어온 뒤 초기 자손 하나하나에 WaitForChild를 반복할 필요는 줄어듭니다.
| 선택 | 적합한 예 | 주의 |
|---|---|---|
| Nonatomic | 큰 건물·지형처럼 일부 Part만 보여도 되는 구조 | 클라이언트가 일부 자손 부재를 견뎌야 함 |
| Atomic | 한 세트로 있어야 하는 문·퍼즐·차량 하위 시스템 | 모델 전체가 함께 들어오므로 단위가 너무 크면 비용 증가 |
| Persistent | 소수의 전역 기준점처럼 항상 필요한 모델 | 절대 stream out되지 않아 메모리를 계속 차지 |
| PersistentPerPlayer | 특정 플레이어에게만 항상 필요한 개인 플롯 등 | 추가·제거 대상 관리와 인원 증가 비용 필요 |
Atomic 보장은 최초 복제 시점의 자손에 적용됩니다. 모델이 클라이언트에 들어온 뒤 서버가 새 Part를 추가하면 그 Part까지 자동으로 초기 세트처럼 동기 도착한다고 가정할 수 없습니다. 동적 자손은 ChildAdded, WaitForChild와 nil 검사 등 별도 경로로 처리합니다.
Atomic 안에 Persistent 모델을 깊게 중첩하면 바깥 모델까지 사실상 항상 남는 구조가 될 수 있습니다. 스트리밍 문서는 계층을 평평하게 유지하라고 권합니다. 모드 이름으로만 관리하지 말고 실제 부모·자손 관계까지 확인하세요.
5. Persistent는 마지막 수단으로 최소화합니다
Persistent 모델은 일반적인 stream in/out 대상이 아니며, 플레이어 입장 뒤 완전한 Atomic 단위로 전송되고 Workspace.PersistentLoaded 이벤트 전에 준비됩니다. 이후 stream out되지 않습니다. 이 특성은 편리하지만, 모든 이용자의 클라이언트 메모리에 계속 남는다는 뜻입니다.
- 항상 참조해야 하는 소수의 세계 기준점인지 확인합니다.
- 서버 Script로 옮기면 클라이언트 상시 참조가 필요 없어지는지 먼저 봅니다.
- Atomic + 적절한 WaitForChild로 해결되는 모델인지 비교합니다.
- PersistentLoaded 전에 접근하는 초기화 코드가 없는지 확인합니다.
- 모델 안 텍스처·Mesh·Sound까지 포함한 실제 메모리 비용을 저사양 기기에서 측정합니다.
DataModel.Loaded가 발생했다고 Persistent 모델이 모두 왔다는 뜻은 아닙니다. Workspace API는 경험 로딩이 persistent loading보다 먼저 끝날 수 있다고 명시합니다. Persistent 모델이 필요한 LocalScript는 PersistentLoaded를 기준으로 초기화해야 합니다.
PersistentPerPlayer는 서버에서 Model:AddPersistentPlayer()로 추가된 이용자에게만 Persistent처럼 동작하고, 다른 이용자에게는 Atomic처럼 동작합니다. 플레이어 전용 집·퀘스트 장소처럼 대상이 제한된 경우 검토할 수 있지만, 떠난 이용자와 상태 변경 시 RemovePersistentPlayer()까지 대칭적으로 관리해야 합니다.
6. stream out은 삭제 이벤트가 아니라 상태 재검증 신호입니다
instance가 빠질 때 Parent가 nil이 되고 부모의 removal 신호가 발생할 수 있습니다. 그 객체를 Lua 변수에 오래 보관했다면 변수 자체가 nil이 되지 않아도 현재 Workspace에 존재하지 않을 수 있습니다. 속성을 읽기 전에 FindFirstAncestorWhichIsA("Workspace") 같은 확인으로 현재 세계에 붙어 있는지 검사할 수 있습니다.
local function isCurrentlyInWorld(instance)
return instance
and instance:FindFirstAncestorWhichIsA("Workspace") ~= nil
end
if isCurrentlyInWorld(targetPart) then
-- 현재 클라이언트 Workspace에 존재할 때만 로컬 효과 처리
end
클라이언트에서만 바꾼 서버 소유 instance 속성은 stream out 뒤 다시 들어올 때 사라질 수 있습니다. 예를 들어 LocalScript가 문 색을 직접 바꿨지만 서버에는 기록하지 않았다면, 다시 stream in된 문은 서버 원본 상태를 받을 수 있습니다. 게임에 영향을 주는 상태는 서버를 원본으로 두고, 클라이언트 효과는 재진입 때 다시 적용할 수 있게 설계하세요.
클라이언트가 서버 소유 객체를 Destroy()하거나 ReplicatedStorage에서 Workspace로 로컬 이동한 상태도 서버와 어긋납니다. 서버는 원본을 계속 가지고 있으므로 객체가 다시 나타나거나 업데이트를 받지 않는 로컬 복사본이 남을 수 있습니다. 스트리밍 호환성 문서는 이런 클라이언트 전용 삭제·이동을 표준 설계로 쓰지 말라고 경고합니다.
CollectionService 태그로 스트리밍 객체를 초기화한다면 GetInstanceAddedSignal()과 제거 신호를 한 쌍으로 처리합니다. 다시 들어온 NPC에서 등장 효과가 매번 재생되지 않게 서버 Attribute로 “실제 최초 생성”과 “클라이언트 재진입”도 구분합니다.
7. 먼 곳으로 PivotTo하기 전에 목적지를 선로딩합니다
캐릭터를 CFrame 또는 PivotTo로 먼 위치로 즉시 옮기면 목적지 지형이 아직 없어서 플레이가 일시 정지되거나 빈 공간처럼 보일 수 있습니다. 서버는 이동 직전에 Player:RequestStreamAroundAsync(position, timeout)를 호출해 목적지 주변 전송을 요청할 수 있습니다.
-- ServerScriptService의 Script 예시
local function moveCharacterAfterPrefetch(player, targetCFrame)
local ok, errorMessage = pcall(function()
player:RequestStreamAroundAsync(targetCFrame.Position, 8)
end)
if not ok then
warn("목적지 스트리밍 요청 실패", errorMessage)
return false
end
local character = player.Character
if not character or not character.Parent then
return false
end
character:PivotTo(targetCFrame)
return true
end
이 호출은 yield하며 효과가 일시적입니다. API 문서는 요청 위치 주변에 무엇이 들어올지 완전히 보장하지 않고, 클라이언트 메모리와 네트워크 조건이 결과에 영향을 준다고 명시합니다. timeout을 생략하면 사실상 무기한 기다릴 수 있지만 저메모리 상태에서는 제한 시간 안이어도 요청이 중단될 수 있습니다. 운영 코드에는 유한한 timeout, 실패 UI와 이동 취소·재시도 경로를 둡니다.
선로딩 성공을 “목적지의 모든 문·NPC가 존재함”으로 해석하지 마세요. RequestStreamAroundAsync가 돌아온 뒤에도 중요한 Atomic 모델이나 대상 instance를 확인하고, 없으면 안전한 대기 위치에 머물거나 사용자에게 다시 시도하도록 안내합니다.
클라이언트가 전송한 targetCFrame을 서버가 그대로 믿는 구조는 스트리밍보다 먼저 보안 문제가 됩니다. 서버가 허용한 목적지 ID를 좌표로 변환하고, 거리·권한·상태를 검증한 뒤 선로딩과 이동을 수행합니다. 원격 호출의 서버 검증은 RemoteEvent 서버 검증 점검법을 함께 적용하세요.
8. 잠깐 볼 곳과 계속 볼 곳은 다른 API를 씁니다
RequestStreamAroundAsync는 곧 이동할 목적지처럼 일시적인 선로딩에 적합합니다. 집과 거래 허브를 동시에 유지하거나 망원경으로 먼 기지를 계속 보여 주는 것처럼 일정 기간 다른 영역도 유지해야 한다면 서버에서 Player:AddReplicationFocus(part)를 제한적으로 사용할 수 있습니다.
- 일시 목적지: RequestStreamAroundAsync 후 이동합니다.
- 일정 시간 유지할 두 번째 영역: AddReplicationFocus로 추가하고 필요가 끝나면 RemoveReplicationFocus합니다.
- 모든 플레이어에게 항상 필요한 작은 모델: Persistent를 비교합니다.
- 특정 플레이어에게만 항상 필요한 작은 모델: PersistentPerPlayer를 비교합니다.
추가 focus는 기본 focus와 같은 StreamingMinRadius·StreamingTargetRadius를 사용합니다. focus를 많이 만들면 저메모리 기기에서 엔진이 메모리를 조절할 여지가 줄어 운영체제가 클라이언트를 종료할 가능성이 커질 수 있습니다. 추가·제거 시점을 로그로 남기고 플레이어 퇴장·관전 종료·카메라 전환 때 반드시 정리하세요.
AddReplicationFocus와 RemoveReplicationFocus는 서버에서 호출해야 하며 LocalScript에서 호출해도 효과가 없습니다. 카메라가 먼 곳을 본다는 이유만으로 자동 focus가 생긴다고 가정하지 말고, 정말 장기 유지가 필요한 기능만 서버에 요청합니다.
9. Raycast와 상호작용은 클라이언트에 들어온 세계만 봅니다
클라이언트의 Raycast, GetPartBoundsInBox, Model:GetBoundingBox 같은 공간 질의는 현재 stream in된 콘텐츠만 반영합니다. 근처 발자국 효과처럼 로컬 영역만 필요한 질의라면 문제없지만, 먼 적과의 시야 판정이나 보상·피격 판정처럼 전체 세계가 필요한 결과를 클라이언트에 맡기면 빠진 장애물을 없는 것으로 판단할 수 있습니다.
| 기능 | 클라이언트에 대상이 없을 때 | 안전한 설계 |
|---|---|---|
| 먼 거리 Raycast 시야 판정 | 아직 안 들어온 벽을 통과할 수 있음 | 서버에서 최종 판정 |
| Atomic 모델 BoundingBox | 모델 자체가 없으면 계산 불가 | 모델 도착을 기다린 뒤 초기 자손 전체 기준 계산 |
| Touched·ProximityPrompt | 연결된 Part가 없으면 해당 이용자에게 작동하지 않음 | 일반 접근 거리라면 자연스러운 stream in, 원거리 필수면 다른 UI/서버 경로 |
| 3D Sound | 부모 3D 객체가 빠지면 소리도 멈춤 | 항상 필요한 환경음만 비스트리밍 컨테이너 또는 작은 Persistent 모델 검토 |
상호작용을 “맵 어디서든 누를 수 있어야 한다”는 이유로 거대한 모델 전체를 Persistent로 바꾸기 전에, 화면 목록·서버 명령·좌표 기반 표시처럼 공간 객체와 분리된 인터페이스를 검토하세요. 스트리밍 이점은 유지하면서 원거리 기능을 제공할 수 있습니다.
10. 반경을 키우기보다 무결성·버퍼·메모리를 함께 봅니다
StreamingMinRadius는 focus 주변에서 가장 높은 우선순위로 들어오는 영역이고, 그 안의 영역은 stream out되지 않습니다. StreamingTargetRadius는 추가 콘텐츠를 받을 최대 거리의 기준입니다. 공식 권장 기본값은 각각 64와 1024이며, Target은 Min보다 커야 중간 버퍼가 생깁니다.
nil 오류를 없애려고 두 값을 크게 올리면 서버 대역폭과 클라이언트 메모리를 더 사용하고 저사양 기기의 적응 폭이 줄어듭니다. 먼저 Script의 존재 가정, 모델 단위, 순간이동 선로딩을 고친 뒤 실제 측정으로 반경을 조정하세요.
- ModelStreamingBehavior: BasePart를 포함한 Nonatomic 모델에는 Improved가 효율적인 권장값입니다.
- StreamOutBehavior: Opportunistic은 Target 밖 콘텐츠를 메모리 압박 전에도 적극 해제해 메모리 사용을 낮추는 권장값입니다.
- StreamingIntegrityMode: PauseOutsideLoadedArea는 캐릭터가 아직 로드되지 않은 영역으로 움직일 때 게임플레이를 일시 정지하는 권장값입니다.
- PredictiveStreamingMode: 스폰 위치와 최근 떠난 위치 같은 예상 영역을 임시 선로딩하지만 게임 로직의 존재 보장을 대신하지 않습니다.
게임이 정지될 때 Player.GameplayPaused를 LocalScript에서 관찰해 자체 안내 UI를 보여 줄 수 있습니다. 기본 알림을 끄고 커스텀 UI를 쓴다면 연결 끊김처럼 오해하지 않도록 “지역 불러오는 중”, 취소·복귀 방법과 장시간 지속 시 재접속 안내를 제공합니다.
11. Server & Clients와 스트리밍 디버그 화면으로 재현합니다
Edit 화면에 모델이 보인다는 사실은 클라이언트 테스트가 아닙니다. Studio의 Test 또는 Test Here는 client와 server를 따로 실행하므로 Client/Server 전환으로 같은 순간의 Explorer를 비교하세요. 더 확실한 비교가 필요하면 Server & Clients에서 1~2개 클라이언트를 띄워 각자 다른 위치에 놓습니다.
- Workspace에서 StreamingEnabled와 관련 속성 값을 기록합니다.
- Client 1은 스폰에 두고 Client 2는 먼 지역으로 이동시킵니다.
- Server Explorer에는 존재하지만 각 Client Explorer에서 다른 모델이 보이는지 확인합니다.
- Output의 파란 클라이언트 메시지와 초록 서버 메시지를 나눠 nil 오류 발생 주체를 찾습니다.
- 가까이 갔을 때 stream in, 멀어졌을 때 stream out, 다시 왔을 때 상태 복구를 확인합니다.
- 먼 목적지 PivotTo 전에 RequestStreamAroundAsync를 적용한 경우와 생략한 경우를 비교합니다.
- Persistent 수를 늘리기 전후 클라이언트 메모리와 입장 시간을 저사양 기기에서 측정합니다.
런타임 스트리밍 상태는 공개 게임에서 Shift+F3, Studio 플레이 테스트에서 Windows 기준 Shift+Ctrl+F3으로 Network Stats를 열고 Shift+1을 반복해 네 번째 Streaming 패널로 이동해 볼 수 있습니다. 활성 설정, 로드된 영역과 상태를 확인하고, 필요하면 디버깅 중에만 카메라 최대 줌 거리를 늘려 색상 영역을 살핍니다.
한 번 가까이 갔던 고성능 PC에서는 콘텐츠가 메모리에 오래 남아 문제가 재현되지 않을 수 있습니다. StreamOutBehavior가 LowMemory이면 실제 저메모리 상황 전까지 빠지지 않을 수 있으므로, 재접속·다른 기기·Opportunistic 테스트를 포함하고 운영 설정은 결과를 기록한 뒤 결정하세요.
12. 증상별 첫 확인 지점
| 증상 | 가능성 높은 원인 | 첫 확인 |
|---|---|---|
attempt to index nil | LocalScript가 아직 없는 Workspace 자손을 점 연산자로 접근 | WaitForChild timeout 또는 FindFirstChild 분기 |
| 문 모델의 일부 Part만 있음 | 큰 Nonatomic 모델의 부분 스트리밍 | 논리 단위를 작은 Atomic 모델로 묶을지 |
| 입장 직후 Persistent 모델이 없음 | DataModel.Loaded만 기다림 | Workspace.PersistentLoaded 기준 초기화 |
| 멀리 갔다 돌아오면 색·효과 초기화 | 로컬 전용 변경이 stream out 뒤 손실 | 서버 원본 상태와 재진입 적용 함수 |
| 순간이동 뒤 빈 공간·일시 정지 | 목적지 선로딩 전 CFrame 이동 | 서버 RequestStreamAroundAsync + 유한 timeout |
| 망원경에서 먼 기지 물리가 멈춤 | 카메라만 이동하고 replication focus 없음 | 제한된 AddReplicationFocus와 제거 시점 |
| 원거리 Raycast가 벽을 무시 | 클라이언트에 벽이 stream in되지 않음 | 서버 최종 질의 |
| Persistent로 바꾼 뒤 저사양 종료 증가 | 항상 남는 모델·자산이 많음 | Persistent 최소화와 메모리 측정 |
| WaitForChild가 영원히 끝나지 않음 | 대상이 범위에 들어오지 않거나 이름·부모가 잘못됨 | timeout, 실패 UI, 서버 경로·좌표 검증 |
증상을 고칠 때 반경, 모델 모드, Script를 동시에 바꾸지 마세요. 한 번에 하나씩 변경하고 client Explorer·Output·Streaming 패널에서 어떤 상태가 바뀌었는지 기록해야 해결책이 메모리 문제를 새로 만들지 않았는지 판단할 수 있습니다.
13. 공개 전 점검표
- StreamingEnabled가 켜진 실제 client simulation에서 테스트했습니다.
- Workspace 자손과 ReplicatedStorage·ServerStorage의 역할을 구분했습니다.
- LocalScript의 점 연산자 경로를 WaitForChild timeout 또는 nil 검사로 바꿨습니다.
- 일부만 있어도 되는 큰 구조는 Nonatomic, 한 세트로 필요한 작은 구조는 Atomic으로 구분했습니다.
- Atomic 최초 자손과 실행 중 추가 자손의 도착 규칙을 구분했습니다.
- Persistent·PersistentPerPlayer를 꼭 필요한 작은 모델에만 사용했습니다.
- stream out 뒤 로컬 상태를 다시 적용하거나 서버 원본에서 복구합니다.
- 먼 순간이동 전에 서버에서 유한 timeout으로 선로딩하고 실패 경로를 처리합니다.
- 추가 replication focus를 제한하고 기능 종료·퇴장 때 제거합니다.
- 보상·피격·시야 같은 전체 세계 판정은 서버에서 검증합니다.
- TargetRadius가 MinRadius보다 크고 반경 확대 전 메모리·대역폭을 측정했습니다.
- Client/Server Explorer, Output, Streaming 디버그 패널로 재진입까지 확인했습니다.
- 고성능 PC 한 번이 아니라 저사양 기기·재접속·먼 거리 왕복을 포함했습니다.
공식 출처·갱신일·적용 범위
아래 Roblox Creator Hub 1차 자료를 2026년 10월 9일 공개 HTML과 Markdown 원문으로 확인했습니다. Markdown 메타데이터의 last_updated는 Instance streaming과 Techniques 문서가 2026년 10월 8일 21:44:08 UTC, Player·Model API가 21:43:58 UTC, Workspace API가 21:43:59 UTC, ModelStreamingMode가 21:44:00 UTC, Studio testing modes가 21:44:03 UTC로 표시됐습니다. 이는 기능 최초 출시일이 아니라 문서 최종 갱신 시각입니다.
- Instance streaming — Workspace 범위, stream in/out, 반경·무결성 설정, replication focus, Nonatomic·Atomic·Persistent·PersistentPerPlayer와 디버그 화면을 확인했습니다.
- Streaming techniques and conversion — WaitForChild·nil 검사, Atomic 초기 자손, 클라이언트 전용 변경, 선로딩, 공간 질의와 상호작용 호환성 절차를 확인했습니다.
- Player.RequestStreamAroundAsync — 일시 선로딩, yield, timeout, 저메모리 중단과 비보장 범위를 확인했습니다.
- Workspace.PersistentLoaded — 일반 경험 로딩과 Persistent 모델 준비 완료가 다르다는 점을 확인했습니다.
- Model.ModelStreamingMode 및 ModelStreamingMode — 모델별 스트리밍 모드와 클라이언트 자손 존재 보장의 범위를 확인했습니다.
- Studio testing modes — Client/Server 전환, Server & Clients 다중 세션과 Output 출처 구분을 확인했습니다.
적용 범위: StreamingEnabled가 활성화된 Roblox Studio Place에서 클라이언트가 Workspace 모델을 찾지 못하거나 stream out 뒤 상태가 어긋나는 문제를 진단하는 일반 절차입니다. 실제 Place의 맵 크기, 동시 접속자, 기기별 메모리, 네트워크 지연, 자산 용량과 반경 값을 측정한 결과가 아니며 특정 설정의 성능 향상을 보장하지 않습니다. 공개 전 자신의 테스트 Place와 지원 기기에서 최신 Creator Hub 문서·Developer Console·Performance 지표를 기준으로 검증하세요.