React에서 IE로 접속할 경우 배너 띄우기

Sol Kim·2021년 10월 31일
2

상담페이지만들기

목록 보기
1/1

Intro


React 공부를 마치고 첫 번째 웹페이지를 만들어 보던 중, 홈페이지 예상 방문객 중 적지 않은 수가 IE를 이용해 페이지를 방문할것으로 예상되어, IE를 통한 접속을 처리해야 했다.

그러나 현재 이용중인 가장 최신 버전의 React에서는 IE11에서는, react-script가 정상적으로 동작하지 않아 index.html문서에 포함된 내용만 렌더링되어 흰색 화면만 뜰 뿐으로 CRA로 생성한 바닐라 상태의 현재 프로젝트에서는 IE 지원이 불가능하다는 결론이었다.

이 이슈에 대한 다른 리액트 기반 페이지들을 벤치마킹해보고자 몇몇 페이지에 IE로 접속을 시도해봤다.
그 결과, 현재 대부분의 홈페이지들에서는 JS를 이용해 위의 이미지와 같은 Microsoft 홈페이지로 리다이렉트시킨 뒤, IE Edge를 이용해 기존의 페이지를 띄워주는 방법을 쓰고 있었다.(Microsoft에서도 IE에 대한 공식 지원 종료를 선언한 뒤, 대형 홈페이지들에 직접 연락해가며 해당 리디렉션을 이용할 것을 권장하고 있다고)

현재 개발중인 페이지에서도 기능적인 면에서는 IE의 공식 지원 종료로 인한 여러 가지 취약점 발생 가능성.
심미적인 면에서는 커스텀 스크롤바의 사용이 불가능한 것과 같은 디자인 요소 이용의 어려움 등, 생각해보니 IE를 포기하고 리디렉션을 이용해야만 할 것 같은 이유들이 꽤 있었다.

그러나 아무래도 IE를 이용해 페이지를 방문할 유저들은 일반적으로 컴퓨터 이용이 서툴고, 이런저런 창들이 많이 뜨게 될 리디렉션을 귀찮아하고 복잡해 할 것 같다는 생각으로 페이지 상단에 IE 외 브라우저를 이용해 접속해달라는 배너를 띄우기로 결정했다.

이후 IE 페이지를 유지할지에 대한 여부는 실제로 홈페이지를 운영해보며 방문자들의 브라우저 정보를 수집해, IE로 접속하는 이용자들의 비율이 유의미할 경우 서비스를 지속하기로 결정했다.

접속한 브라우저 확인하기


if ( 
  (navigator.appName === 'Netscape' && navigator.userAgent.search('Trident') !== -1)
  || (agent.indexOf("MSIE") !== -1) 
) { ... }

접속한 브라우저를 확인하기 위해서는, Navigator 객체를 이용해 브라우저 스니핑을 진행하면 된다.

Navigator 객체는 브라우저 공급자 및 버전 정보 등을 포함한 브라우저에 대한 다양한 정보를 저장하는 객체로, appNameappCodeName 프로퍼티에 현재 사용중인 브라우저에 대한 정보를 담는다.

IE11을 포함해 크롬, 파이어폭스, 사파리는 appName을 'Netscape'로 사용하며,
IE10 이하 버전과 크롬, 파이어폭스, 사파리, 오페라 모두 appCodeName을 'Mozila'로 사용한다.

따라서, appName만을 가지고 IE와 기타 브라우저를 구분하긴 불가능하므로, OS 및 버전 등의 다양한 정보가 담긴 userAgent 프로퍼티를 함께 이용해야만 했다.

Explore User Agents를 확인해 볼 수 있는 페이지를 참조하면 알 수 있듯이, IE는 IE 10 이전에는 userAgentMSIE를 포함하며, IE 11버전은 Trident를 포함하므로, appName값과 userAgent값을 참조하는 위의 코드를 통해 접속한 브라우저가 IE인지 아닌지에 대한 여부를 판별할 수 있었다.

개발중인 홈페이지의 페이지 전환은 react-router-dom을 통해 이루어지고, IE 배너는 어느 페이지에서 접속했던 상관없이 띄워주어야 했으므로, 라우팅 코드가 존재하는 App.js의 가장 상위에서 헤더를 띄워주도록 했다.

다만 navigator.appName의 경우 현재 @deprecated이므로, 최대한 사용을 지양해야 할 것.
완전히 deprecated되기 전에 IE 점유율이 먼저 줄어들 것 같긴 하지만

IE11에서 React 작동하도록 설정하기



IE 11에서는 React가 흰 화면만 뱉는다.

안타깝지만, 이미 언급했듯이 IE에서는 React가 하얀 화면만 보내고 동작하지 않는다.
IE11에서 리액트가 동작하지 않는 이유는 코드에 폴리필이 적용되어 있지 않기 때문도 있지만, 무엇보다 중요한 것은 react-script가 정상적으로 동작하지 않아 index.html의 내용만 불러오고 컴포넌트들을 index.html문서에 제대로 가져다 붙이지 못한다는 것.

