Vue.js + VTK.js를 사용한 3D 치과 모델 렌더링 시스템에서, 모델이 정렬되지 않은 상태로 먼저 화면에 표시되고, Reset 버튼을 눌러야 정렬된 상태로 보이는 문제 발생
graph TD
A[onMounted] --> B[모델 렌더링]
B --> C[정렬되지 않은 모델 화면 표시]
C --> D[watch 감지]
D --> E[registration_result 적용]
E --> F[변환 행렬 적용]
G[Reset 버튼] --> H[저장된 정렬 상태 적용]
H --> I[정렬된 모델 표시]
// 잘못된 실행 순서
onMounted(async () => {
await renderScene(modelData); // 1. 모델 먼저 렌더링
// 이 시점에서 이미 화면에 정렬되지 않은 모델이 표시됨
});
watch(() => store.registration_result, (result) => {
applyAlignment(result); // 2. 나중에 정렬 적용
});
// 정렬 적용 중복 실행 방지
const isApplyingAlignment = ref(false);
function applyRegistrationResult(result: any) {
if (isApplyingAlignment.value) {
console.log('이미 정렬 적용 중 - 스킵');
return;
}
isApplyingAlignment.value = true;
try {
// 정렬 로직 실행
applyTransformations(result);
} finally {
isApplyingAlignment.value = false;
}
}
// ViewerFacade.ts
public forceRender(): void {
if (this.scene) {
this.sceneManagerAdapter.renderScene(this.scene);
console.log('ViewerFacade: Force render completed');
} else {
console.warn('ViewerFacade: Scene not initialized, cannot force render');
}
}
onMounted(async () => {
try {
// 1. 모델 렌더링
const modelData = await createArrayBufferToPropRequestDto();
viewerFacade.renderScene(modelData);
// 2. 렌더링 완료 후 기존 정렬 결과가 있으면 즉시 적용
setTimeout(() => {
const existingResult = autoAlignmentStore.registration_result;
if (existingResult && JSON.stringify(existingResult) !== '{}') {
console.log('onMounted: 기존 registration_result 발견, 즉시 적용');
applyRegistrationResult(existingResult);
}
}, 100); // 렌더링 완료를 위한 짧은 지연
// 3. 이벤트 리스너 등록
addEventListeners();
} catch (error) {
console.error('Component: Failed to render scene:', error);
}
});
// 정렬 로직을 별도 함수로 분리하여 재사용
function applyRegistrationResult(result: any) {
if (isApplyingAlignment.value) return;
console.log('registrationResult 적용 시작 - ', result);
if (result && JSON.stringify(result) !== '{}') {
isApplyingAlignment.value = true;
try {
const registrationResult = new RegistrationResult(result);
const transformations = extractTransformations(registrationResult);
// 변환 행렬 적용
transformations.forEach(({ modelName, matrix }) => {
viewerFacade.applyTransformToProp(modelName, matrix);
});
// 강제 렌더링으로 즉시 화면 업데이트
setTimeout(() => {
viewerFacade.forceRender();
setCameraView(CAMERA_VIEWS.FRONT);
}, 200);
} finally {
isApplyingAlignment.value = false;
}
}
}
// onMounted와 watch에서 동일한 함수 사용
watch(() => autoAlignmentStore.registration_result, applyRegistrationResult);
onMounted → 정렬되지 않은 모델 표시 → 사용자가 Reset 클릭 → 정렬된 모델 표시
Case 1: Result 있음
onMounted → 모델 렌더링 → 즉시 정렬 적용 → 정렬된 모델 표시
Case 2: Result 없음
onMounted → 정렬되지 않은 모델 표시 → Result 도착 → 즉시 정렬 적용 → 정렬된 모델 표시
isProcessing
플래그 활용결론: 3D 웹 애플리케이션에서는 렌더링 타이밍과 상태 동기화가 매우 중요하며, 명확한 실행 순서 보장과 중복 방지 메커니즘이 필수적이다.