๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“‚ Project/Solo

[๐Ÿ” ๋ง›์ง‘ ๊ณต์œ  ์‚ฌ์ดํŠธ] ๋ฆฌ์•กํŠธ๋กœ CRUD ๊ตฌํ˜„ํ•˜๊ธฐ

by Dev. Ella 2023. 5. 16.

๐Ÿ› ๏ธ ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ

์›น ์‚ฌ์ดํŠธ ๋‚ด์—์„œ ์‚ฌ์šฉ์ž๋“ค์ด ์ž์œ ๋กญ๊ฒŒ ๋ง›์ง‘ ์ถ”์ฒœ ๊ธ€์„ ์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ๋‹ค.

As-Is: ํ˜„์žฌ๋Š” ๊ธฐ์กด์— ์˜ฌ๋ผ์˜จ ๊ธ€์„ ๋ณผ ์ˆ˜ ์žˆ๊ธฐ๋งŒ ํ•จ
โžก๏ธ To-be: ๋ง›์ง‘ ์ œ๋ณด ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๊ธ€์„ Create, Read, Update ๊ทธ๋ฆฌ๊ณ  ์‚ญ์ œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด Delete ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿ’ก ๊ตฌํ˜„ ๊ณผ์ • - Create

1. input ์นธ์„ ๋งŒ๋“ ๋‹ค.

input์˜ ํƒ€์ž…์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๋‹ค์–‘ํ•˜๋‹ˆ ๊ณจ๋ผ์„œ ํ™œ์šฉํ•ด ๋ณด์ž.

// ์ˆœ์„œ๋Œ€๋กœ 

<input type = "date" />
<input type = "range" />
<input type = "checkbox" />
<input type = "input" /> or ๊ทธ๋ƒฅ <input/>
<input/> <select/>
<textarea/>

 

2. onChange ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ™œ์šฉํ•œ๋‹ค.

onChange ๋˜๋Š” onInput๋ผ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž๊ฐ€ <input>์— ๋ฌด์–ธ๊ฐ€ ์ž…๋ ฅ ์‹œ, ์ค‘๊ด„ํ˜ธ ์•ˆ์— ์žˆ๋Š” ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ํ•œ๋‹ค.

<input onChange={() => {console.log("์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋ฉด ๋‚˜ํƒ€๋‚˜๋Š” ๋‚ด์šฉ")}} />

 

์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌด์–ธ๊ฐ€๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์•ˆ์— ์žˆ๋Š” ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด ๋ณด์ธ๋‹ค. ์ด์™ธ์—๋„ ์Šคํฌ๋กค, ๋งˆ์šฐ์Šค ์˜ค๋ฒ„ ๋“ฑ๋“ฑ ์ˆ˜๋งŽ์€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋“ค์ด ์žˆ๋Š”๋ฐ, ์ด๋Š” ๊ตณ์ด ์™ธ์šธ ํ•„์š”๋Š” ์—†๊ณ  ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๊ทธ๋•Œ๊ทธ๋•Œ ๊ฐ–๋‹ค ์“ฐ๋ฉด ๋œ๋‹ค.

 

 

3. input์— ์ž…๋ ฅํ•œ ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค.

ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•œ๋‹ค. ์•„๋ฌด๊ฑฐ๋‚˜ ์จ๋„ ๋˜๋ฉฐ ๋‚ด๊ฐ€ ์ž…๋ ฅํ•œ 'e'๋Š” ๋ณดํ†ต ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ผ๋Š” ์—ญํ• ์„ ํ•˜๋Š”๋ฐ, input ํƒœ๊ทธ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์— ๊ด€๋ จ๋œ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๋“ค์ด ์ด ํŒŒ๋ผ๋ฏธํ„ฐ ์•ˆ์— ๋‹ด๊ฒจ ์žˆ๋‹ค. ์ด e์— .target์„ ๋ถ™์ด๋ฉด ํ•ด๋‹น ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ html ํƒœ๊ทธ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ค€๋‹ค.

