JiwonDev

React #4 ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ๋ฐ ์ปดํฌ๋„ŒํŠธ์˜ ์ดํ•ด

by JiwonDev

๋ฆฌ์•กํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ View ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ

ํŠน๋ณ„ํ•œ ๋ฌธ๋ฒ• ๊ณต๋ถ€ ์—†์ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์•ˆ๋‹ค๋ฉด ์œ ์‚ฌํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ฃผ๋กœ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ๋งŽ์ด ์ž‘์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ด ๊ธ€์—์„œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ *๋”๋ณด๊ธฐ arr.map(callback, [thisArg]) ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋”๋ณด๊ธฐ

arr.map(callback, [thisArg])

Array.prototype.map( )

 

callback ํ•จ์ˆ˜๋ฅผ ์ฃผ๋ฉด, ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ํ•ด๋‹น ํ•จ์ˆ˜ ์ ์šฉ ์‹œํ‚จ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋‹จ, ์›๋ณธ ๋ฐฐ์—ด์€ ์ˆ˜์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

[thisArg]๋ฅผ ์ž…๋ ฅํ•œ๋‹ค๋ฉด ์ฝœ๋ฐฑํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•  this ๊ฐ’์„ ์„ค์ • ํ•ด ์ค„์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

์ฝœ๋ฐฑ ํ•จ์ˆ˜

callback ( currentValue, [index ,[array]] )

currentValue๋Š” ํ˜„์žฌ ์ฒ˜๋ฆฌ ์ค‘์ธ ์š”์†Œ, index๋Š” ์ฒ˜๋ฆฌ ์ค‘์ธ ์š”์†Œ์˜ ์ธ๋ฑ์Šค, array๋Š” ์ „์ฒด ๋ฐฐ์—ด ๊ฐ’์ž…๋‹ˆ๋‹ค. 

๋ณดํ†ต ์ฝœ๋ฐฑํ•จ์ˆ˜๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ ๋งŽ์ด ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

let numbers [ 1,2,3,4,5 ];
let myCallback = fucntion(num,index){
	return num+index;
}

// ์•„๋ž˜ 2๊ฐœ์˜ ๋ฐฐ์—ด์˜ ๊ฒฐ๊ณผ ๊ฐ’์€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
let newNumbers1 = number.map(myCallback);
let newNumbers2 = numbers.map( (num,index) => num+inedx );

#1. ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐํ™”

๋ฆฌ์•กํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ view๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

class Contact extends React.Component {
    render() {
        return (
            <div>
                <div>Jiwo1 010-9999-9991</div>
                <div>Jiwo2 010-9999-9992</div>
                <div>Jiwo3 010-9999-9993</div>
                <div>Jiwo4 010-9999-9994</div>
            </div>
        )
    }
}

์œ„ ์ฝ”๋“œ๋ฅผ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ์ฒดํ™” ์‹œํ‚ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class ContactInfo extends React.Component {
// ContactInfo๋ฅผ ๊ฐ์ฒดํ™” ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.
    render() {
        return (
            <div>
                {this.props.contact.name}
                {this.props.contact.phone}
            </div>
        );
    }
}

class Contact extends React.Component {
    constructor(props) {
        super(props);
        this.state={ 
        // ๋ฐ์ดํ„ฐ๋ฅผ [๊ฐ์ฒด, ๊ฐ์ฒด...] ํ˜•ํƒœ๋กœ state์— ๋“ฑ๋กํ•˜์˜€์Šต๋‹ˆ๋‹ค.
            contactData:[
                {name:'Jiwo1',phone:'010-9999-9991'},
                {name:'Jiwo2',phone:'010-9999-9992'},
                {name:'Jiwo3',phone:'010-9999-9993'},
                {name:'Jiwo4',phone:'010-9999-9994'},
            ]
        }
    }

