📚 1. 사전 지식
참고 : 웹 접근성이란?, 웹 접근성 개선하는 법, Next.js의 _document와 _app에 대하여
웹 접근성
: 장애인이나 고령자분들이 웹 사이트에서 제공하는 정보를 비장애인과 동등하게 접근하고 이용 할 수 있도록 보장하는 것으로 웹 접근성 준수는 법적의무사항
웹 접근성 개선하는 법
1. 대체 텍스트 포함하기 이미지, 로고, 그림 등의 그래픽에 대체 텍스트를 사용하세요.
2. 높은 색상 대비 선택
3. 정보가 있는 링크 텍스트 사용
4. 텍스트 크기 및 정렬 확인
5. 서식 지원 텍스트 사용
6. 번호 매기기 및 글머리기호 목록 사용
_app
: 서버로 요청이 들어왔을 때 가장 먼저 실행되는 컴포넌트로, 페이지에 적용할 공통 레이아웃 역할
- Component 속성값은 서버에 요청한 페이지가 됨
- pagesProps는 getInitialProps, getStaticProps, getServerSideProps 중 하나를 통해 페칭한 초기 속성값이 됨
_document
: _app 다음에 실행되며, 공통적으로 활용할 <head>(ex. 메타 태그)나 <body> 태그 안에 들어갈 내용들을 커스텀
- _document를 작성할 때는 Document 클래스를 상속받는 클래스형 컴포넌트로 작성해야 함
- next/document로부터 import한 <Html>,<Head>,<Main>,<NextScript>요소를 리턴해야 함
- 서버에서 실행되기에 브라우저 api 또는 이벤트 핸들러가 포함되면 안 됨
🤩 2. 실제로 구현하기
1. _document.tsx 추가 & lang속성 추가
접근성이 84점이 나왔다.
언어를 설정하지 않았던 것이다. 그런데 우리 프로젝트에는 Next.js로 만든 프로젝트로, html태그가 애초에 없었다 !
// pages/_app.tsx
...
<div className="flex h-screen w-screen justify-center bg-slate-50 ">
<MetaHead />
<GoogleScript />
<Suspense fallback={<Loader />}>
<Provider store={store}>
<QueryClientProvider client={queryClient}>
<PersistGate loading={null} persistor={persistor}>
<Component {...pageProps} />
</PersistGate>
</QueryClientProvider>
</Provider>
</Suspense>
</div>
그렇다면 Next.js의 html은 우리가 손볼 수 없는 것일까?
Next.js로 만든 프로젝트의 요소 구조는 이러하다. html > head, body가 있고, head에는 내가 _app.tsx에서 <MetaHead>안에 넣은 것들이 들어가고, body 태그 안의 id=__next요소 안에 _app.tsx에서 넣은 태그들이 들어가 있다.
위의 사전 지식에 있는 것처럼 _app이 실행되고, _document가 실행된다. _document 안에는 공통적으로 활용할 <head>(메타 태그)나 <body> 태그 안에 들어갈 내용들을 커스텀할 때 사용한다.
그래서 pages폴더 안에 _document.tsx파일을 만들어주었다.
// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html lang="ko">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
<Html> 태그 속성으로 lang="ko"를 넘겨주었다.
성공적 !
접근성이 3점 올라 87점이 되었다! 좀만 더 가보즈아
2. user-scable=no?
lighthouse에서 user-scable="no"와 maximum-scale을 지적하였다. 기존 우리 코드의 Head이다.
// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html lang="ko">
<Head>
...
<meta
name="viewport"
content="initial-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no"
/>
...
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
user-scable이란, 사용자가 브라우저의 확대축소를 가능하게 할 것인지에 대한 정의이다. 확대가 되면 불편할 것이라 판단하여 이를 no로 하고, maximum-scale도 1로 설정해두었다. 이를 아래 코드처럼 바꾸었다.
// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html lang="ko">
<Head>
...
<meta
name="viewport"
content="initial-scale=1.0, width=device-width, maximum-scale=5.0, user-scalable=yes"
/>
...
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
maximum-scales=5.0, user-scable=yes로 바꾸고 다시 lighthouse를 측정해보았다.
무려 97점을 받았다 !
![](https://t1.daumcdn.net/keditor/emoticon/niniz/large/023.gif)
마지막으로 lighthouse가 권장하는 것은 백그라운드 및 포그라운드 색상의 대비인데 이건 디자이너와 협의를 더 해봐야겠지만, 색을 전체적으로 바꿔야 하기에 이거는 힘들 것으로 예상된다.
🤔 2. 느낀 점 / 배운 점 / 추가로 공부할 것
웹 접근성을 향상시켜 장애인뿐만 아니라 비장애인 모두가 이용할 수 있게 만드는 것에 대해 뿌듯함을 느꼈다. 다양한 사람들과 다양한 환경을 고려하여 프로그래밍하는 개발자가 되어야겠다고 결심했다.
추가로 공부할 것 : Next js 구동방식 과 getInitialProps
최초에 Next서버로 요청이 들어왔을 때, Next 서버에서는 요청이 들어온 페이지에 들어갈 데이터를 Fetch하고 Html을 구성하여 Client로 보내준다.
- _app.js, _document.js : 최초로 실행되는 녀석들. Next server logic에 사용되는 파일로, client에서 사용하는 로직(window/DOM로직)을 사용하면 안 됨.
- _app.js : client에서 띄우길 바라는 전체 컴포넌트의 레이아웃. 내부에 Content들이 있다면 전부 실행하고 Html의 Body로 구성
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>);
}
export default MyApp;
- props로 받은 Component : 요청한 페이지. Get요청을 보냈다면, Component에는 /pages/index.js파일이 props로 내려오게 됨.
- _document.js : _app.js실행 후 실행 됨. static html를 구성하기 위한 _app.jsHtml body가 어떤 형태로 들어갈지 구성하는 곳. Content들을 브라우저가 html로 이해하도록 구조화 시켜주는 곳
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>)
}
}
export default MyDocument
- _app.js가 실행되며 갖춰진 content들은 <Main> 아래에 생성됨. <Main>을 제외한 다른 컴포넌트들은 initialize하지 않음
getInitialProps : 각 페이지마다 사전에 불러와야할 데이터 → CSR에서는 componentDidMount or useEffet로 컴포넌트가 마운트 되고 나서 함. 이 과정을 서버에서 미리 처리하도록 도와준는 것
→ Next 9.3에서는 getInitialProps < getStaticProps, getStaticPaths, getServerSideProps 권장.
ServerSide Cycle
1. Next Server가 GET 요청을 받는다.
2. 요청에 맞는 Page를 찾는다.
3. _app.js의 getInitialProps가 있다면 실행한다.
4. Page Component의 getInitialProps가 있다면 실행한다. pageProps들을 받아온다.
5. _document.js의 getInitialProps가 있다면 실행한다. pageProps들을 받아온다.
6. 모든 props들을 구성하고, _app.js > page Component 순서로 rendering.
7. 모든 Content를 구성하고 _document.js를 실행하여 html 형태로 출력한다.
'개발 일지 > 개발 일지' 카테고리의 다른 글
[개발 일지] dependencies vs devDependencies 구분하기 (0) | 2023.05.18 |
---|---|
[개발 일지] React Native 도전기 (1) (0) | 2023.05.16 |
[개발 일지] React성능 최적화 (2) : React Query의 캐싱 기능 (1) | 2023.05.05 |
[개발 일지] React성능 최적화 (1) : React.memo로 사용자 경험 개선하기 (0) | 2023.05.03 |
[개발 일지] React Query - Custom Hook 만들기 (+Typescript) (0) | 2023.04.13 |
[개발 일지] JWT + 소셜 로그인을 정복해보자 (React + Spring Boot, Kakao Login, Naver Login) (0) | 2023.04.11 |
[개발 일지] Intersection Observer API & react-query를 이용한 무한스크롤 구현 (0) | 2023.02.28 |
[개발 일지] Suspense를 이용하여 모든 api에 Loading 화면을 설정하자 (NextJS, Suspense) (0) | 2023.02.18 |