<input onChange={(e) => {console.log(e.target)}} />

 

๋”๋ถˆ์–ด, e.target ๋’ค์— .value๋ฅผ ๋ถ™์ด๋ฉด, ํ•ด๋‹น ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ html ํƒœ๊ทธ์— ์ž…๋ ฅํ•œ '๊ฐ’'์ด ๋‚˜์˜จ๋‹ค. ๋”ฐ๋ผ์„œ '์ž…๋ ฅ'์ด๋ผ๊ณ  ์ž…๋ ฅํ•˜๋ฉด ใ…‡๋ถ€ํ„ฐ ๋งˆ์ง€๋ง‰ ใ„ฑ๊นŒ์ง€ ์ฝ˜์†”์— ์ฐํžŒ๋‹ค.

<input onChange={(e) => {console.log(e.target.value)}} />

 

4. input์— ์ž…๋ ฅํ•œ ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์€ ๋ณดํ†ต ๋ณ€์ˆ˜๋‚˜ state์— ์ €์žฅํ•ด ๋‘๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ๋Š” state์™€ state ๋ณ€๊ฒฝ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์„œ ์•„๊นŒ ์จ๋‘” console.log ๋ถ€๋ถ„์— ๋„ฃ์–ด์ฃผ์ž. ๊ทธ๋Ÿผ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์ด state์— ์ €์žฅ๋œ๋‹ค.

let [inputValue, setInputValue] = useState('');
   
  // ... ์ƒ๋žต
  
<input onChange={(e) => {setInputValue(e.target.value)}} />

์–ด?

๊ทธ๋Ÿฐ๋ฐ ์ฒ˜์Œ์— ์ž…๋ ฅํ•œ ๊ฐ’์ด ์ฝ˜์†”์— ์ฐํžˆ์ง€ ์•Š๊ณ , ๋‘ ๋ฒˆ์งธ ์ž…๋ ฅํ•œ ๊ฐ’๋ถ€ํ„ฐ ์ฐํžŒ๋‹ค.

์™œ ๊ทธ๋Ÿด๊นŒ?

 

state ๋ณ€๊ฒฝ ํ•จ์ˆ˜๋Š” ๋Šฆ๊ฒŒ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฐ”๋กœ '๋น„๋™๊ธฐ์ '์œผ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ฆ‰, state๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ธฐ ์ „์— console์— ์žˆ๋Š” ์ค„์„ ์‹คํ–‰ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

 

๐Ÿ’ก ๊ตฌํ˜„ ๊ณผ์ • - Read, Update

1. state ๋ณ€๊ฒฝ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์ƒˆ๋กœ์šด ๊ธ€์ด ์ถ”๊ฐ€๋˜๋„๋ก ํ•˜๋ ค๋ฉด ์ž…๋ ฅ๋œ ๋‚ด์šฉ์„ ์ €์žฅํ•˜๊ณ  ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค. ํ˜„์žฌ inputValue๋ผ๋Š” state ๋ณ€๊ฒฝ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž…๋ ฅ๋œ ๋‚ด์šฉ์„ ์ €์žฅํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ด state ๋ณ€๊ฒฝ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ธ€์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  addPost ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€๋กœ ์„ ์–ธํ•ด ์ฃผ์—ˆ๋Š”๋ฐ, ์ด ํ•จ์ˆ˜๋Š” ์ž…๋ ฅ๋œ ๋‚ด์šฉ(inputValue)์„ ์ƒˆ๋กœ์šด ๊ธ€๋กœ ์ถ”๊ฐ€ํ•˜๊ณ , ์ œ๋ชฉ๊ณผ ์ข‹์•„์š” ๋ฒ„ํŠผ์˜ ๋ฐฐ์—ด์„ ์—…๋ฐ์ดํŠธํ•œ ํ›„, inputValue๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ํ•˜๋‚˜์˜ ๊ธ€์ด ์ถ”๊ฐ€๋  ๋•Œ ์—…๋ฐ์ดํŠธ ๋˜์–ด์•ผ ํ•  ๊ฒƒ๋“ค(์ œ๋ชฉ, ์ข‹์•„์š” ๋ฒ„ํŠผ, ์ž…๋ ฅ๋ž€)์„ addPost ํ•จ์ˆ˜์˜ ์กฐ๊ฑด๋ฌธ ์•ˆ์— ๋„ฃ์–ด์ค€๋‹ค.

