1. 문제 발생❓
TypeScript에서 MutableRefObject<PdpRefs> 타입을 사용하는 Lnb 컴포넌트에서 refs.current를 배열처럼 처리하려고 할 때 문제가 발생했습니다. PdpRefs는 Map<PdpLnbTabName, HTMLElement | null> 타입으로 정의되어 있지만, 실제로는 숫자 인덱스(0, 1, 2, 3 등)로 접근할 수 있는 객체로 동작했습니다.
// 타입 정의
export type PdpRefs = Map<PdpLnbTabName, HTMLElement | null>;
// 컴포넌트에서 시도한 코드
{refs.current.map((ref, index) => { // 오류: 'map' 속성이 없습니다
// ...
})}
2. 원인 추론 🔎
- TypeScript 타입으로는 PdpRefs가 Map 객체로 정의되어 있음
- 실제 런타임에서 refs.current는 다음과 같은 특성을 보임
- Object.keys(refs.current)는 ["0", "1", "2", "3"]을 반환
- .enctries( )같은 Map 메소드는 빈 배열을 반환(size=0)
- 숫자 인덱스로 직접 접근(refs.current[1])은 실제 DOM 요소를 반환
- 즉, refs.current는 Map의 프로토타입을 가진 일반 객체와 유사한 하이브리드 객체로 보임
< refs 객체의 이상 구조 >
실제 콘솔 로그에서 refs 객체 구조를 살펴보면 추가적인 이상한 점이 발견되었습니다ㅠㅠ
이거 확인중1 => {current: Map(0)}
current: Map(0) {0: div#강의 소개, 1: div#튜터, 2: section#커리큘럼.css-zbbk26, 3: section#FAQ.css-zbbk26, size: 0}
이 구조에서 발견는 이상한 점:
- Map(0)은 크기가 0인 Map을 의미하지만, 내부에 4개의 요소가 존재함
- Map은 key-value 쌍으로 저장되어야 하는데, 여기서는 숫자 인덱스만 보임
- 표준 Map 인터페이스와 달리 숫자 인덱스로 직접 접근 가능
- 키가 PdpLnbTabName 타입("강의소개", "커리큘럼" 등)이 아닌 숫자 인덱스(0, 1, 2, 3)로 되어 있음
이는 실제 객체가 Map 처럼 보이게 만들었지만 내부적으로는 일반 객체 처럼 동작하도록 만들어진 것으로 추정됩니다. 이런 구조는 타입 안전성을 해치고 예상치 못한 동작의 원인이 될 수 있습니다.
3. 해결 과정 📋
숫자 인덱스를 이용해 객체에서 요소를 추출하여 배열로 반환하는 방법을 사용했습니다.
const refArray = [];
for (let i = 0; i < Object.keys(refs.current).length; i++) {
if (refs.current[i]) {
refArray.push(refs.current[i]);
}
}
이렇게 생성된 배열을 컴포넌트 내에서 사용했습니다.
{refArray.map((ref, index) => {
if (!ref) return null;
return (
<S.Item
key={ref?.id}
isActive={activeIndex === index}
onClick={() => { /* ... */ }}
>
{ref?.id}
</S.Item>
);
})}
< 추가 해결 포인트 >
처음에는 배열이 비어 있는 문제가 계속 발생했는데, 이는 useEffect의 의존성 배열을 적절히 설정하지 않아서 발생한 타이밍 문제였습니다.
// 문제가 있는 코드
useEffect(() => {
console.log("이거 확인중2 =>", refArray);
}, []); // 빈 의존성 배열
// 해결책
useEffect(() => {
console.log("이거 확인중2 =>", refArray);
}, [refArray]); // refArray를 의존성으로 추가
의존성 배열에 refArray를 추가함으로써 데이터가 로드된 후에 로그가 실행되도록 보장했습니다.
4. 결과 ❤🔥
이러한 비정상적인 ref 객체 구조는 아마도 라이브러리 통합 과정이나 특수한 초기화 패턴에서 발생했을 가능성이 높습니다. 단기적인 해결책으로는 현재의 접근 방식이 효과적이지만, 장기적으로는 refs 객체 생성 부분을 검토하여 Map 객체를 올바르게 사용하거나 타입 정의를 실제 구조에 맞게 조정하는 것이 바람직합니다!
'인턴' 카테고리의 다른 글
Jotai (0) | 2025.03.25 |
---|---|
[ Troubleshooting🛠️ ] GNB 자동 스크롤과 페이지 이동 기능 통합 (0) | 2025.03.25 |
[ Troubleshooting🛠️ ] HTML <picture>과 <source> 태그 활용하기 (0) | 2025.03.25 |
Vercel CLI을 이용한 환경변수 세팅 (0) | 2025.03.25 |
자동 스크롤 useRef 적용하기 💫 (0) | 2025.03.14 |