그러나 현재 이용중인 가장 최신 버전의 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 객체는 브라우저 공급자 및 버전 정보 등을 포함한 브라우저에 대한 다양한 정보를 저장하는 객체로, appName
과 appCodeName
프로퍼티에 현재 사용중인 브라우저에 대한 정보를 담는다.
IE11을 포함해 크롬, 파이어폭스, 사파리는 appName을 'Netscape'로 사용하며,
IE10 이하 버전과 크롬, 파이어폭스, 사파리, 오페라 모두 appCodeName을 'Mozila'로 사용한다.
따라서, appName만을 가지고 IE와 기타 브라우저를 구분하긴 불가능하므로, OS 및 버전 등의 다양한 정보가 담긴 userAgent 프로퍼티를 함께 이용해야만 했다.
Explore User Agents를 확인해 볼 수 있는 페이지를 참조하면 알 수 있듯이, IE는 IE 10 이전에는 userAgent
에 MSIE
를 포함하며, IE 11버전은 Trident
를 포함하므로, appName
값과 userAgent
값을 참조하는 위의 코드를 통해 접속한 브라우저가 IE인지 아닌지에 대한 여부를 판별할 수 있었다.
개발중인 홈페이지의 페이지 전환은 react-router-dom
을 통해 이루어지고, IE 배너는 어느 페이지에서 접속했던 상관없이 띄워주어야 했으므로, 라우팅 코드가 존재하는 App.js
의 가장 상위에서 헤더를 띄워주도록 했다.
다만 navigator.appName
의 경우 현재 @deprecated
이므로, 최대한 사용을 지양해야 할 것.
완전히 deprecated되기 전에 IE 점유율이 먼저 줄어들 것 같긴 하지만
IE 11에서는 React가 흰 화면만 뱉는다.
안타깝지만, 이미 언급했듯이 IE에서는 React가 하얀 화면만 보내고 동작하지 않는다.
IE11에서 리액트가 동작하지 않는 이유는 코드에 폴리필이 적용되어 있지 않기 때문도 있지만, 무엇보다 중요한 것은 react-script
가 정상적으로 동작하지 않아 index.html
의 내용만 불러오고 컴포넌트들을 index.html
문서에 제대로 가져다 붙이지 못한다는 것.
따라서 위의 문제는 다음과 같이 해결할 수 있다.
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";
...
CRA로 인해 최신 버전으로 설치된 react-scripts
를 3.2.0 버전으로 다운그레이드한다.
모듈의 버전 변경은 이곳저곳에서 예상치 못한 에러들을 발생시킬 수 있으므로, 되도록이면 프로젝트 초반에 진행하는 게 좋을 것 같다.
react-scripts
는 다음 구문을 이용해 다운그레이드 할 수 있다.
npm uninstall react-scripts
npm install react-scripts@3.2.0
package.json
의 browserlist
에 ie 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"
]
}
수정이 완료 되었다면 위의 파일을 삭제하자. 없으면 삭제하지 않아도 된다.
이제 IE 페이지에 배너를 구현할 준비가 모두 끝났으므로, 배너를 구현하기만 하면 된다.
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
를 이용해 최초 렌더링 시에만 함수를 호출하도록 해야 한다.
이후 사이트 디자인에 맞추어 배너를 구현하면 된다.
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
으로 선언된 CloseButtonBlock
을 div
로 바꾸었더니 onClick
이벤트가 정상적으로 동작했다.
혹시나 form
이나 onSubmit
과 관련된 세팅이 IE와 크롬에서 다른 건 아닌지, IE의 스크립트 보안 세팅이 문제인건 아닌지 한참 찾아봤으나, 생각보다 허무한 결론.
onClick
을 button
인 CloseButtonBlock
에 할당한 것이 아니라, 버튼의 하위 요소인 ButtonContentsWrapper
에 할당했던 것.
크롬의 경우 버튼의 하위 요소가 클릭되어도 하위 요소에 적용된 onClick
이 정상적으로 실행되지만, IE에서는 버튼이 클릭되었는데 버튼에 할당된 onClick
이벤트 요소가 아무것도 없으므로 실행되지 않도록 하는 차이인 것 같다.
큰 도움 되었습니다. 감사합니다!