๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋ฒˆ์—ญ

๋ฆฌ์•กํŠธ๋กœ ์ฑ„ํŒ… ํ”„๋ก ํŠธ์—”๋“œ ๊ตฌ์ถ•ํ•˜๊ธฐ [๋ฒˆ์—ญ]

by Whiimsy 2022. 5. 31.

 

๐Ÿฑ‍๐Ÿ‘ค ์›๋ฌธ : https://bhavaniravi.medium.com/learn-reactjs-by-building-a-chat-frontend-2d8fe664276e

 

Learn ReactJs by Building a Chat FrontEnd

Building a Chat application from scratch using ReactJs

bhavaniravi.medium.com

 

๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฑ„ํŒ… ์‘์šฉํ”„๋กœ๊ทธ๋žจ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ž‘์„ฑํ•ด๋ณด์ž.

๐Ÿฅ— ๋ฆฌ์•กํŠธ๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

React๋Š” ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋นŒ๋“œํ•˜๊ธฐ ์œ„ํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. ํŽ˜์ด์Šค๋ถ๊ณผ ๊ฐœ์ธ ๊ฐœ๋ฐœ์ž ๋ฐ ๊ธฐ์—… ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์˜ํ•ด ์œ ์ง€ ๋ณด์ˆ˜๋œ๋‹ค. — Wikipedia

 

๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด HTML + JS + CSS = React์ด๋‹ค.

 

๐Ÿฅ— ์™œ ๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€?

  • ๋‚˜๋Š” ์ตœ๊ทผ์— ํŒŒ์ด์ฌ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฑ์—”๋“œ๋กœ ํฌ์ง€์…˜์„ ์˜ฎ๊ฒผ๊ณ  ์ด ์ผ์„ ๋” ์ข‹์•„ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๋‚ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‹ค๋ ฅ์ด ํ—›๋˜์ด ๋˜๋Š” ๊ฒƒ์€ ์‹ซ๋‹ค.
  • ๋‚ด ์นœ๊ตฌ๋“ค ๋Œ€๋ถ€๋ถ„์ด ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋“ค์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋“ค์˜ ์–ธ์–ด(๋ฆฌ์•กํŠธ ์šฉ์–ด์™€ ๊ทธ๋“ค์ด ๋ฌด์—‡์„ ๋งํ•˜๊ณ  ์žˆ๋Š”์ง€ ๋‘˜ ๋‹ค)๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค๋Š” ์••๋ฐ•๊ฐ์ด ์žˆ๋‹ค.
  • ๋ฆฌ์•กํŠธ๋กœ ๊ตฌ์ถ•ํ•œ ๊ฐœ์ธ ๋น„๋ฅผ ์ด์šฉํ•ด ๋‚˜๋งŒ์˜ ํฌํŠธํด๋ฆฌ์˜ค ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค.
  • ๋ณด๋„ˆ์Šค ํฌ์ธํŠธ: ํ•จ๊ป˜ ์ผํ•˜๊ณ  ์žˆ๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๊ฐ€ "๋ฆฌ์•กํŠธ๋กœ๋Š” ํ•  ์ˆ˜ ์—†๋Š” ์ผ์€ ์—†๋‹ค"๋ผ๊ณ  ๋งํ•˜๊ณ  ๊ฐ”๋‹ค.

๐Ÿฅ— ํ•„์ˆ˜ ์กฐ๊ฑด

HTML, CSS ๋ฐ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ ๊ฐ™์€ ํ”„๋ก ํŠธ์—”๋“œ ๊ธฐ์ˆ ์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.(๋งˆ์Šคํ„ฐํ•  ํ•„์š”๋Š” ์—†๋‹ค.) ์ด ๊ธฐ์ˆ ๋“ค์„ ํ™œ์šฉํ•ด ์›น ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ์ถฉ๋ถ„ํ•˜๋‹ค.

 

๐Ÿฅ— ๋ฆฌ์•กํŠธ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์ ์ธ ์ดํ•ด

React = Component + props + state

 

์ดˆ๋ณด์ž๋กœ์„œ ์ ‘ํ•˜๊ฒŒ ๋  ์„ธ ๊ฐ€์ง€ ๊ธฐ๋ณธ ์šฉ์–ด๋Š” Component, state, props์ด๋‹ค. ์ด ์™ธ์—๋„, "Lazy React", "React Hooks" ๋“ฑ๊ณผ ๊ฐ™์€ ํ™”๋ คํ•œ ์ด๋ฆ„๋“ค์„ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ๋“ค์€ ๋‚ด ๋ชฉ๋ก์—๋Š” ์žˆ์ง€๋งŒ ์ด ๋ธ”๋กœ๊ทธ์—๋Š” ์—†๋‹ค.

 

