본문 바로가기

블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기

[80일차] 20210706 React, Webpack, CSS 웹팩으로 Header 만들기

반응형

 

 

 

 

어제 만들거를 복사해서 다시 만들기 

 

1. package.json / webpack.config.js 복사  (package.json 복사한 이유 - 다시 설치 위해 by 'npm install'

 

2. index.html  /index.jsx 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id ="root"></div>
    <script type="text/javascript" src="./dist/app.js"></script>
</body>
</html>

 

3. terminal  - 새로만든 directory 로 들어가 있는지 확인 

 

 

4. 아래 명령어 실행 (packages 다운) 

$ npm install

-> webpack까지 다 설치 됨 

 

webpack config만 실행시키면 됨 -> 근데 아래 명령어 실행 전 오류가 남 ! 

$ npm ren dev

 

ERROR

C:\Users\saeee_z18xmwt\OneDrive\문서\react_first_lesson0628\0706webpack>cd .. C:\Users\saeee_z18xmwt\OneDrive\문서\react_first_lesson0628>cd .\0706webpack2 C:\Users\saeee_z18xmwt\OneDrive\문서\react_first_lesson0628\0706webpack2>npm istall 일괄 작업을 끝내시겠습니까 (Y/N)? y C:\Users\saeee_z18xmwt\OneDrive\문서\react_first_lesson0628\0706webpack2>npm install npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: 0705webpack@1.0.0 npm ERR! Found: react-refresh@0.10.0 npm ERR! node_modules/react-refresh npm ERR! dev react-refresh@"^0.10.0" from the root project npm ERR! npm ERR! Could not resolve dependency: npm ERR! peer react-refresh@">=0.8.3 <0.10.0" from @pmmmwh/react-refresh-webpack-plugin@0.4.3 npm ERR! node_modules/@pmmmwh/react-refresh-webpack-plugin npm ERR! dev @pmmmwh/react-refresh-webpack-plugin@"^0.4.3" from the root project npm ERR! npm ERR! Fix the upstream dependency conflict, or retry npm ERR! this command with --force, or --legacy-peer-deps npm ERR! to accept an incorrect (and potentially broken) dependency resolution. npm ERR! npm ERR! See C:\Users\saeee_z18xmwt\AppData\Local\npm-cache\eresolve-report.txt for a full report. npm ERR! A complete log of this run can be found in: npm ERR! C:\Users\saeee_z18xmwt\AppData\Local\npm-cache\_logs\2021-07-06T00_32_22_058Z-debug.log

위의 두 개가 설치 오류가 있었던거 같음

 

 

아래 명령 실행 

npm install -D @pmmmwh/react-refresh-webpack-plugin --save --legacy-peer-deps 
npm install webpack -D

다시 해보니 위의 명령어 첫 번째만 해도 된다 ! 처음엔 둘 다 입력해야 되었다. 

 

 

 

 * 오늘 알게 된 것 !

    <div id ="root"></div>
    <script type="text/javascript" src="./dist/app.js"></script>
    <!--
        위코드 - index.jsx + app.jsx 을 합쳐서 = app.js 에 담음 
        dev server는 -> dist - app.js 가 안보이지만 실제로 돌아가고 있음 ! 
    
    -->

dist - app.js 는 dev server에서는 보이지는 않지만 돌아가고 있음 ! 

 

 

 

 

 


 

 

 

 

위의 웹팩 환경세팅, React + CSS 

App / Func / Class Component  - 따로 모듈로 뺄 것 ! 총 index 합쳐서 4개의 파일로 만들어짐 (쪼개짐)

 

index.jsx -> DOM only  ! 

 

1. 아래처럼 나누기 

 

 

 

2. index.jsx와 app.jsx 연결하기 

 

app.jsx

import React, {Component} from 'react'


class App extends Component{
    render(){
        return(
            <>
                Hello world
            </>
        )

    }
}
// module.exports => require 같은 것  기본 js 모듈 언어 
// export default App =>import 같은 것  => babel 덕분에 가능 
export default App

 

index.jsx

import React,{Component} from 'react'
import ReactDOM from 'react-dom'
import App from './app'       // 불러오기 



ReactDOM.render(
    <App />,
    document.querySelector('#root')
)

 

 

 

 

3. Func Component / Class Component +   App 연결 

li tag 로 감싸기 / 큰 틀은 ul로 ! 

 

ClassComp.jsx

import React, {Component} from 'react'


class ClassComp extends Component{
    render(){
        return(
            <li className="classComp">
                Class Component
            </li>
        )
    }
}

export default ClassComp

 

FuncComp.jsx

import React from 'react'

const FuncComp = () =>{
    return(
        <li className="funcComp">
            Function Component
        </li>
    ) 
}

export default FuncComp

App.jsx 로 가져오기

import React, { Component } from 'react'
import ClassComp from './component/ClassComp'
import FuncComp from './component/FuncComp'

class App extends Component {
    render() {
        return (
            <>
                <h1>Hello React</h1>
                <ul className="Comp">
                    <ClassComp />
                    <FuncComp />
                    <ClassComp />
                    <FuncComp />
                </ul>
            </>
        )

    }
}
// module.exports => require 같은 것  기본 js 모듈 언어 
// export default App =>import 같은 것  => babel 덕분에 가능 
export default App

 

 

 

CSS 연결하기 

 

1) 흔히 웹페이지에서 만드는 방식

