본문 바로가기
Archive/Java 풀스택 아카데미

[TIL] 2. 7월 3주차 - jQuery & React(학습 중에 알게된 것들)

by Lseing 2025. 7. 20.

현대이지웰 자바 풀스택과정을 들으면서 배웠던 것들과 배우면서 들었던 나의 생각과 부족했던 점들을 돌아보면서
정리해보려고한다 이렇게 기록함으로써 좀 더 나은 개발자의 모습이 되었으면 희망한다.

목차

  1. prop() 과 attr()의 차이
  2. useState란?
  3. 구조 분해 할당이란?
  4. counter문제

🧐jQuery 학습중에 알게된 것들

 

↔️prop() & attr()의 차이

챗봇파트 실습중에 새로운 메세지가 추가될 때마다 채팅창을 맨 아래로 자동 스크롤하기 위해서 prop()을 사용했었다.
이렇게 하기 위해서는 현재 시점에서 변화된 스크롤 높이가 필요하다 그렇다면 속성값이 필요하다는 건데 attr이 HTML 속성을 다룬다는 것이 생각났지만 prop을 사용하는 것을 보고 "attr을 써도 되지 않을까?"라고 생각했었다

찾아보니 이런 차이점이 있었다.

  다루는 값 반환값
attr() HTML 속성 정적인 값, 초기값
prop() DOM 객체의 속성 객체의 현재 상태, 동적으로 변화하는 실시간 값

채팅창 특성상 채팅을 칠 때마다 높이가 변화하기 때문에 attr()이 아닌 prop()을 사용하는게 당연하다.

🧐React 학습중에 알게된 것들

 

1. useState

useState는 컴포넌트에 state 변수를 추가할 수 있는 React Hook이다.
컴포넌트의 상태관리를 하기위해 사용된다, 상태가 변경되면 이를 감지해 다시 리렌더링해주는 역할을 한다.

React의 함수 컴포넌트는 렌더링 될 때마다 함수 전체가 다시 호출되는데, 만약 컴포넌트 내부에 일반 JS 변수를 사용한다면,

리렌더링이 될 때마다 해당 변수는 초기값으로 돌아가는 문제가 생긴다.

하지만 useState로 선언한 변수는 React가 특별히 관리하여 리렌더링 되어도 그 값을 유지한다.

예시로 확인해보자

export default function Counter() { //일반 변수를 사용했을 때
  let count = 0;

  const handleClick = () => {
    count = count + 1;
    console.log(count);
  };
  return (
    <div>
      <p>{count}</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}
//-------useState예시--------------
export default function Counter() {
  const [count, setCount] = useState(0); //count를 state변수로 선언, 초기값은 0으로 설정
  return (
    <div>
      <p>{count}</p>
      <button onClick={()=>setCount(count + 1)}>Click me</button>
    </div>
  );
}

버튼을 아무리 눌러도 증가된 값이 반영되지 않음(일반변수) / 값의 변경에 따라 잘 반영된 모습(useState)

왜 이런 차이가 있는걸까?

리액트 문서를 찾아보면 일반 변수를 사용한 경우 지역 변수를 업데이트를 하고 있다.

첫 번째로는 React에서는 이 컴포넌트를 두 번째로 렌더링할 때 지역 변수의 변경 사항을 고려하지 않고 처음부터 렌더링한다는 특징이 있다. 즉 지역변수는 렌더링간에 그 값이 유지되지 않는다는 것이다.
두번째로는 지역 변수를 업데이트를 해도 렌더링을 일으키지 않는다는 것이다. React가 컴포넌트를 다시 렌더링해야한다는 것을 인식하지 못한다는 것이다.

useState 훅은 이 문제점들을 해결해준다.

1.state변수를 통해 렌더링간에 데이터를 유지해준다.

2. 변수를 업데이트하고 다시 렌더링을 유발하는 state setter함수가 있다.

그래서 사용할때는 const [value, setValue] = useState(0); 의 구조를 한다.

value는 state 변수이고 setValue는 setter함수이다.

이미지로 표현해본 모습

참고 링크: https://ko.react.dev/learn/state-a-components-memory

 

2. 구조분해할당이란?

위의 내용을 보면 const [value, setValue] = useState(0); 이런 형태로 useState 사용할 수 있다고 했다. 그런데 일반적인 변수 선언 형태와는 익숙하지 않은 형태라서 이게 어떻게 가능할까하고 보니 문서에 구조 분해 할당이라는 개념을 찾아 볼 수 있었다.

구조 분해 할당 구문은 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식이다.

let user = ["steve", "male"]; // 사용자의 정보가 들어있는 배열

let [name, gender] = user; // 구조 분해 할당을 이용해서 값을 할당함

console.log(name);
console.log(gender);

출력된 모습

구조분해 할당 참고: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Destructuring

 

3. counter 문제

useState를 이용해서 counter를 구현하다가 값의 변경이 제대로 이루어지지 않는 문제를 만났었다

import { useState } from 'react';

export default function Counter() {
  const [num, setNum] = useState(0);
  return (
    <div>
      <p>{num}</p>
      <button onClick={() => setNum(num++)}>+</button>&nbsp; // 후위연산 사용
      <button onClick={() => setNum(num--)}>-</button> // 후위연산 사용
    </div>
  );
}

문제의 원인은 후위연산을 사용했기 때문이다.

문제가 발생하는 과정은 이러하다

1. 컴포넌트가 렌더링 될 때 num의 값은 0이라는 스냅샷으로 존재함

2. 사용자가 버튼을 클릭해서 setNum(num++)을 호출

3. num++ 표현식은 현재 값인 0을 먼저 반환하고 지역변수 num의 값을 1로 더함

4. react의 setNum 함수에는 0값이 전달됨

5. 현재 state값인 0과 setNum으로 들어온 0 값을 비교함 => 두 값이 동일하므로 변화가 없다고 판단하여 렌더링 일어나지 않음

6. 함수 실행 끝남 -> 1이 더해진 임시 변수는 메모리에서 사라짐(함수 실행이 끝났기 때문)

7. 리렌더링이 일어나지 않았기 때문에 react에서 기억하는 공식적인 num의 상태는 다음 클릭 때도 여전히 0임

그렇다면 num++과 num + 1의 차이는 무엇일까❓

은행으로 예시를 들어보자

num++ - 영수증에 낙서하는 행동

1. num = 0 이라고 적힌 잔고 증명서(스냅샷)를 가지고 있음

2. 증명서위에 펜으로 값을 1로 바꾸려고 시도 (num++)

3. num++ 은 후위연산자이기 때문에 낙서하기 전의 원본값 0 이 적힌 증명서를 은행원(setNum)에게 제출함

4. 은행원은 원래 잔고도 0원이고 제출받은 증명서도 0원이므로 변화가 없다고 판단해 아무런 업무를 처리하지 않음

num + 1 - 새 요청서를 작성하는 행동

1. num = 0 이라고 적힌 증명서(스냅샷)를 참고만 함

2. 별도의 메모장에 1이라는 새로운 값을 적음

3. 은행원(setNum)에게 메모에 적힌 값(새로운 값)으로 바꿔달라고 요청

4. 은행원은 현재 잔고 0과 요청받은 값 1이 다른것을 확인하고 정상적으로 잔고를 업데이트 함(리렌더링)