๐Ÿฅ— ์–ด๋–ป๊ฒŒ ์‹œ์ž‘ํ•˜๋Š”๊ฐ€?

๋‚˜๋Š” ๋ฌธ์„œํ™” ์ž‘์—…๊ด‘์ด๋‹ค. ๋ฌธ์„œํ™”์™€ ๊ทธ ๋ฌธ์„œ๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๋•Œ ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค๋‚˜ ํŠœํ† ๋ฆฌ์–ผ์„ ์ฐพ๋Š” ๋ฐ ์—„์ฒญ๋‚œ ์‹œ๊ฐ„์„ ํ• ์• ํ•œ๋‹ค.

๋ฆฌ์•กํŠธ ๊ณต์‹ ๋ฌธ์„œ์˜ ํŠœํ† ๋ฆฌ์–ผ์€ tic tac toe ๊ฒŒ์ž„์„ ํ†ตํ•ด Component๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  state ๋ฐ props๋ฅผ ๊ฐ€์ง€๊ณ  ๋…ธ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค ์ค€๋‹ค. ๋‚œ ๊ทธ ํŠœํ† ๋ฆฌ์–ผ์„ ์™„๋ฃŒํ–ˆ์ง€๋งŒ ํ”„๋กœ์ ํŠธ์— ์–ด๋–ป๊ฒŒ ์ ์šฉํ•ด์•ผ ํ• ์ง€ ์ „ํ˜€ ์ดํ•ดํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.

๋๋‚ด ๋‚ด๊ฒŒ ํšจ๊ณผ๊ฐ€ ์žˆ์—ˆ๋˜ ๊ฒƒ์€ "๋ฆฌ์•กํŠธ๋กœ ์‚ฌ๊ณ ํ•˜๊ธฐ" ๋ถ€๋ถ„์ด์—ˆ๋‹ค. ์ด ๋ถ€๋ถ„์—์„  ์›น ํŽ˜์ด์ง€๋ฅผ Component๋กœ ๋ถ„ํ• ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์ด๋Ÿฌํ•œ Component์— state, props๋ฅผ ๋„์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค€๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ์ข‹์€ ์ ์€ ์‹ค์ œ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” ๋ฐฉ์‹๊ณผ ๋งค์šฐ ๋น„์Šทํ•˜๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋Š” ํ•ญ์ƒ ๋””์ž์ธ์„ ๊ฐ€์ง€๊ณ  ์ผํ•œ๋‹ค. ๋”ฐ๋ผ์„œ tic tac toe ๊ฒŒ์ž„์ฒ˜๋Ÿผ ๋นˆ ์Šฌ๋ ˆ์ดํŠธ๋กœ ๋ฆฌ์•กํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์€ ํฐ ๋„์›€์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.

 

๐Ÿฅ— ๋ฌด์—‡์„ ๋งŒ๋“ค ๊ฒƒ์ธ๊ฐ€?

๋‚˜๋Š” HTML, CSS ๋ฐ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋งŒ์„ ์‚ฌ์šฉํ•ด ์ด ๊ณตํ†ต ํ”„๋ก ํŠธ์—”๋“œ ์ฑ„ํŒ… ๋ชจ๋“ˆ์„ ๊ตฌ์ถ•ํ–ˆ๋‹ค. ๋‚ด ํ…œํ”Œ๋ฆฟ์—์„  ์ฑ—๋ด‡์„ ๋งŒ๋“ค๊ณ  ๊ฐ€์ง€๊ณ  ๋†€ ์ˆ˜ ์žˆ๋‹ค. ๋‚ด ๋Œ€๋ถ€๋ถ„์˜ ์ทจ๋ฏธ์šฉ ์ฑ—๋ด‡ ํ”„๋กœ์ ํŠธ๋Š” ์ด ํ…œํ”Œ๋ฆฟ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

๋‚˜์˜ ์ตœ์ข… ๋ชฉํ‘œ๋Š” ๋ฐฑ์—”๋“œ API๋กœ ๋ฉ”์„ธ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ์ฑ„ํŒ… ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ๋‚ด GitHub์— ์žˆ๋Š” ์ฝ”๋“œ๋กœ ์ง์ ‘ ์‹คํ—˜ํ•˜๊ณ  ์‚ฌ์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿฅ—  ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ค€์—์„œ ์ƒ๊ฐํ•˜๊ธฐ