2) 웹팩에서 처리하는 방식 

 

 

1). 흔히 웹페이지에서 만드는 방식

css 폴더 만들기 - index.css 파일 만들기 

 

index.css

*{
    margin:0;
    padding:0;
}

ul,li{
    list-style:none;
    padding:5px;
    margin:5px;
    
}

body{
    background-color: #000;
    color:#Fff
}

.Comp{
    border: 3px solid blue
}

.classComp{
    border:3px solid red
}

.funcComp{
    border:3px solid yellow
}

 

index.jsx 에 css 연결

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./css/index.css">
</head>
<body>
    <div id ="root"></div>
    <script type="text/javascript" src="./dist/app.js"></script>
    <!--
        위코드 - index.jsx + app.jsx 을 합쳐서 = app.js 에 담음 
        dev server는 -> dist - app.js 가 안보이지만 실제로 돌아가고 있음 ! 
    
    -->
</body>
</html>

 

 

 

 

 

2. 웹팩으로 하는 법

 

 

1. 서버를 끄고 아래 명령어 실행 

$ npm i -D css-loader   // react 파일에서 css 불러오는 능력을 가진 아이 (react page에서 import css 할 수 있) - > 웹팩에서 쓸 수 있도록
$ npm i -D style-loader   // css-loader가 가지고 온걸 style tag로 감싸는 아이
$ npm i -D mini-css-extract-plugin

 

2. css 연결위한 webpack.config.js 수정 

 

webpack.config.js - module안에서부터 작업을 시작  - rules [ {}  ] 현재 배열안에 객체 1 개 상태 (좀 길긴 함) 

rules의 두 번째 객체에 css를 넣어줄 것 !! 

 

webpack.config.js

const path = require('path')
const webpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')  //추가 
const webpack = require('webpack')


module.exports = {  //module.exports부터 무조건 쓰기 ! 
    name:'firstWebpack', //webpack의 이름  / 안적어도 된다. 
    mode:'development', //어떤 용도로 개발을 할 것이냐 
    devtool:'eval',   // eval -> 개발용 , hidden-source-map -> 배포용 

    resolve:{
        extensions:['.js', '.jsx']
    },

    entry:{
        app:['./index.jsx']
    },

    // module을 통해 babel or sth 통해 해석해야하는구나 알도록 설정
    // 외부파일 가져와서 읽을 때 사용하는 
    // babel은 js 뿐만 아니라 다른 파일도 읽을 수 있음 -> 규칙 정해주기
    module:{
        rules:[{
            test:/\.jsx?$/,  //확장자 .js / .jsx 가능하게
            loader:'babel-loader', // webpack - babel 이해해주는 아이
            // babel 내용 바꾸고 싶을 때 ex) plugin, preset..
            options:{
                presets:[
                    ['@babel/preset-env', {
                        targets:{
                            browsers:['>5% in KR','last 2 chrome versions']
                        },
                        debug:true,
                    }], 
                    '@babel/preset-react'
                ],
                plugins:[
                    'react-refresh/babel'
                ]
            }
        },{
            test:/\.css$/,
            //js에서 css파일 읽어서 어떻게 작동시킬지 적기 
            //뒤에 있는 css-loader부터 실행 -> style-loader 실행 
            //style-loader는 css-loader 없이 사용이 안됨! 
            use:['style-loader','css-loader']
        }]
    },
    plugins:[
        new webpackPlugin(),
        new webpack.LoaderOptionsPlugin({debug:true})
    ],

    output:{
        path:path.join(__dirname,'dist'),
        filename:'app.js', 
        //정적 파일로 바꾼다. 
        publicPath:'/dist'
    },

    // 실행할 때 
    devServer:{
        publicPath:'/dist',
        hot:true, // hot reload 
    }
}

 

 

 

 