// ...์ƒ๋žต

function App() {
  let report = '๐Ÿง ๋‚˜๋งŒ ์•„๋Š” ๋ง›์ง‘ ์ œ๋ณดํ•˜๊ธฐ'; 
  let [title, setTitle] = useState(['์„ฑ์ˆ˜์—ญ', '๊ฐ•๋‚จ์—ญ', '์••๊ตฌ์ •์—ญ']);
  let [thumb, setThumb] = useState([0, 0, 0]);
  let [modal, setModal] = useState(false); 
  let [modalTitle, setModalTitle] = useState(0);
  let [inputValue, setInputValue] = useState('');
  

  // ๋ง›์ง‘ ์ œ๋ณดํ•˜๊ธฐ ๋ฒ„ํŠผ
  const addPost = () => { // ๊ธ€์ด ์ƒ์„ฑ๋˜๋ฉด
    if (inputValue) {
      setTitle([...title, inputValue]); // ์ œ๋ชฉ ์—…๋ฐ์ดํŠธ
      setThumb([...thumb, 0]); // ์ข‹์•„์š” ๋ฒ„ํŠผ ์—…๋ฐ์ดํŠธ
      setInputValue(''); // ์ž…๋ ฅ๋ž€ ์ดˆ๊ธฐ ์ƒํƒœ๋กœ ์—…๋ฐ์ดํŠธ
    }
  };

    // ...์ƒ๋žต

 

2. onClick ์ด๋ฒคํŠธ๋กœ ํ•จ์ˆ˜๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.

๋ฒ„ํŠผ์— onClick ์ด๋ฒคํŠธ๋กœ addPost ํ•จ์ˆ˜๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ํด๋ฆญํ•  ๋•Œ ์ƒˆ๋กœ์šด ๊ธ€์ด ์ถ”๊ฐ€๋˜๋„๋ก ํ•œ๋‹ค.

// ...์ƒ๋žต

return (

    // ...์ƒ๋žต
      
      {/* ์ถ”์ฒœ ๋ง›์ง‘ ์ž…๋ ฅ๋ž€ */}
      <textarea 
      className='reportArea' 
      placeholder = "์ถ”์ฒœ ๋ง›์ง‘์ด ์žˆ๋‚˜์š”?" 
      value={inputValue}
      onChange={(e) => {setInputValue(e.target.value);}} />
      <p/>
      
      {/* ๋ง›์ง‘ ์ œ๋ณด ๋ฒ„ํŠผ */}
      <button 
      className='reportButton'
      onClick={addPost}> // ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๊ธ€ ์ƒ์„ฑ
      { report }</button>
      <p/>
      
    </div>
  );
}

export default App;

 

์ด์ œ ๋‚ด์šฉ์„ ์ž…๋ ฅ์ฐฝ์— ์ž…๋ ฅํ•œ ํ›„, ๋ง›์ง‘ ์ œ๋ณด ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ƒˆ๋กœ์šด ๊ธ€์ด ์ถ”๊ฐ€๋  ๊ฒƒ์ด๋‹ค.

 

 

๐Ÿ’ก ๊ตฌํ˜„ ๊ณผ์ • - Delete

1. splice๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐฐ์—ด์ด ์—…๋ฐ์ดํŠธ๋˜๋„๋ก ๋งŒ๋“ ๋‹ค.