์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ์›น ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฐœ๋ณ„ UI ์š”์†Œ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์œ„ ์‚ฌ์ง„์„ ๋ดค์„ ๋•Œ, ์•ฝ 4~5๊ฐœ์˜ UI ์š”์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์š”์†Œ๋“ค์„ ๊ฐ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ  ํ•˜๋Š” ๋…๋ฆฝ์ฒด๋กœ ๊ฐ์‹ธ๋Š” ๊ฒƒ์ด๋‹ค. 

 

Send ๋ฒ„ํŠผ (SendButton)

class SendButton extends Component{
    render(){
      return (
         <div className="send_message" 
              <div className="text">send</div>
         </div>);
    }
}

 

ํ…์ŠคํŠธ ๋ฐ•์Šค (MessageTextboxContainer)

class MessageTextBoxContainer extends Component{
  render(){
    return(
      <div className="message_input_wrapper">
        <input id="msg_input" 
               className="message_input" 
               placeholder="Type your messages here..."/> 
      </div>
    );
  }
}

 

์•„๋ฐ”ํƒ€ (Avatar)

์•„๋ฐ”ํƒ€๋Š” ํ”„๋กœํ•„ ์‚ฌ์ง„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ง€๊ธˆ์€ ์‚ฌ๋žŒ๋งˆ๋‹ค ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐฐ๊ฒฝ์˜ ์•„๋ฐ”ํƒ€๋ฅผ ๋ณด์—ฌ์ฃผ๋ ค ํ•œ๋‹ค.

class Avatar extends Component {
  render(){
    return(
      <div className="avatar"/>
    ); }
}

 

๋ฉ”์„ธ์ง€ (MessageBox)

MessageBox ์ปดํฌ๋„ŒํŠธ์—๋Š” Avatar ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋‹ค. ๊ฐ ๋ฉ”์„ธ์ง€์— ๋Œ€ํ•ด ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค.

class MessageBox extends Component{
  render(){
    return(
      <li className={`message ${this.props.appearance} appeared`}>
        <Avatar></Avatar>
        <div className="text_wrapper">
            <div className="text">{this.props.message}</div>
        </div>
      </li>
    );
  }
}

 

์ „์ฒด ์•ฑ (ChatApp)

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์œ„์—์„œ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋“ค์„ ํ•จ๊ป˜ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ์ „์ฒด UI๋ฅผ ๋งŒ๋“ ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๋ฉ”์„ธ์ง€๊ฐ€ ๋‚˜์—ด๋˜๋Š” ๋ฉ”์„ธ์ง€ ์ปจํ…Œ์ด๋„ˆ, ํ…์ŠคํŠธ ์ƒ์ž ๋ฐ ๋ณด๋‚ด๊ธฐ ๋ฒ„ํŠผ์ด ํฌํ•จ๋œ๋‹ค. ์ผ๋‹จ ์ง€๊ธˆ์€ this.state์™€ this.handleClick์„ ๋ฌด์‹œํ•˜๋„๋ก ํ•˜์ž!

class ChatApp extends Component {
render() {
    return (
      <div className="chat_window">
        <MessagesContainer messages={this.state.messages}/>
        <div className="bottom_wrapper clearfix">
          <MessageTextBoxContainer/>
          <SendButton handleClick={this.handleClick}/>
        </div>
      </div>
    );
  }
}

 

๐Ÿฅ— ์ด๋ฒคํŠธ ์บก์ฒ˜๋ง

์ปดํฌ๋„ŒํŠธ์˜ states์™€ props์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ธฐ ์ „์— ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.

  • ๋ณด๋‚ด๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ๋ฉ”์„ธ์ง€ ๋ณด๋‚ด๊ธฐ
  • ์—”ํ„ฐ ํ‚ค๋ฅผ ๋ˆŒ๋Ÿฌ ๋ฉ”์„ธ์ง€ ๋ณด๋‚ด๊ธฐ

์ด ๋ธ”๋ก์—์„œ๋Š” press_enter ๋ฐ send_button_click ์ด๋ฒคํŠธ๋ฅผ ์บก์ฒ˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ๋‹ค.

๋ณด๋‚ด๊ธฐ ๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ๋กœ ๋Œ์•„๊ฐ€ ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ™์—ฌ๋ณด์ž. ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ํ…์ŠคํŠธ ๋ฐ•์Šค์— onKeyPress ์ด๋ฒคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด ์ด๋ฒคํŠธ๋ฅผ ์บก์ฒ˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

class SendButton extends Component{
    handleClick(){
        console.log("I am captured");
    }
render(){
      return (
         <div className="send_message" 
              onClick={this.props.handleClick}>
              <div className="text">send</div>
         </div>);
    }
}

 

