프로젝트를 진행하면서 페이지 전환을 어떻게 사용했는지에 대한 정리.

 

 

프로젝트에서는 react-router-dom을 통해 페이지 라우팅을 처리하고 있다.

대부분의 블로그를 보면 다들 react-router-dom은 기본적으로 사용하는 것 같다.

react를 배운 강의에서도 react-router-dom을 사용했고 그로 인해 자연스럽게 useNavigate를 통해 페이지 전환을 처리했다.

 

react에서 페이지 전환은 몇가지 방법이 있었다.

1. useNavigate

2. Link

3. a Tag

4. window.location.href

 

그외 연관될만한 것으로는 ESLint를 사용했다.

따로 ESLint에 대한 설정을 하진 않았고 기본 상태 그대로 사용했다.

 

 

useNavigate

useNavigate는 react-router V6에서 새로 추가된 hook이다.

이전 버전까지는 useHistory가 해당 기능을 담당했다고 한다.

useNavigate는 react-router-dom을 통해 import 한 뒤 사용하게 되며 이벤트 핸들링에서 페이지 전환을 하도록 하거나 이벤트 액션으로 바로 전달할 수 있다.

하지만 클릭 이벤트에 대한 처리로 useNavigate를 바로 처리하는 것 보다는 Link 를 사용하는 것이 좋고, 핸들링을 통해 이벤트 로직 처리 후 페이지 전환을 하는 경우에 useNavigate를 사용한다고 한다.

 

사용 코드

import React from 'react';
import { useNavigate } from 'react-router-dom';
//...

function BoardPage() {
    //...
    const navigate = useNavigate();
    //...
    
    const handleOnClick = (e) => {
        //event handling code
        naviagte('/');        
    }
    
    return (
        <div>
            <BoardChildComponent
                data={data}
                onClickBtn={() => {
                    navigate('/board/insert')
                }}
            />
        </div>
    )
}

 

위 코드같은 방법으로 사용할 수 있다.

이벤트 핸들링 이후 페이지 전환을 처리하기 위해 사용하거나 하위 컴포넌트에 넘겨줘서 사용할 수 있도록 하는 방법이 있다.

useNavigate는 V6가 되면서 useHistory가 변화한 것인 만큼 useHistory에서 사용하던 window의 history를 이용한 navigate 기능도 가능하다.

간단하게 navigate(-1)을 하면 뒤로가기가 된다거나 하는 기능을 처리할 수 있다.

 

 

Link

다음은 Link 다.

기본적인 태그처럼 사용하게 되는데 Link 역시 react-router 에서 제공한다.

사용하는 것은 a 태그와 비슷하게 사용이 가능하다.

a 태그에서 href를 Link에서는 to 속성이 담당한다.

 

사용코드

import { Link } from 'react-router-dom';

//...

return (
    <Link to={'/'}>메인</Link>
    <Link onClick={handleOnClick}>onClickEvent</Link>
)

 

Link는 위와 같이 사용하게 되며 to 를 통해 직접 url을 작성해 이동하거나 onClick을 통해 핸들링을 하도록 할 수도 있다.

 

 

a Tag

이건 솔직히 react에서만 사용하는 것은 아니고 html 문법이니 정리할지 말지 고민했지만 정리한다.

href를 통해 url을 작성해준다.

 

사용코드

<a href={`/board/${board.boardNo}`})>{board.boardTitle}</a>
<a href={'#') onClick={handleOnClick}>{board.boardTitle}</a>

 

a 태그는 기본적으로 href 속성을 통한 url이동을 처리하고 따로 무언가를 수행하지 않고 클릭에 대한 이벤트 핸들링이 필요한 경우에는 href 속성 값으로 #을 넣어 처리한다.

#을 넣어주게 되면 아무것도 실행하지 않고 페이지 최상단으로 이동하게 된다.

 

근데 문제는 React에서 a 태그의 href 속성에 #을 넣게 되면 경고문이 발생한다.

 

The href attribute requires a valid value to be accessible. Provide a valid, navigable address as the href value. If you cannot provide a valid href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/anchor-is-valid.md jsx-a11y/anchor-is-valid

 

href 속성에 액세스 하려면 유효한 값이 필요하니 유효하고 탐색 가능한 주소를 href 값으로 제공해야 한다.

유효한 href를 제공할 수 없지만 link와 유사한 요소가 필요한 경우 button을 사용하고 적절한 스타일로 변경하라는 내용이다.

 

프로젝트에서 a 태그가 사용되는 부분으로는 게시판에서 상세 페이지로 이동하기 위해 게시글 정보를 감싸는 것과 페이징 버튼에 대해 a 태그로 처리했었다.

페이징 버튼의 경우 button으로 수정했지만 게시글에 대해서는 button으로 처리하기는 좀 그랬다.

이런 경우에는 Link를 통해 처리하면 좋다.

그리고 a 태그에서 href 속성에 # 을 넣어주게 되면 url에 #이 붙는 경우가 생기는데 Link를 사용하면 굳이 # 으로 처리할 필요도 없다보니 url에도 #이 붙을일이 없어서 그건 좋다!

 

그리고 a 태그를 통한 페이지 이동은 페이지 전체를 새로 불러오게 된다고 한다.

수정이 발생하는 컴포넌트만 재 렌더링 되는 것이 아닌 전체가 렌더링 되기 때문에 그런면에서 상황을 고려해 a 태그를 사용하는 것 보다 Link 태그를 사용해야 한다는 의견이 있었다.

 

 

window.location.href

보통 JQuery 사용했을 때 많이 사용하던 방법이다.

 

사용코드

window.location.href = '/';

 

거의 이 방법은 사용하지 않았는데 모듈에서 사용하게 되었다.

react hook은 컴포넌트에서만 사용할 수 있다는 조건이 있기 때문에 모듈에서 사용하기 위해서는 호출하는 컴포넌트에서 useNavigate를 같이 보내줘야 했다.

하지만 모듈 처리에서 조건에 따라 페이지 이동이 발생할수도, 없을수도 있고 navigate를 사용하지 않는 컴포넌트에서도 이 모듈 요청때문에 navigate를 보내줘야 하는 상황도 발생했다.

 

그래서 location.href 로 처리해보고자 했으나 ESLint 경고문이 발생했다.

 

ESLint: Unexpected use of 'location'.(no-restricted-globals)

 

JQuery에서는 location.href 만으로도 사용이 가능하지만 여기서는 location이 예기치 않게 사용되었다는 위와 같은 경고문이 발생한다.

IntelliJ 를 통해 문제를 해결하면  // eslint-disable-next-line no-restricted-globals  이런 주석이 달리면서 경고문이 사라지는데 ESLint 가 전역변수를 참조할 수 있게 주석으로 명시해주는 것이라고 한다.

 

그래서 window.location.href로 사용하는 것이 더 나은 방법이라고 생각한다.

하지만 window.location.href는 a 태그 이동처럼 전체 페이지가 렌더링 된다고 한다.

현재 프로젝트에서 사용하는 경우는 에러 핸들링에서 오류 페이지로 전환에 사용했기 때문에 전체 렌더링이 된다고 해도 딱히 뭐가 없어서 문제가 되진 않지만 그렇지 않은 경우에는 어떤 방법으로 해야할지 테스트와 경험이 필요할 것 같다.

+ Recent posts