따라서 위의 문제는 다음과 같이 해결할 수 있다.

  1. 폴리필 적용
  2. react-script 다운그레이드
  3. package.json 수정
  4. node_modules/.cache 삭제

폴리필 적용

설치

npm install react-app-polyfill

적용

src/index.js에 설치한 폴리필을 적용시킨다.

import "react-app-polyfill/ie11";
import "react-app-polyfill/stable";
import React from "react"
import App from "./App";
...

react-script 다운그레이드

CRA로 인해 최신 버전으로 설치된 react-scripts를 3.2.0 버전으로 다운그레이드한다.
모듈의 버전 변경은 이곳저곳에서 예상치 못한 에러들을 발생시킬 수 있으므로, 되도록이면 프로젝트 초반에 진행하는 게 좋을 것 같다.

react-scripts는 다음 구문을 이용해 다운그레이드 할 수 있다.

npm uninstall react-scripts
npm install react-scripts@3.2.0

package.json 수정

package.jsonbrowserlistie 11을 추가해준다.

"browserslist": {
    "production": [
      "ie 11", // 추가
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "ie 11", // 추가
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }

node_modules/.cache 삭제

수정이 완료 되었다면 위의 파일을 삭제하자. 없으면 삭제하지 않아도 된다.

배너 구현하기

이제 IE 페이지에 배너를 구현할 준비가 모두 끝났으므로, 배너를 구현하기만 하면 된다.

App.js

checkIE()

  const checkIE = () => {
    const agent = navigator.userAgent.toLowerCase();
    if (
      (navigator.appName === 'Netscape' &&
        navigator.userAgent.search('Trident') !== -1) ||
      agent.indexOf('msie') !== -1
    ) {
      setIsIE(true);
    }
  }

App.js

const App = () => {
  const [isIE, setIsIE] = useState(false);
  useEffect(() => {
    checkIE();
  }, []);
  return (
    <>
      {isIE ? <IEWarning/> : ''}
      <Route component={MainPage} path="/" exact />
    </>
  );
};

CheckIE 함수를 만들어 IEWarning 컴포넌트를 띄워준다.
CheckIE에서는 state값인 isIE를 변경하므로, 무한 렌더링 하지 않기 위해서는 App에서 useEffect를 이용해 최초 렌더링 시에만 함수를 호출하도록 해야 한다.

이후 사이트 디자인에 맞추어 배너를 구현하면 된다.

부록 : <button> Onclick 이슈

IE Warning 배너를 구현하며, 크롬에서는 정상 작동하는 onClick 이벤트가 IE에서는 작동하지 않는 것을 발견했다.

문제의 코드

const IEWarning = () => {
    const [isVisible, setIsVisible] = useState(true);
    const closeBanner = () => {
        setIsVisible(false);
    }
  return (
      <>
        <WarningBlock isVisible={ isVisible }>
            <LeftElementBlock>
                <img src={ WarningIcon } style={ StyleWarningIcon } alt="warningIcon"/>이 페이지는 Internet Explorer 이용을 권장하지 않습니다. IE 이외의 브라우저를 이용해 주세요.
            </LeftElementBlock>
            <CloseButtonBlock>
                <ButtonContentsWrapper onClick={ closeBanner }>
                    <img src={ CloseIcon } style={ StyleCloseIcon } className="closeIcon" alt="closeIcon"/>닫기
                </ButtonContentsWrapper>
            </CloseButtonBlock>
        </WarningBlock>
        <Spacer isVisible={ isVisible }/>
      </>
  );
};

IE에서의 문제를 해결하기 위해 Button으로 선언된 CloseButtonBlockdiv로 바꾸었더니 onClick 이벤트가 정상적으로 동작했다.

혹시나 form이나 onSubmit과 관련된 세팅이 IE와 크롬에서 다른 건 아닌지, IE의 스크립트 보안 세팅이 문제인건 아닌지 한참 찾아봤으나, 생각보다 허무한 결론.

onClickbuttonCloseButtonBlock에 할당한 것이 아니라, 버튼의 하위 요소인 ButtonContentsWrapper에 할당했던 것.

크롬의 경우 버튼의 하위 요소가 클릭되어도 하위 요소에 적용된 onClick이 정상적으로 실행되지만, IE에서는 버튼이 클릭되었는데 버튼에 할당된 onClick이벤트 요소가 아무것도 없으므로 실행되지 않도록 하는 차이인 것 같다.

References

profile
풀스택 꿈나무

1개의 댓글

comment-user-thumbnail
2022년 4월 18일

큰 도움 되었습니다. 감사합니다!

답글 달기