๐Ÿฅ— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง

click ๋ฐ keypress ์ด๋ฒคํŠธ๋ฅผ ์บก์ฒ˜ํ–ˆ์œผ๋‹ˆ ์–ด๋–ป๊ฒŒ ์ด ์ด๋ฒคํŠธ๋“ค์„ ์ฒ˜๋ฆฌํ• ์ง€ ์‚ดํŽด๋ณด์ž. ์—ฌ๊ธฐ๊ฐ€ ๋‚ด๊ฐ€ ์ œ์ผ ํ—ค๋งจ ๋ถ€๋ถ„์ด๋‹ค.

๋ณด๋‚ด๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ Enter ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ…์ŠคํŠธ ๋ฐ•์Šค์— ์ ํ˜€ ์žˆ๋˜ ๋ฉ”์„ธ์ง€๊ฐ€ MessageContainer์˜ ๋ฉ”์„ธ์ง€ ์ปดํฌ๋„ŒํŠธ๋กœ ์ถ”๊ฐ€๋œ๋‹ค.

์ด์ œ ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ฑ„์šฐ๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด์ž. ์ด ๋ฐ์ดํ„ฐ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ state์™€ props์— ์˜ํ•ด ์ •์˜๋œ๋‹ค.

 

States์™€ Props

๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด๊ณ  ๊ทธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ œ ๊ธฐ๋Šฅ์„ ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์‚ดํŽด๋ณด์ž.

  • ๋ณด๋‚ด๊ธฐ ๋ฒ„ํŠผ(Send Button) : ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” current_message๋ฅผ ์ฑ—๋ด‡์œผ๋กœ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ์ ‘๊ทผ ๊ถŒํ•œ์ด ํ•„์š”ํ•˜๋‹ค.
  • ๋ฉ”์„ธ์ง€ ํ…์ŠคํŠธ ๋ฐ•์Šค(Message Text Box) : ์‚ฌ์šฉ์ž๊ฐ€ current_message๋ฅผ ์ž…๋ ฅํ•  ๋•Œ Enter ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋ฉ”์„ธ์ง€๋ฅผ ์ฑ—๋ด‡์œผ๋กœ ์ „์†กํ•˜๋„๋ก ์œ ์ง€ ๋ฐ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•œ๋‹ค.
  • ๋ฉ”์„ธ์ง€ ์ปจํ…Œ์ด๋„ˆ(Message Container) : ๋ด‡๊ณผ ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์„ฑํ•œ ๋ชจ๋“  ๋ฉ”์‹œ์ง€์˜ ๋ชฉ๋ก์„ ์œ ์ง€ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

๋ฉ”์‹œ์ง€ ์ปจํ…Œ์ด๋„ˆ(Message Container)์— ์ง€๊ธˆ ์ž‘์„ฑํ•˜๊ณ  ์žˆ๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ๋„์šฐ๋ ค๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ํ…์ŠคํŠธ ๋ฐ•์Šค(Message Text Box)์— ์ž‘์„ฑํ•œ ๋ฉ”์„ธ์ง€(Current Message)๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค.

 

๋˜ํ•œ ๋ฉ”์‹œ์ง€ ์ปจํ…Œ์ด๋„ˆ(Message Container)๋Š” ์ง€๊ธˆ๊นŒ์ง€ ์ž…๋ ฅ ๋ฐ ์ˆ˜์‹ ๋œ ๋ชจ๋“  ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”์ ํ•ด์•ผ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฉ”์„ธ์ง€๋ฅผ ์†์„ฑ์— ๋”ฐ๋ผ ๋ฐฐ์—ด๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

 

class TextBox extends Component{
constructor(props){
    this.state.current_message = ""
}
onChange(e) {
    this.setState({
      current_message: e.target.value;    
    }); 
    if(e.key === "Enter"){
      // We need to add a new message to MessageContainer component
    }
}
render(){
    return(
      <div className="message_input_wrapper">
        <input ... 
             value={this.props.current_message} 
             onChange={this.props.onChange}/>
      </div>
    );
  }
}

 

ํ…์ŠคํŠธ ๋ฐ•์Šค(TextBox) ์ปดํฌ๋„ŒํŠธ์˜ current_message๋Š” ์ฒ˜์Œ์—” ๋น„์–ด์žˆ์ง€๋งŒ ํ…์ŠคํŠธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๊ฐ’์ด ๋ณ€ํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ…์ŠคํŠธ ๋ฐ•์Šค(TextBox) ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์€ ๋ฉ”์„ธ์ง€ ์ปจํ…Œ์ด๋„ˆ(Message Container)์— ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค.

 