๊ธ€์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ๊ฐ ๊ธ€์— ๋Œ€ํ•œ ์‚ญ์ œ ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•˜๊ณ , ํ•ด๋‹น ๋ฒ„ํŠผ์ด ํด๋ฆญ๋˜์—ˆ์„ ๋•Œ ํ•ด๋‹น ๊ธ€์„ ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค. ๊ธ€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ deletePost ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ์ธ๋ฑ์Šค๋ฅผ ๋ฐ›์•„์™€์„œ ํ•ด๋‹น ์ธ๋ฑ์Šค์— ์žˆ๋Š” ๊ธ€์˜ ์ œ๋ชฉ๊ณผ ์ข‹์•„์š” ๋ฒ„ํŠผ์„ ๋ฐฐ์—ด์—์„œ ์ œ๊ฑฐํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ, splice ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๋ณธ ๋ฐฐ์—ด์„ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

// ...์ƒ๋žต

function App() {
  let report = '๐Ÿง ๋‚˜๋งŒ ์•„๋Š” ๋ง›์ง‘ ์ œ๋ณดํ•˜๊ธฐ'; 
  let [title, setTitle] = useState(['์„ฑ์ˆ˜์—ญ', '๊ฐ•๋‚จ์—ญ', '์••๊ตฌ์ •์—ญ']);
  let [thumb, setThumb] = useState([0, 0, 0]);
  let [modal, setModal] = useState(false); 
  let [modalTitle, setModalTitle] = useState(0);
  let [inputValue, setInputValue] = useState('');
  

	// ... ์ƒ๋žต

  // ์ œ๋ณดํ•œ ๋ง›์ง‘ ์‚ญ์ œ
  const deletePost = (index) => { // ์‚ญ์ œ ํ•จ์ˆ˜๋Š” index๋ฅผ ๋ฐ›์•„์˜ด
    const newTitle = [...title];
    const newThumb = [...thumb];
    newTitle.splice(index, 1); // splice๋กœ ์ œ๋ชฉ ๋ฐฐ์—ด ์—…๋ฐ์ดํŠธ
    newThumb.splice(index, 1); // splice๋กœ ์ข‹์•„์š” ๋ฒ„ํŠผ ๋ฐฐ์—ด ์—…๋ฐ์ดํŠธ
    setTitle(newTitle);
    setThumb(newThumb);
  };
  
	// ... ์ƒ๋žต

 

๋˜ํ•œ, title.map( ) ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ๊ฐ post์— ๋Œ€ํ•œ ์‚ญ์ œ ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ๋ฒ„ํŠผ์— onClick ์ด๋ฒคํŠธ๋กœ deletePost(i)๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ํด๋ฆญํ•  ๋•Œ ํ•ด๋‹น ๊ธ€์„ ์‚ญ์ œํ•˜๋„๋ก ํ•œ๋‹ค. i๋Š” ํ˜„์žฌ ๊ธ€์˜ ์ธ๋ฑ์Šค๋‹ค.

// ...์ƒ๋žต          
              <p className="share">๐Ÿ“ฎ ๊ณต์œ ํ•˜๊ธฐ</p>
              <button className="deleteButton" onClick={() => deletePost(i)}
              >์‚ญ์ œ</button> {/* onClick์œผ๋กœ ์‚ญ์ œ ์ด๋ฒคํŠธ ์ƒ์„ฑ */}
          </div>)
        }) 
      }
    </div>
  );
}

export default App;

 

์ด์ œ ๊ฐ ๊ธ€ ์˜†์— ์ถ”๊ฐ€๋œ ์‚ญ์ œ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ๊ธ€์ด ์‚ญ์ œ๋  ๊ฒƒ์ด๋‹ค.

 

 

๐Ÿฅณ ๊ธฐ๋Šฅ ๊ตฌํ˜„

 

 

๋Œ“๊ธ€