    render() { 
    /* ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ contactData๋ฅผ ๋ฐ›์œผ๋ฉด
     <ContactInfo/> ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
     ์ฐธ๊ณ ๋กœ ์ด๋Ÿฐ์‹์œผ๋กœ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ์ƒ์„ฑํ•  ๋•Œ ๊ฐ์ฒด๋ณ„๋กœ key๊ฐ’์„ ๋”ฐ๋กœ ์ฃผ์ง€ ์•Š์œผ๋ฉด 
     ๋ฆฌ์•กํŠธ ์ž์ฒด์—์„œ ๊ฒฝ๊ณ ๋ฅผ ๋„์šฐ๋‹ˆ key={index}๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ธ๋ฑ์Šค๊ฐ’์„ ํ‚ค๋กœ ์ค์‹œ๋‹ค.
    */
        const mapToComponent = (contactData) => {
          return contactData.map((contac,index) => {
              return (<ContactInfo contact={contac} key={index}/>)
          })
        };

        return (
            <div>
            // ์œ„์—์„œ ๋งŒ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ.
                {mapToComponent(this.state.contactData)}
            </div>
        )
    }
}

#2. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

์šฐ์„ , ๋ธŒ๋ผ์šฐ์ € ๋ฐ–์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋Ÿฐํƒ€์ž„ Node.js๋ฅผ ์„ค์น˜ํ•ด์ค๋‹ˆ๋‹ค.

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

๊ทธ๋ฆฌ๊ณ  Node.js์—์„œ ์ œ๊ณตํ•˜๋Š” npm(node Package Manager)์„ ํ†ตํ•ด ํ˜„์žฌ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” webpack๋„ ์„ค์น˜ํ•ด์ค์‹œ๋‹ค.

npm install --global webpack webpack-dev-server


--global (๋˜๋Š” -g)
: ํ•ด๋‹น ์ปดํ“จํ„ฐ์˜ ๋ชจ๋“  ํ”„๋กœ์ ํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

webpack : ๋ธŒ๋ผ์šฐ์ € ์œ„์—์„œ import๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ณ , .jsํŒŒ์ผ๋“ค์„ ํ•˜๋‚˜๋กœ ๊ตฌ์กฐํ™” ์‹œ์ผœ์ค๋‹ˆ๋‹ค.

webpack-dev-server : ๋ณ„๋„์˜ ์„œ๋ฒ„ ์—†์ด๋„ static ํŒŒ์ผ์„ ๋‹ค๋ฃจ๋Š” ์›น ์„œ๋ฒ„๋ฅผ ์—ด ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋ฉฐ ์ฝ”๋“œ๊ฐ€ ์ˆ˜์ •๋  ๋•Œ ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ๋ฆฌ๋กœ๋“œ ๋˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(hot-loader ๊ธฐ๋Šฅ)

 

npm init ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด node.js์˜ ๊ธฐ๋ณธ ์„ค์ •ํŒŒ์ผ(package.json ๋“ฑ)์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. 

๋˜๋Š” ์‚ฌ์šฉํ•˜์‹œ๋Š” IDE ํŽธ์ง‘๊ธฐ์˜ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๋…ธ๋“œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜์…”๋„ ๋ฉ๋‹ˆ๋‹ค.