"๋ฆฌ์•กํŠธ์—์„œ ์ƒํƒœ(state) ๊ณต์œ ๋ž€ ํ•ด๋‹น ์ƒํƒœ๊ฐ€ ํ•„์š”ํ•œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ๊ทธ๊ฒƒ์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์„ ์ƒํƒœ(state)๋ฅผ ๋Œ์–ด์˜ฌ๋ฆฐ๋‹ค(lifting up)๊ณ  ๋งํ•œ๋‹ค."

 

์ƒํƒœ ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ(Lifting State Up)

์ด์ œ ์ปจํŠธ๋กค์„ ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๋กœ ์ด๋™์‹œ์ผœ์•ผ ํ•˜๋Š”์ง€๊ฐ€ ๋ฌธ์ œ๋‹ค. ์ปดํฌ๋„ŒํŠธ์˜ ๊ฐ„๋‹จํ•œ ํŠธ๋ฆฌ๋ฅผ ๊ทธ๋ ค๋ณด๊ณ  ๋ฌด์—‡์ด ์ ํ•ฉํ•œ์ง€ ์•Œ์•„๋ณด์ž.

 

ํŠธ๋ฆฌ๋ฅผ ๊ทธ๋ ค๋ณด๋ฉด, ๋ชจ๋“  ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ current_message์™€ ์ง€๊ธˆ๊นŒ์ง€ ์ˆ˜ ๋ฐœ์‹ ๋œ ๋ชจ๋“  ๋ฉ”์„ธ์ง€ ๋ชฉ๋ก์— ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„, ๋ชจ๋“  ์ƒํƒœ(state) ๋ฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ(event handling) ์š”๊ตฌ ์‚ฌํ•ญ์„ ๊ฐ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ์œ„์ž„ํ•˜๋Š” ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ChatApp ํ•˜๋‚˜๋ฟ์ด๋‹ค.

 

์šฐ๋ฆฌ์˜ ChatApp ์ปดํฌ๋„ŒํŠธ๋Š” ์ด์ œ ์•ฝ๊ฐ„ ๋ณต์žกํ•ด์งˆ ๊ฒƒ์ด๋‹ค. ๋จผ์ € ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ์ •์˜ํ•˜๊ณ  ๋‚˜์ค‘์— ํ•„์š”์— ๋”ฐ๋ผ ์ด๋ฒคํŠธ์— ์ถ”๊ฐ€ํ•˜์ž.

 

addMessageBox(enter=true){
  let messages = this.state.messages;
  let current_message = this.state.current_message;
  if(current_message && enter){
    messages = [...messages, {"message":current_message}];
}
handleClick(){
  this.addMessageBox();
}
_handleKeyPress(e) {
  let enter_pressed = false;
  if(e.key === "Enter"){
    enter_pressed = true;
   }
   this.addMessageBox(enter_pressed)
}
render() {
  return (
    <div className="chat_window">
      <MessagesContainer messages={this.state.messages}/>
      <div className="bottom_wrapper clearfix"> . 
       <MessageTextBoxContainer 
           _handleKeyPress={this._handleKeyPress}
           onChange={this.onChange}
           message={this.state.current_message}> .      
       </MessageTextBoxContainer>
      <SendButton handleClick={this.handleClick}/>
      </div>
    </div>
);}

 

์ฝ”๋“œ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ(event handler)์™€ state & props๋ฅผ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ค€์—์„œ ์ •์˜ํ•˜๊ณ  ์ด๋ฅผ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์— ์œ„์ž„ํ•œ๋‹ค.

 


 

ํ”„๋ก ํŠธ์—”๋“œ์™€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹ซ์–ดํ•˜๋˜ ์‚ฌ๋žŒ์—์„œ๋ถ€ํ„ฐ ๊ทธ๊ฒƒ์„ ์ด์šฉํ•ด ์ฑ„ํŒ… ์•ฑ์„ ๋งŒ๋“  ์‚ฌ๋žŒ์ด ๋˜๊ธฐ๊นŒ์ง€, ์ด์ œ ๋‚˜๋Š” ๋ฆฌ์•กํŠธ ๋•๋ถ„์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ข‹์•„ํ•œ๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ค ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ตฌ์ถ•ํ•  ๋•Œ๋„ ๋‚œ ๋ฆฌ์•กํŠธ์™€ ํ•จ๊ป˜ํ•  ๊ฒƒ์ด๋‹ค!