3. index.html  -> css link style sheet 삭제 

-> 다시 브라우저 보면 css 사라져있음

 

 

4. index.jsx 에 css import 

import React,{Component} from 'react'
import ReactDOM from 'react-dom'

import App from './app'
import './css/index.css'  //추가 


ReactDOM.render(
    <App />,
    document.querySelector('#root')
)

 

head에 style이 생김 ! 

 

css-loader in webpack.config -> 아래처럼 import를 가능하게 함. 

import './css/index.css'  //추가

style-loader -> 

 

 

 

5. css 폴더 안 ClassComp.css / FuncComp.css 작성 = > 나눠 담기 

classComp.css

.classComp{
    border:3px solid red
}

funcComp.css

.funcComp{
    border:3px solid yellow
}

 

 

ClassComp.jsx에 css넣기

import React, {Component} from 'react'
import '../css/classComp.css'


class ClassComp extends Component{
    render(){
        return(
            <li className="classComp">
                Class Component
            </li>
        )
    }
}

export default ClassComp

FuncComp.jsx 에 css 넣기

import React from 'react'
import '../css/funcComp.css'

const FuncComp = () =>{
    return(
        <li className="funcComp">
            Function Component
        </li>
    ) 
}

export default FuncComp

-> 그래도 style 이 위처럼 다다다 붙어서 변수 명 겹치는걸 100% 방지하긴 어려울 수도... 방법은 -> 코드스프릿팅 (?) 

 

 

 

 

 

 

6. 위의 style 3개를 한 파일로 합쳐주기 

요거 해주는 아이가 mini-css-extract-plugin 

 

webpack.config.js 에 가져오기 

const path = require('path')
const webpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')   
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')   //추가

 

config

const path = require('path')
const webpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin') 
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')


module.exports = {  //module.exports부터 무조건 쓰기 ! 
    name:'firstWebpack', //webpack의 이름  / 안적어도 된다. 
    mode:'development', //어떤 용도로 개발을 할 것이냐 
    devtool:'eval',   // eval -> 개발용 , hidden-source-map -> 배포용 

    resolve:{
        extensions:['.js', '.jsx']
    },

    entry:{
        app:['./index.jsx']
    },

    // module을 통해 babel or sth 통해 해석해야하는구나 알도록 설정
    // 외부파일 가져와서 읽을 때 사용하는 
    // babel은 js 뿐만 아니라 다른 파일도 읽을 수 있음 -> 규칙 정해주기
    module:{
        rules:[{
            test:/\.jsx?$/,  //확장자 .js / .jsx 가능하게
            loader:'babel-loader', // webpack - babel 이해해주는 아이
            // babel 내용 바꾸고 싶을 때 ex) plugin, preset..
            options:{
                presets:[
                    ['@babel/preset-env', {
                        targets:{
                            browsers:['>5% in KR','last 2 chrome versions']
                        },
                        debug:true,
                    }], 
                    '@babel/preset-react'
                ],
                plugins:[
                    'react-refresh/babel'
                ]
            }
        },{
            test:/\.css$/,
            //js에서 css파일 읽어서 어떻게 작동시킬지 적기 
            //뒤에 있는 css-loader부터 실행 -> style-loader 실행 
            //style-loader는 css-loader 없이 사용이 안됨! 
            use:[MiniCssExtractPlugin.loader,'css-loader']  //수정 111
        }]
    },


    plugins:[
        new webpackPlugin(),
        new webpack.LoaderOptionsPlugin({debug:true}),
        //() 매서드 실행시켜주기 
        // app.css 파일 명으로 만들어서 하나로 묶어 주겠다. 
        new MiniCssExtractPlugin({filename:'app.css'}) //수정 222
        // 그럼 아래에 output 경로로 css 가 생긴다. 
    ],

    output:{
        path:path.join(__dirname,'dist'),
        filename:'app.js', 
        //정적 파일로 바꾼다. 
        publicPath:'/dist'
    },

    // 실행할 때 
    devServer:{
        publicPath:'/dist',
        hot:true, // hot reload 
    }
}

 