(์ฐธ๊ณ ๋กœ npx create-react-app ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ์•„๋ž˜์˜ ๊ณผ์ •์„ ํฌํ•จํ•œ ๊ธฐ๋ณธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

 

๊ทธ๋ฆฌ๊ณ  react ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๋Ÿฐํƒ€์ž„(react-dom)์„ ์„ค์น˜ํ•ด์ค์‹œ๋‹ค.

์ฐธ๊ณ ๋กœ --save๋Š” ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์˜ node ์„ค์ •ํŒŒ์ผ(package.json)์— ์„ค์น˜๋‚ด์šฉ์„ ์ €์žฅํ•˜๋Š” ๋ช…๋ น์–ด์ž…๋‹ˆ๋‹ค.

npm install --save react react-dom

๋ฆฌ์•กํŠธ JSX ๋ฌธ๋ฒ•๊ณผ webpack์„ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•ด์„œ ์•„๋ž˜์˜ ๋ฆฌ์•กํŠธ ๊ฐœ๋ฐœ ์˜์กด ๋ชจ๋“ˆ๋„ ์„ค์น˜ํ•ด์ค์‹œ๋‹ค.

--save-dev๋Š” --save์™€ ๋™์ผํ•˜์ง€๋งŒ, ํ˜„์žฌ ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ์šฉ์œผ๋กœ ์„ค์น˜ํ•˜์—ฌ ๋‚˜์ค‘์— ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ๋ฅผ ํŽธํ•˜๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

npm install --save-dev babel-core bable-loader babel-preset-es2015 babel-preset-react
npm install --save-dev react-hot-loader webpack webpack-dev-server

 

๊ทธ๋ฆฌ๊ณ  package.json ์— ๋“ค์–ด๊ฐ€ sciprts๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

...
"script" : {
"test" : "..."
"dev-server" : "webpack-dev-server"
}

์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๋ฉด ์•ž์œผ๋กœ npm run dev-server ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹คํ–‰ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


#2-1 Webpack ์„ค์ •

node๋กœ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋“ค์„ ๋ชจ๋‘ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด, Webpack ์„ค์ •ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์ค์‹œ๋‹ค. ๋ณต์‚ฌํ•ด์„œ ์ƒ์„ฑํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

/webpack.config.js

var webpack = require('webpack');

module.exports = {
    entry: './src/index.js',

    output: {
        path: __dirname + '/public/',
        filename: 'bundle.js'
    },

    devServer: {
        hot: true,
        inline: true,
        host: '0.0.0.0',
        port: 4000,
        contentBase: __dirname + '/public/',
    },

    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel',
                exclude: /node_modules/,
                query: {
                    cacheDirectory: true,
                    presets: ['es2015', 'react']
                }
            }
        ]
    },

    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ]
}

 

์ฐธ๊ณ ๋กœ ์œ„ ์ฝ”๋“œ์˜ ์„ค๋ช…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

// ES5 ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋‚ด์žฅํ•จ์ˆ˜ (ES6๋ถ€ํ„ฐ๋Š” import)
var require = function(src){       //line 1 ์ธ์ž๋ฅผ ๋ฐ›์•„์™€์„œ
    var fileAsStr = readFile(src)  //line 2 ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ๋ถˆ๋Ÿฌ์˜จ ํ›„
    var module.exports = {}        //line 3 exports ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ 
    eval(fileAsStr)                //line 4 ์†Œ์Šค๋ฅผ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. exports์— key:value๋กœ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.
    return module.exports          //line 5 ์™„์„ฑ๋œ exports๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
}
// npm ์„ค์น˜ํ•œ webpack ์ฝ”๋“œ๋ฅผ require (ES6์ดํ›„์—์„œ๋Š” import ํ‚ค์›Œ๋“œ)๋กœ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
// require ํ•จ์ˆ˜๋Š” ํ•ด๋‹น ์ฝ”๋“œ๋‚ด์— module.exports๋ฅผ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค.
var webpack = require('webpack');

