ReactJS - #1 기초 및 실습 (2주차)
#1 기초 및 실습 (2주차)
nextjs.org/docs/basic-features/pages
Basic Features: Pages | Next.js
Next.js pages are React Components exported in a file in the pages directory. Learn how they work here.
nextjs.org
next.js는 기본적으로 page routing 방식을 밑에 형식과 같이 지원해준다.
next.js에서 자체적으로 지원해주는 Link와 Router 기능
위 코드와 같이 import 를 한 후
요런 식으로 써주게 되면 'pages/class.js' 로 자동으로 routing된다
페이지 이동이 좀 자유로운 장점이 있다.
이런식으로도 쿼리스트링으로도 넘길 수 있다.
폴더 구조 세팅
이런식으로 폴더구조를 생성해주고
server.js를 세팅하기 위해 기본적으로 필요한 express, cookie-parser, morgan, express-session을 install한다
jaeho@jaehoiui-MacBookPro my-app % npm install --save express morgan cookie-parser express-session
* 중간에 --save를 붙여주는 이유는 아마도 package.json 안의 dependencies 부분에 명시적으로 표시해주려고 하는 듯?
그런 다음에 server.js에 다음코드를 추가한다.
const express = require('express');
const next = require('next');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const expressSession = require('express-session');
그리고 밑에 서버를 만들어주는 기본 코드를 추가한다.
* 그리고 주석을 꼭 읽어보고 다시 생각해보자
const express = require('express');
const next = require('next');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const expressSession = require('express-session');
const dev = process.env.NODE_ENV !== 'production';
// app 자체를 next구조대로 가져온다.
// 기본적인 handler와 app자체는 next.js를 기반
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then( () => {
// next가 준비가 되면 next안에서 express를 불러온다.
const server = express();
// server로 express 세팅해주는 부분
server.use(morgan('dev'));
server.use(express.json());
server.use(express.urlencoded({ extended : true}));
server.use(cookeParser('!ASD!ASd!AVZXC!@#123'));
server.use(
expressSession({
resave : false,
saveUninitialized : false,
secret : '!ASD!ASd!AVZXC!@#123',
cookie : {
httpOnly : true,
secure : false,
},
}),
);
// 라우팅을 하는 과정을 실질적으로는 next에 내장된 자체 핸들러에서 처리를 하고 있다고 생각했을때 제약이 있다.
// 어떤 규칙을 지켜야하고 우리가 원하는 식의 코드 특히, 웹어플리케이션의 시멘틱한 구조를 자신의 기본적인 라우팅 과정에서 인식하지 못하는 경우가 생긴다.
// 위처럼 라우팅 자체를 통제하는 방식 , page단위의 queryProps로 관리하는 방법의 예
// server.get('*')보다 직접 라우팅하는 코드가 위에 있어야 한다.
// 쿼리스트링으로 next에서 데이터를 가져오는 방식에서 이슈가 있는데 새로고침을 했을때 값을 못가져오는 경우가 발생한다.
// 그래서 이런 구조로 짜서 props형태로 데이터를 유지하기 위해서 서버를 구성한다.
// 또한, front에서 파일처리 할 때 node.js에서는 aws s3같이 직접 스토리지에 바로 저장하는 구조로 하지 않을때는 멀터라는 모듈을 써서
// 로컬에 저장해놓고 저장시켜준 파일을 인식시켜서 보내면서 temp파일로 저장하고 삭제하는 방법을 사용하는데 근데 이걸 완전히 page단위에서 처리할 수 는 없기때문에
// 항상 ajax라던지 로컬서버로 연결을 시키는 과정이 필요한데 이럴때 server가 필요하다.
// 여기서 구성하는 서버는 백엔드가 만든 어떤 데이터를 연결시켜주고 서버환경을 구축하기 위해서 만들어준 서버보다는 front-end 단위에서 rendering에 도움을 준다던지
// 우리가 프론트 쪽에서 직접 작업하기 어려운 코드들을 로컬서버에서 작동시키기 위해 구축하는 경우가 있다.
// 이 밑에 코드를 달지 않으면 next는 기본적으로 csr을 기본으로 작동한다.
server.get('/product/:id/:name/:name/:price', (res, req) => {
const actualPage = '/product_detail';
const queryParams = {
id : req.params.id,
name : req.params.name,
price : req.prarms.price
}
// 이렇게 queryParams로 정리해서 page에 보내면 page에서는 props로 받아서 사용할 수 있다.
return app.render(req, res, actualPage, queryParams);
})
// 페이지 props를 연결하는 과정을 이렇게 간단하게 만들어놓은것 -> next에서 ssr을 사용할때 이런 구조를 사용해라라는 document
// 이걸안하면 page단위 라우팅이 안된다.
server.get('*', (req, res) =>{
return handle(req, res);
})
server.listen(3000, () => {
console.log('next + express running on port 3000');
})
})
추가 설명
웹이라고 하는게 쿼리스트링이나 시멘틱한 것들이 필요한가 생각하면 모바일 어플리케이션에서는
페이지가 스텍으로 쌓이는 개념이라 유지를 시킬 수 있는데 웹은 페이지가 넘어가거나 전환이 되어버리면
세션이나 쿠키나 로컬 스토리지에 저장하고 따로 호출하지 않으면 연결이 되지 않는 구조가 많다.
그렇다고 전부 저장하고 호출할 수 없기 때문에 쿼리스트링이나 시멘틱한 구조의 데이터 전달과정이 필요하다.
기본적인 서버 구축이 끝났으면 잘 작동이 되는지 점검을 해야하는데
package.json파일에서 start를 "next start" 에서 "node server.js"로 바꿔준다.
실행시키는 코드는 다음과 같다
jaeho@jaehoiui-MacBookPro my-app % npm run build && npm start
해당 명령어를 실행했을때 inex.js에서 style에 대한 코드를 수정안한 부분 때문에 빌드가 제대로 되지 않아
css를 참조하는 코드를 지우고 다시 run
그럼 아래 화면처럼 잘 처리되는 것을 확인할 수 있다.
이렇게 된~줄 알았겠지만 사실 다시보면 ReferenceError가 발생한것을 확인할 수 있는데
cookieParser를 cookeParser라고 오타를 쳐서 발생한 에러, 해당 코드를 수정한 뒤 서버를 돌리고 웹페이지로 들어가보면
이러한 화면이 출력되는 것을 확인할 수 있다.
nodemon moduel설치
서버에 변경사항이 있을때마다 자동 재실행해주는 모듈, 편하게 작업하기 위해 설치하는 모듈이다라고 생각하면 편하다.
보통 설치할때 글로벌로 설치하는게 좋다.
-g
jaeho@jaehoiui-MacBookPro my-app % sudo npm install -g nodemon
그리고 script 의 dev를 다음과 같이 바꿔준다.
styled-components install
jaeho@jaehoiui-MacBookPro my-app % npm install --save babel-plugin-styled-components styled-components
.babelrc 파일 생성
그 안에 stlyed-components 기본세팅 코드 작성
{
"presets": ["next/babel"],
"plugins": [
[
"styled-components",
{
"ssr" : true,
"displayName" : true,
"preprocess" : false
}
]
]
}
styled-components를 이용해서 내부 스타일링을 할때만 하면된다.
sass로 세팅하는 경우는 styled-components를 install해서 사용할 필요가 없다.
_document 파일 생성
_document는 next document라고 해서 next자체가 seo를 할수 있다고 말한게 next 안에서 DOM구조, html이 가지고있는 document
구조를 기능화해서 만들어 놓았기 때문이라고 생각하면 된다.
import Document, { Head, Main, NextScript } from 'next/document';
export default class MyDocument extends Document{
render(){
return (
<html lang = "en">
<Head>
<meta charSet="utf-8" />
<title>React Practice</title>
<meta name="viewport" content="width=device-width, initial-scale-1.0, maximum-scale=1, user-scalable=no" />
{/* 스타일 시트 링크 */}
{/* 웹폰트 임포팅 */}
{/* 메타설정 */}
</Head>
<body>
<Main /> {/* 라우터에 해당하는 페이지가 렌더링 되는 부분 */ }
<NextScript /> {/* Next 관련 된 자바스크립트 파일 */}
</body>
</html>
)
}
}
// import { ServerStyleSheet } from 'styled-components';
// export default class MyDocument extends Document{
// static getInitialProps({ renderPage }){
// // step 1 : Create an instance of ServerStyleSheet
// const sheet = ServerStyleSheet();
// // step2 : Retrieve styles from components in the page
// const page = renderPage(App => props => sheet.collectStyles(<App {...props} />));
// // Step 3 : Extract the styles as <style> tags
// const styleTags = sheet.getStyleElement();
// // step 4: Pass styleTags as a prop
// return { ...page, styleTags};
// }
// render(){
// return (
// <html>
// <Head>
// {/* step 5 : Output the styles in the head` */}
// <meta charSet='utf-8'/>
// <meta name='viewport' content='initial-scale=1.0, width=device-width' />
// {this.props.styleTags}
// </Head>
// <body>
// <Main />
// <NextScript />
// </body>
// </html>
// );
// }
// }
이렇게 한후에 서버를 실행시키면
우리가 설정했던 설정들이 페이지에 들어가 있는 것을 확인할 수 있다.