-> server 끄고 다시 실행  -> 

 

app.js 나오는지 확인

 

가상(?)으로 만든 app.css 를 index.html 에 추가

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel ="stylesheet" href="./dist/app.css">
</head>
<body>
    <div id ="root"></div>
    <script type="text/javascript" src="./dist/app.js"></script>
    <!--
        위코드 - index.jsx + app.jsx 을 합쳐서 = app.js 에 담음 
        dev server는 -> dist - app.js 가 안보이지만 실제로 돌아가고 있음 ! 
    
    -->
</body>
</html>

잘 됨 신기하군,,,

 

 

--> 웹팩사용하여 css 불러오기 

 

CRA 로 배우게되면 위의 기술을 react 기술이라고 오해할 수도..! 

 

 

 

 

 


 

 

 

 

위의 기술 활용해서 HEADER 만들어 보기 ! 

 

 

React, 웹팩, css, 간단한 반응형 

 

1. 해당 package.json / webpack.config.js 복사 + 다른 파일들 만들어서 기본 세팅해주기

 

 

이번에는 0706webpack 폴더 안에 0706header 폴더에 만듬 ! 

 

-> npm i  -> 또 에러나서 -> 위의 오류 대처대로 하니깐 실행됨 ! 

 

 

 

 

 

 

 

 

 

 

 

 

<전체적인 폴더트리>

 

2. 파일을 먼저 위 그림처럼 생성하기 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. index.jsx & App 연결 

 

 

4. App component에서 Navbar 불러오기 

 

 

5. server 잠시 실행 끊기 -> package 다운

$ npm i react-icons

navbar.jsx

import React,{Component} from'react'
import '../css/navbar.css'
import {FaFacebook, FaInstagram, FaBeer} from 'react-icons/fa'   //추가 1

class Navbar extends Component{
    render(){
        return(
            <ul>
                <li><FaFacebook/></li>   //수정1
                <li><FaInstagram/></li>   //수정2
                <li><FaBeer> 콜 </li>       //추가 2
            </ul>
        )
    }
}

export default Navbar

 

React-icon 사이트 설명이 잘 되어 있음 ! 

https://react-icons.github.io/react-icons/

 

React Icons

React Icons Include popular icons in your React projects easily with react-icons, which utilizes ES6 imports that allows you to include only the icons that your project is using. Installation (for standard modern project) npm install react-icons --save Usa

react-icons.github.io

 

 

 

 

6. 배열을 하나 만들어서 반복문으로 출력하기 

Navbar.jsx

import React, { Component } from 'react'
import '../css/navbar.css'
import { FaFacebook, FaInstagram, FaBeer, FaTwitter } from 'react-icons/fa'

class Navbar extends Component {
    state = {
        social: [
            {
                id:1,
                url:'https://www.twitter.com',
                icon: <FaTwitter />
            },
            {
                id:2,
                url:'https://www.facebook.com',
                icon: <FaFacebook />
            },
            {
                id:3,
                url:'https://www.instagram.com',
                icon: <FaInstagram />
            }
        ]
    }


    render() {
        return (
            <ul className="social-icons">
                <li><FaFacebook /></li>
                <li><FaInstagram /></li>
                <li><FaBeer /> </li>
            </ul>
        )
    }
}

export default Navbar

React에서 반복문 지원 자체를 안함 for 문 자체를 ,,,

    render() {
        return (
            <nav>
                <div className="nav-center">
                    <ul className="social-icons">
                        {
                            this.state.social.map(item => {
                                const { id, url, icon } = item
                                return (
                                    <li key={id}>
                                        <a href={url}>{icon}</a>
                                    </li>
                                )
                            })
                        }
                    </ul>
                </div>
            </nav>
        )
    }

a 는 React에서 잘 쓰지않지만 여기서는 연습용 ! 

 

 

 

