축구팀 관리 프로젝트 13일차 - 포메이션 관리 화면, ts(2339) 오류
축구팀 관리 프로젝트에서 드디어(?) 이 화면을 맡게 되었습니다. 생각보다 어려운 화면이어서 맡기가 부담스럽긴 했지만 그래도 최대한 노력해보려 합니다. 그리고 화면 구성하며 나타난 typescript 해결 과정에 대해서도 기록하려합니다.
포메이션 관리 화면 시작
전날 작업한 기록입니다
전날 아래의 경기 일정 페이지를 다 만들고 나서 오늘 아침 팀원에게 공유하려고 다시 들어가보니 이미지가 나오지 않았습니다. 왜 그런가 찾아보니 페이지 로드시 '팀원 확인 하는 API'와 '일정별 이미지 가져오는 API'가 순서 상관 없이 동작하고 있었기 때문이었습니다.
순서가 중요한데 이부분을 적용하지 않아서 발생한 오류였습니다. 팀원 확인 → 일정별 이미지 가져오기 가 되어야 하는데 순서를 정해두지 않으니 어떨땐 팀원 확인이 또 어떨때는 일정별 이미지 가져오기 API가 동작하고 있었습니다. 이를 수정하고 다시 확인해봤을 때 이상 없이 동작하는 것을 볼 수 있었습니다.
그러고 나서 남은 작업들을 확인해봤습니다. 어떤 팀원은 통계 페이지 하고 있고, 어떤 팀원은 사용자 관리 화면을 하고 있고 있었습니다. 작업한 화면, 작업 하고 있는 화면 그리고 남은 작업화면을 보니 이 페이지가 남아있었습니다.
기획할 때 이 화면이 계획한 화면 중에서 제일 어려울거다 말이 있었습니다. 그도 그럴 것이 오른쪽에 나타날 선수 명단을 왼쪽으로 끌어당기면 왼쪽 선수 자리에 등록되게 동적 구현을 하자고 계획했기 때문입니다. 팀원들도 필자에게 이 화면을 맡으면서 그정도의 리엑트 구현은 어려울 수 있으니 드래그 앤 드롭 이벤트가 어려우면 선수명단에서 드롭다운하여 포지션 지정하여 만드는 방법을 하기를 권했습니다. 두 가지 방법 모두 처음 접하는 기능이기 때문에 테스트해보고 실현 가능성 있는 방법을 하겠다고 했습니다.
그렇게 시작한 테스트
우선 시작은 경기장 필드 안에 아이콘이 동적으로 움직이도록 하는것부터 해보았습니다.
이렇게 동적 이동을 하게 하기 위해서 react-draggable을 활용했습니다.
react-draggable 샘플 페이지
react-draggable을 테스트하려고 코드를 짜고 실행해보니 아래처럼 화면이 나왔습니다.
지정한 아이콘들이 전부 경기장 밖을 나가는 모양이었습니다. 범위 지정이 필요해 보였습니다. 그래서 이미지가 담긴 이미지 컨포넌트에 ref를 부여하기로 했습니다.
// 이미지의 ref를 생성합니다.
const fieldRef = useRef(null);
그 후 useState를 사용하여 컴포넌트가 마운트될 때 해당 이미지의 경계를 계산하도록 했습니다.
// 드래그 가능한 경계를 설정하는 state입니다.
const [bounds, setBounds] = useState({ left: 0, top: 0, right: 0, bottom: 0 });
useEffect(() => {
// 이미지의 경계를 계산하여 state를 업데이트합니다.
if (fieldRef.current) {
const { left, top, right, bottom } = fieldRef.current.getBoundingClientRect();
setBounds({ left, top, right: right - left, bottom: bottom - top });
}
이 후 계산된 경계는 draggable 컴포넌트에 bounds 속성으로 전달되어 드래그가 이미지 경계에서 가능하도록 제한했습니다.
<Image ref={fieldRef} src='../../img/field.png' alt="경기장 사진" />
{/* 드래그 가능한 경계를 Draggable 컴포넌트에 전달합니다. */}
<Draggable bounds={bounds}>
<Player style={{ left: formation433.goalkeeper.x, top: formation433.goalkeeper.y }} />
</Draggable>
여기서 코드를 수정하고 보니 아래와 같이 예기치 않은 오류를 발견하게 됩니다.
ts(2339) 오류
'never' 형식에 'getBoundingClientRect' 속성이 없습니다.ts(2339)
예상 못한 에러라 당황했지만 바로 찾아보았습니다. 찾아보니 이 오류의 뜻은 쉽게 말해 getBoundingClientRect 메서드를 호출하려 하는 데 대상이 실제로 그 메서드를 가지고 있지 않다는 의미였습니다. ref가 DOM 요소를 참조하지 않거나 타입이 명확하지 않아 발생한 오류였습니다. 현재 작업하는 이 파일이 tsx 형식이라 ref에 타입을 명확히 해야 했었습니다. 그래서 아래와 같이 이미지 ref에 HTMLImageElement 타입을 지정하여 오류를 잡을 수 있었습니다.
const Formation = () => {
// 이미지의 ref를 HTMLImageElement로 설정합니다.
const fieldRef = useRef<HTMLImageElement>(null);
TypeScript는 자바스크립트에 타입 안정성을 추가하여, 개발 과정에서 발생할 수 있는 많은 오류를 미리 잡을 수 있게 합니다. 이 오류를 통해 never 타입이 예상되지 않은 곳에서 사용되었음을 알 수 있었으며, 이를 통해 개발하며 타입이 올바르게 적용되었는지 확인해야 함을 배울 수 있었습니다.
▼ 이전 진행한 프로젝트들 ▼
'내일배움캠프 > 축구팀 관리 프로젝트' 카테고리의 다른 글
축구팀 관리 프로젝트 15일차 - 경기 후 기록 등록하는 로직 수정 (0) | 2024.01.27 |
---|---|
축구팀 관리 프로젝트 14일차 - 전술 설정 화면, nestjs cron 사용 (1) | 2024.01.26 |
최종프로젝트 12일차 경기 일정 조회 작업, 쿼리 최적화에 대해 (0) | 2024.01.23 |
최종프로젝트 11일차 - 경기장 예약 완료, ORM 쿼리 복잡해질 때 (1) | 2024.01.23 |
최종프로젝트 10일차 - 경기장 예약 화면 작성 중, 좌표에서 주소 변환 (0) | 2024.01.21 |