// ๋‹ค๋ฅธ ์™ธ๋ถ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก exports๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.
// ์ฐธ๊ณ ๋กœ module.exports ์™€ exports ํ‚ค์›Œ๋“œ๋Š” ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ํ•ฉ๋‹ˆ๋‹ค.
module.exports = {
    entry: './src/index.js',
	// entry์— ํ•„์š”ํ•œ ๋ชจ๋“ˆ๋“ค์„ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๊ฐœ๋ผ๋ฉด [ a, b... ] 
    
    output: { // ํ•ฉ์นœ ๋ชจ๋“ˆ ํŒŒ์ผ๋“ค์„ ์ €์žฅํ•  ๊ฒฝ๋กœ
        path: __dirname + '/public/',
        filename: 'bundle.js'
    },

    devServer: { // ๊ฐœ๋ฐœ์šฉ Server ์„ค์ •์ž…๋‹ˆ๋‹ค.
        hot: true, // hot-loader ์˜จ์˜คํ”„
        inline: true, // hot-loader์˜ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋ฒˆ๋“ค์— ๊ฐ™์ด ๋„ฃ์–ด์คŒ
        host: '0.0.0.0', // ๊ธฐ๋ณธ๊ฐ’์€ localhost, ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์šฐ๋“œ์— ๋”ฐ๋ผ ์„ค์ •
        port: 4000, // ํฌํŠธ ๋ณดํ†ต 3000,4000
        contentBase: __dirname + '/public/', //์ •์ ์ธ Content๋ฅผ ์ €์žฅํ•  ํด๋”. ๊ธฐ๋ณธ์€ Public
    },

    module: { //babel ์„ค์ •
        loaders: [ // ์ปดํŒŒ์ผ ์ด ์™ธ์—๋„ less, sass, HTML-mini ๋“ฑ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์„ค์ •๊ฐ€๋Šฅ.
            {
                test: /\.js$/,
                loader: 'babel',
                exclude: /node_modules/,
                query: {
                    cacheDirectory: true,
                    presets: ['es2015', 'react']
                }
            }
        ]
    },

    plugins: [ // webpack-hot-loader๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์ถ”๊ฐ€
        new webpack.HotModuleReplacementPlugin()
    ]
}

# 2-2 HTML ๋ฐ JS ์ž‘์„ฑ

public ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ , ํ•ด๋‹น ํด๋”์•ˆ์— index.html์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ public ํด๋”์•ˆ์—๋Š” ์ด๋Ÿฌํ•œ ์ •์ ์ธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉฐ webpack์˜ ๊ด€๋ฆฌ๋Œ€์ƒ์— ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>React App</title>
</head>
<body>
    <div id="root"></div>
    <script src="bundle.js"></script>
    <!-- bundle.js ๋Š” Webpack์—์„œ output์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. -->
</body>
</html>

๊ทธ๋ฆฌ๊ณ  ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค.

src/components/ ์™€ src/index.js ๋ฅผ ๋งŒ๋“ค๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” ํ•ด๋‹น ํด๋”์— ๋ชจ์•„๋‘˜๊ฒ๋‹ˆ๋‹ค.

 

 

webpack ์—์„œ ES5๋กœ ์„ค์ •ํ•˜์˜€์œผ๋ฏ€๋กœ ES6 ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ• ๋ ค๋ฉด ๋”ฐ๋กœ ์„ค์ •์„ ํ•ด์ฃผ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์— .jshintrc ๋ฅผ ๋งŒ๋“ค์–ด ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ค์‹œ๋‹ค.

{
  "esversion" : 6
}

 

์ด ๊ณผ์ •์„ ๋งˆ์ณค๋‹ค๋ฉด ํ”„๋กœ์ ํŠธ ๊ตฌ์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋Œ€๋žต์ ์ธ ํ”„๋กœ์ ํŠธ์˜ ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ–ˆ๋‹ค๋ฉด, ๋‹ค์Œ ๊ธ€์—์„œ๋Š” npx create-react-app ์œผ๋กœ ๊ธฐ๋ณธ ํ”„๋กœ์ ํŠธ ํ‹€(๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ)๋ฅผ ์ด์šฉํ•˜์—ฌ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

'๐Ÿ–ผFront > React' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

๋ฆฌ์•กํŠธ์™€ Virtual DOM  (0) 2021.04.16
React #5 create-react-app  (0) 2021.04.05
React #3 props & state  (0) 2021.04.05
React #2 ๋ฆฌ์•กํŠธ.JS  (0) 2021.04.05
React #1 ๊ฐœ๋…  (0) 2021.03.29

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