-
ReactJS - #1 기초 및 실습 (2주차)React 2020. 12. 17. 18:23
#1 기초 및 실습 (2주차)
nextjs.org/docs/basic-features/pages
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> // ); // } // }
이렇게 한후에 서버를 실행시키면
우리가 설정했던 설정들이 페이지에 들어가 있는 것을 확인할 수 있다.
'React' 카테고리의 다른 글
ReactJS - #3 기초 및 실습 (2주차) (0) 2020.12.20 ReactJS - #5 기초 및 실습 (1주차) (0) 2020.12.17 ReactJS - #4 기초 및 실습 (0) 2020.12.16 ReactJS - #3 기초 및 실습 (0) 2020.12.16 ReactJS - #2 기초 및 실습 (0) 2020.12.16