7. div 더 추가 그리고 아래 li 들을 다시 반복문으로 만들어보기 

    render() {
        return (
            <nav>
                <div className="nav-center">
                    {/*logo*/}
                    <div className="nav-header">
                        <h1 className="logo">Logo</h1>
                    </div>
                    {/* navigation */}
                    <div className="links-container">
                        <ul>
                            <li><a href="#">1</a></li>
                            <li><a href="#">2</a></li>
                            <li><a href="#">3</a></li>
                        </ul>
                    </div>
                    {/* socia-icons */}
                    <ul className="social-icons">
                        {
                            this.state.social.map(item => {
                                const { id, url, icon } = item
                                return (
                                    <li key={id}>
                                        <a href={url}>{icon}</a>
                                    </li>
                                )
                            })
                        }
                    </ul>
                </div>
            </nav>
        )
    }

↓↓

import React, { Component } from 'react'
import '../css/navbar.css'
import { FaFacebook, FaInstagram, FaBeer, FaTwitter } from 'react-icons/fa'

class Navbar extends Component {
    state = {
        social: [
            {
                id: 1,
                url: 'https://www.twitter.com',
                icon: <FaTwitter />
            },
            {
                id: 2,
                url: 'https://www.facebook.com',
                icon: <FaFacebook />
            },
            {
                id: 3,
                url: 'https://www.instagram.com',
                icon: <FaInstagram />
            }
        ],

        menu: [
            {
                id:1,
                url:'/',
                text:'coconut'
            },
            {
                id:2,
                url:'/',
                text:'banana'
            },
            {
                id:3,
                url:'/',
                text:'mango'
            }
        ]
    }


    render() {
        return (
            <nav>
                <div className="nav-center">
                    {/*logo*/}
                    <div className="nav-header">
                        <h1 className="logo">Logo</h1>
                    </div>
                    {/* navigation */}
                    <div className="links-container">
                        <ul>
                            {
                                this.state.menu.map(item=>{
                                    let {id, url, text} = item
                                    return(
                                        <li key={id}>
                                            <a href={url}>{text}</a>
                                        </li>
                                    )
                                })
                            }
                        </ul>
                    </div>
                    {/* socia-icons */}
                    <ul className="social-icons">
                        {
                            this.state.social.map(item => {
                                let { id, url, icon } = item
                                return (
                                    <li key={id}>
                                        <a href={url}>{icon}</a>
                                    </li>
                                )
                            })
                        }
                    </ul>
                </div>
            </nav>
        )
    }
}

export default Navbar

 

 

 

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./dist/app.css">  //추가 
</head>
<body>
    <div id = 'root'></div>
    <script type="text/javascript" src="./dist/app.js"></script>
</body>
</html>

index.jsx

import React from 'react'
import ReactDOM from 'react-dom'

import App from './App'
import '../0706header/css/index.css'

ReactDOM.render(
    <App/>,
    document.querySelector('#root')
)

 

 

 

 

 

navBar에 FaBars 가져오기 

import { FaFacebook, FaInstagram, FaBars, FaTwitter } from 'react-icons/fa'

 

logo 옆에 추가

                    <div className="nav-header">
                        <h1 className="logo">Logo</h1>
                        <button className="nav-toggle">
                            <FaBars />
                        </button>
                    </div>

 

index.css

*{padding:0;margin:0;}


ul,li{list-style:none;}
a{ text-decoration:none;}


/* NavBar */

NavBar .css

/* mobile */

.nav-header{
    display:flex;
    align-items: center;
    justify-content: space-between; /* 양쪽 끝 */
    padding:1rem;
}


.logo{
    font-size: 3rem;
}

/* rem 확대 축소 비율로 늘어남 */ 

.links-container{
    height:0;
    overflow:hidden;
}

.social-icons{
    height:0;
    overflow:hidden;
}

.nav-toggle{
    font-size:3rem;
    /*투명하게 만들기 */
    background:transparent;
    border-color:transparent;
    color:blue;
}

/* PC css style */
@media screen and (min-width:800px){


    .logo{
        font-size: 4rem;
    }

    .nav-toggle{
        /*pc 경우에 토글 안보이게*/ 
        font-size: 0px;
        color:blue;
    }

    .nav-center{
        max-width:1170px;
        margin:0 auto;
        display: flex;
        align-items:center;
        justify-content: space-between;
        padding:1rem;
    }

    .links-container{
        height:auto;
    }

    .links{
        display: flex;
    }
    .links>li>a{
        margin:0 0.5rem;
        color:blue;
        font-size: 0.75rem;
    }

    .social-icons{
        display:flex;
        height:auto;
    }

    .social-icons>li>a{
        margin: 0 .5rem;
        color: red;
    }

}

pc일때
mobile 일 때 

 

 

 

반응형