Hello It's good to be back ^_^

[UMC 블로그챌린지] Web 파트 2주차 useState와 useReducer에 대해 알아보기 본문

Study/Web

[UMC 블로그챌린지] Web 파트 2주차 useState와 useReducer에 대해 알아보기

HongyeonLee 2026. 3. 24. 22:01

 

 

들어가기 전에 앞서, 솔직히 나는 훅이 뭔지, useState가 뭔지도 잘 모르기 때문에 우선 개념 정리가 필요했다

 

 

개념정리

자바스크립트에서 화살표 함수의 형태

//기본 형태
const 함수명 = (매개변수) => { 함수내용 }

//사용 예시
const Button = ({ onClick, text }: ButtonProps) => {
  return <button onClick={onClick}>{text}</button>;
};

//해석
// Button이라는 함수는 ButtonProps 타입의 객체를 매개변수로 받으며,
// 이를 구조 분해해 만든 버튼 요소를 리턴한다

 

JSX

: JavaScript + HTML/XML 로 둘의 문법이 혼용해서 사용한다. 참고 영상

https://www.youtube.com/watch?v=hyNQpRdS0rY&list=PLo3AHtncM26y0qX58gjc_QrkYlBCzQ2R_&index=10

 

자바스크립트에서의 객체

: { }를 이용해서 나타내고 멤버로는 key : value형의 변수와 함수이다

 

컴포넌트란?

: props라는 데이터를 매개변수로 입력받아 UI(자바스크립트 객체)를 출력하는 ‘함수’

 

props란?

: 컴포넌트에 전달할 다양한 정보를 담고 있는 자바스크립트 객체, 부모 컴포넌트가 자식 컴포넌트에게 전달해주는 자바스크립트 객체

 

state란? 

: 리액트 엔진이 관리하는 컴포넌트 전용 메모리 공간에 저장된 자바스크립트 값

: 컴포넌트가 기억하는 값, 컴포넌트 내부에서 관리하는 변할 수 있는 값

  • 다른 일반프로그래밍 언어에서 변수와 같은 역할을 한다고 뭉뜽그려서 말할 수 있다. 리액트는 변수가 아니라 '상태'를 기준으로 화면을 바꾸기 때문에 상태를 이용하는 것이 기본이다. 은 이러한 상태의 값을 바꿀 수 있게하는 자바스크립트 함수이다

 

구조분해할당

: 객체나 배열에서 필요한 값만 추출하여 지역 변수로 즉시 선언하는 문법

  • 리액트의 훅은 배열을 리턴한다. 우리는 훅이 리턴한 배열의 요소들을 이용해야하는데 매번 배열[인덱스]로 접근하면 불편할 것이다. 그래서 처음 훅이 리턴할 때부터 각각의 배열의 요소들을 따로 분해해서 변수로 받아 사용한다. 이것은 구조를 분해해서 할당한다는 의미로 구조분해할당이라고 한다.

 

사용예시

객체 분해

//구조분해할당 사용 전
function Profile(props) {
  // 매번 props.xxx 라고 써야 함
  return <h1>{props.name}님, 나이는 {props.age}살이군요.</h1>;
}
//구조분해할당 사용 후
function Profile({ name, age }) {
  // props 객체에서 name과 age라는 키(key)를 가진 값만 쏙 뽑아서 변수로 만듦
  return <h1>{name}님, 나이는 {age}살이군요.</h1>;
}

 

배열 분해

const [count, setCount] = useState(0);

1. useState()은 [0, 함수]라는 원소를 가진 배열을 리턴한다.

2. 각각의 배열의 요소를 count라는 변수와 setCount()라는 함수에 할당한다

 

 

useState()

: 변하는 데이터를 기억하고, 그 데이터에 맞춰 화면을 자동으로 바꿔주는 자바스크립트 함수

//사용 형식
const [state, setState] = useState(initialValue);

state: 컴포넌트에서 사용할 데이터

 

setState: state 값을 변경할 때 사용하는 함수

 

initialValue:state의 초기값

//사용 예시
import { useState } from 'react';

function Counter() {
  // 1. 'count'라는 상태를 0으로 시작하겠다고 리액트 금고에 예약함
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>현재 값: {count}</p>
      {/* 2. 버튼 클릭 시 setCount 함수로 값을 1 증가시킴 */}
      {/* 3. 리액트가 알람을 듣고 Counter 함수를 다시 실행함 */}
      <button onClick={() => setCount(count + 1)}>증가</button>
    </div>
  );
}

 

 

useReducer()

: useState와 같은 상태를 관리하는 훅

: 관리해야할 상태가 많아질 때 구조적으로 사용하기 위해 이용한다

//사용 형식
const [state, dispatch] = useReducer(reducer, initialState);

 

useReducer의 4가지 핵심 구성 요소

  1. 상태 (State): 관리할 데이터의 현재 값 (은행 잔고).
  2. 액션 (Action): 무엇을 할지 적힌 주문서 (입금, 출금, 송금 등). 보통 { type: 'DEPOSIT', payload: 1000 } 같은 객체 형태입니다.
  3. 리듀서 (Reducer): 주문서를 보고 실제로 돈을 계산하는 함수. (상태를 변경하는 로직이 담긴 본체)
  4. 디스패치 (Dispatch): 주문서를 은행 창구(Reducer)에 전달하는 행위.
//사용 예시
// 1. 리듀서 함수: (현재 상태, 주문서)를 받아서 '새로운 상태'를 반환함
function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 }; // 새 객체 반환
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  // 2. useReducer(리듀서함수, 초기값) 호출
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <>
      <h1>{state.count}</h1>
      {/* 3. dispatch를 통해 '주문서(action)'를 보냄 */}
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
    </>
  );
}

 

 

 

복잡한 구조를 컴팩트하기 만들기 위해 사용한다는 것은 알았다.

정리된 블로그를 보면서 내가 1학년 때 작업한 게임 프로젝트가 생각났는데 당시 작성했던 코드를 하나 가져오자면

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using TMPro;

public class CafeGame : MonoBehaviour
{
    public GameObject[] FruitsPrefabs;
    public GameObject[] ReceiptPrefabs;

    public List<GameObject> Order1 = new List<GameObject>();
    public List<GameObject> Order2 = new List<GameObject>();
    public List<GameObject> Order3 = new List<GameObject>();
    public List<GameObject> Order4 = new List<GameObject>();
    public List<GameObject> Order5 = new List<GameObject>();

    public List<GameObject> Order1Name = new List<GameObject>();
    public List<GameObject> Order2Name = new List<GameObject>();
    public List<GameObject> Order3Name = new List<GameObject>();
    public List<GameObject> Order4Name = new List<GameObject>();
    public List<GameObject> Order5Name = new List<GameObject>();

    public VerticalLayoutGroup Order1NameVertical;
    public VerticalLayoutGroup Order2NameVertical;
    public VerticalLayoutGroup Order3NameVertical;
    public VerticalLayoutGroup Order4NameVertical;
    public VerticalLayoutGroup Order5NameVertical;

    public List<GameObject> TotalClickedFruits = new List<GameObject>();
    public List<GameObject> TotalFruitImage = new List<GameObject>();
    public List<GameObject> TotalFruitName = new List<GameObject>();

    public VerticalLayoutGroup ClickFruitsVertical;
    public VerticalLayoutGroup ClickNameVertical;

    private GameObject ReceiptObj1;
    private GameObject ReceiptObj2;
    private GameObject ReceiptObj3;
    private GameObject ReceiptObj4;
    private GameObject ReceiptObj5;

    [SerializeField] private GameObject BlenderBtn;
    [SerializeField] private Sprite[] BlenderSprite;

    public int money = 0;
    private float yPosBox =2;

    private int fruitsCount;

    public int clickCount = 0;

    public TMP_FontAsset customFont;

    [SerializeField]
    private TextMeshProUGUI moneyNumTextInStartPanel;

    public AudioClip successSound; // 성공 사운드 클립

    private AudioSource audioSource;

    private int fortuneId;



    void Start()
    {
        money = 0;
        clickCount = 0;
        audioSource = GetComponent<AudioSource>();

        fortuneId = DayFortune.GetTodayFortuneId();
        Debug.Log("운세번호: " + fortuneId);

    }

    void Update()
    {
        if (TotalClickedFruits.Count < 5)
        {
            if (Input.GetMouseButtonDown(0)) //클릭한 과일 인식
            {
                Vector2 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                RaycastHit2D hit = Physics2D.Raycast(pos, Vector2.zero, Mathf.Infinity);
                if (hit.collider != null && hit.collider.gameObject.name != "GarbageBtn")
                {
                    GameObject clickedObject = hit.collider.gameObject;
                    TotalClickedFruits.Add(clickedObject);
                    clickCount++;

                    //클릭한 과일 이미지 생성
                    Sprite fruitSprite = clickedObject.GetComponent<SpriteRenderer>().sprite; //클릭한 과일의 스프라이트를 가져옴
                    GameObject fruitImageObject = new GameObject("FruitImage", typeof(RectTransform)); //RectTransform 컴포넌트를 가진 오브젝트 생성
                    fruitImageObject.AddComponent<Image>().sprite = fruitSprite; //생성된 오브젝트에 이미지 컴포넌트를 추가하고 클릭한 과일의 이미지를 넣음
                    RectTransform RectTransform1 = fruitImageObject.GetComponent<RectTransform>();
                    RectTransform1.SetParent(ClickFruitsVertical.transform, false); //버티컬 레이아웃의 자식요소로 들어가게 함
                    TotalFruitImage.Add(fruitImageObject); //생성된 오브젝트를 리스트에 추가

                    // 클릭한 과일 이름 생성
                    string FruitName = clickedObject.name;
                    GameObject FruitNameObj = new GameObject("FruitNameText");
                    FruitNameObj.AddComponent<TextMeshProUGUI>().text = FruitName;
                    TextMeshProUGUI textMeshPro = FruitNameObj.GetComponent<TextMeshProUGUI>();
                    textMeshPro.font = customFont;
                    textMeshPro.color = Color.black;
                    textMeshPro.fontSize = 63;
                    RectTransform rectTransform2 = FruitNameObj.GetComponent<RectTransform>();
                    rectTransform2.SetParent(ClickNameVertical.transform, false); //버티컬 레이아웃의 자식요소로 들어가게 함
                    rectTransform2.sizeDelta = new Vector2(260f, rectTransform2.sizeDelta.y);
                    TotalFruitName.Add(FruitNameObj);
                }
        }

        //실시간 번 돈 나타내기
        moneyNumTextInStartPanel.SetText(money.ToString()+"만원");

        //과일을 클릭한 횟수에 따라 블랜더의 이미지 변경
        Image imageComponent = BlenderBtn.GetComponent<Image>();
        switch(clickCount)
        {
            case 0:
                imageComponent.sprite = BlenderSprite[0];
                imageComponent.SetNativeSize();
                break;
            case 1:
                imageComponent.sprite = BlenderSprite[1];
                imageComponent.SetNativeSize();
                break;
            case 2:
                imageComponent.sprite = BlenderSprite[2];
                imageComponent.SetNativeSize();
                break;
            case 3:
                imageComponent.sprite = BlenderSprite[3];
                imageComponent.SetNativeSize();
                break;
            case 4:
                imageComponent.sprite = BlenderSprite[4];
                imageComponent.SetNativeSize();
                break;
            case 5:
                imageComponent.sprite = BlenderSprite[5];
                imageComponent.SetNativeSize();
                break;
        }

        // if(TotalClickedFruits.Count == 0)
        // {
        //     imageComponent.sprite = BlenderSprite[0];
        //     imageComponent.SetNativeSize();
        // }

        //과일 이름 표시
        // string allClickedObjectNames = "";
        // foreach (var FruitsObject in TotalClickedFruits)
        // {
        //     allClickedObjectNames += FruitsObject.name + "\n";
        // }
        // clickedObjectNameText.SetText(allClickedObjectNames);
        }
    }

    public void SpawnFruits_1()
    {
        
        if (fortuneId == 7) //알바 하드모드 운세일 경우
        {
            float p = Random.value;
            Debug.Log("1번 과일개수확률: " + p);
            if(p < 0.3f) //30%확률로 과일의 개수가 3개 나올 수도 있음
                fruitsCount = 3;
            else
                fruitsCount = Random.Range(4, 6); //70%확률로 과일의 개수 4, 5개
        }
        else
            fruitsCount = Random.Range(3, 6); //한 주문에 나오는 과일의 개수 3~5개 사이

        for (int i = 0; i < fruitsCount; i++)
        {
            //과일 생성
            float yPos = 2.8f - 0.6f*i;
            Vector3 spawnPosition = new Vector3(-5.6f, yPos, 0);
            int randNum = Random.Range(0, FruitsPrefabs.Length);
            GameObject RandomFruit = FruitsPrefabs[randNum];
            GameObject FruitsObj = Instantiate(RandomFruit, spawnPosition, Quaternion.identity);
            Order1.Add(FruitsObj);
            //과일 이름 생성
            string fruitName = FruitsObj.name.Replace("(Clone)", ""); //생성된 과일 오브젝트의 이름에서 클론을 떼고 저장
            GameObject FruitNameObj = new GameObject("FruitNameText");
            FruitNameObj.AddComponent<TextMeshProUGUI>().text = fruitName;
            TextMeshProUGUI textMeshPro = FruitNameObj.GetComponent<TextMeshProUGUI>();
            textMeshPro.font = customFont;
            textMeshPro.color = Color.black;
            textMeshPro.fontSize = 15;
            //배치 버티컬 구조
            RectTransform rectTransform = FruitNameObj.GetComponent<RectTransform>();
            rectTransform.SetParent(Order1NameVertical.transform, false); //버티컬 레이아웃의 자식요소로 들어가게 함
            Order1Name.Add(FruitNameObj);
        }
        //주문 영수증 오브젝트 생성
        Vector3 spawnPositionBox = new Vector3(-5f, yPosBox, 0);
        GameObject ReceiptObj = ReceiptPrefabs[0];
        ReceiptObj1 = Instantiate(ReceiptObj, spawnPositionBox, Quaternion.identity);
    }

    public void SpawnFruits_2()
    {
        if (fortuneId == 7) //알바 하드모드 운세일 경우
        {
            float p = Random.value;
            Debug.Log("2번 과일개수확률: " + p);
            if(p < 0.3f) //30%확률로 과일의 개수가 3개 나올 수도 있음
                fruitsCount = 3;
            else
                fruitsCount = Random.Range(4, 6); //70%확률로 과일의 개수 4, 5개
        }
        else //하드모드 운세가 아닐경우
            fruitsCount = Random.Range(3, 6); //한 주문에 나오는 과일의 개수 3~5개 사이

        for (int i = 0; i < fruitsCount; i++)
        {
            float yPos = 2.8f - 0.6f*i;
            Vector3 spawnPosition = new Vector3(-3.1f, yPos, 0);
            int randNum = Random.Range(0, FruitsPrefabs.Length);
            GameObject RandomFruit = FruitsPrefabs[randNum];
            GameObject FruitsObj = Instantiate(RandomFruit, spawnPosition, Quaternion.identity);
            Order2.Add(FruitsObj);

            GameObject FruitNameObj = new GameObject("FruitNameText");
            string fruitName = FruitsObj.name.Replace("(Clone)", "");
            FruitNameObj.AddComponent<TextMeshProUGUI>().text = fruitName;
            TextMeshProUGUI textMeshPro = FruitNameObj.GetComponent<TextMeshProUGUI>();
            textMeshPro.font = customFont;
            textMeshPro.color = Color.black;
            textMeshPro.fontSize = 15;
            RectTransform rectTransform = FruitNameObj.GetComponent<RectTransform>();
            rectTransform.SetParent(Order2NameVertical.transform, false); //버티컬 레이아웃의 자식요소로 들어가게 함
            Order2Name.Add(FruitNameObj);
        }
        Vector3 spawnPositionBox = new Vector3(-2.5f, yPosBox, 0);
        GameObject ReceiptObj = ReceiptPrefabs[0];
        ReceiptObj2 = Instantiate(ReceiptObj, spawnPositionBox, Quaternion.identity);
    }

    public void SpawnFruits_3()
    {

        if (fortuneId == 7) //알바 하드모드 운세일 경우
        {
            float p = Random.value;
            Debug.Log("3번 과일개수확률: " + p);
            if(p < 0.3f) //30%확률로 과일의 개수가 3개 나올 수도 있음
                fruitsCount = 3;
            else
                fruitsCount = Random.Range(4, 6); //70%확률로 과일의 개수 4, 5개
        }
        else
            fruitsCount = Random.Range(3, 6); //한 주문에 나오는 과일의 개수 3~5개 사이
        
        for (int i = 0; i < fruitsCount; i++)
        {
            float yPos = 2.8f - 0.6f*i;
            Vector3 spawnPosition = new Vector3(-0.6f, yPos, 0);
            int randNum = Random.Range(0, FruitsPrefabs.Length);
            GameObject RandomFruit = FruitsPrefabs[randNum];
            GameObject FruitsObj = Instantiate(RandomFruit, spawnPosition, Quaternion.identity);
            Order3.Add(FruitsObj);

            GameObject FruitNameObj = new GameObject("FruitNameText");
            string fruitName = FruitsObj.name.Replace("(Clone)", "");
            FruitNameObj.AddComponent<TextMeshProUGUI>().text = fruitName;
            TextMeshProUGUI textMeshPro = FruitNameObj.GetComponent<TextMeshProUGUI>();
            textMeshPro.font = customFont;
            textMeshPro.color = Color.black;
            textMeshPro.fontSize = 15;
            RectTransform rectTransform = FruitNameObj.GetComponent<RectTransform>();
            rectTransform.SetParent(Order3NameVertical.transform, false); //버티컬 레이아웃의 자식요소로 들어가게 함
            Order3Name.Add(FruitNameObj);
        }
        Vector3 spawnPositionBox = new Vector3(0f, yPosBox, 0);
        GameObject ReceiptObj = ReceiptPrefabs[0];
        ReceiptObj3 = Instantiate(ReceiptObj, spawnPositionBox, Quaternion.identity);
    }

    public void SpawnFruits_4()
    {
        if (fortuneId == 7) //알바 하드모드 운세일 경우
        {
            float p = Random.value;
            Debug.Log("4번 과일개수확률: " + p);
            if(p < 0.3f) //30%확률로 과일의 개수가 3개 나올 수도 있음
                fruitsCount = 3;
            else
                fruitsCount = Random.Range(4, 6); //70%확률로 과일의 개수 4, 5개
        }
        else
            fruitsCount = Random.Range(3, 6); //한 주문에 나오는 과일의 개수 3~5개 사이
        
        for (int i = 0; i < fruitsCount; i++)
        {
            float yPos = 2.8f - 0.6f*i;
            Vector3 spawnPosition = new Vector3(1.9f, yPos, 0);
            int randNum = Random.Range(0, FruitsPrefabs.Length);
            GameObject RandomFruit = FruitsPrefabs[randNum];
            GameObject FruitsObj = Instantiate(RandomFruit, spawnPosition, Quaternion.identity);
            Order4.Add(FruitsObj);

            GameObject FruitNameObj = new GameObject("FruitNameText");
            string fruitName = FruitsObj.name.Replace("(Clone)", "");
            FruitNameObj.AddComponent<TextMeshProUGUI>().text = fruitName;
            TextMeshProUGUI textMeshPro = FruitNameObj.GetComponent<TextMeshProUGUI>();
            textMeshPro.font = customFont;
            textMeshPro.color = Color.black;
            textMeshPro.fontSize = 15;
            RectTransform rectTransform = FruitNameObj.GetComponent<RectTransform>();
            rectTransform.SetParent(Order4NameVertical.transform, false); //버티컬 레이아웃의 자식요소로 들어가게 함
            Order4Name.Add(FruitNameObj);
        }
        Vector3 spawnPositionBox = new Vector3(2.5f, yPosBox, 0);
        GameObject ReceiptObj = ReceiptPrefabs[0];
        ReceiptObj4 = Instantiate(ReceiptObj, spawnPositionBox, Quaternion.identity);
    }

    public void SpawnFruits_5()
    {
        if (fortuneId == 7) //알바 하드모드 운세일 경우
        {
            float p = Random.value;
            Debug.Log("5번 과일개수확률: " + p);
            if(p < 0.3f) //30%확률로 과일의 개수가 3개 나올 수도 있음
                fruitsCount = 3;
            else
                fruitsCount = Random.Range(4, 6); //70%확률로 과일의 개수 4, 5개
        }
        else
            fruitsCount = Random.Range(3, 6); //한 주문에 나오는 과일의 개수 3~5개 사이
        
        for (int i = 0; i < fruitsCount; i++)
        {
            float yPos = 2.8f - 0.6f*i;
            Vector3 spawnPosition = new Vector3(4.4f, yPos, 0);
            int randNum = Random.Range(0, FruitsPrefabs.Length);
            GameObject RandomFruit = FruitsPrefabs[randNum];
            GameObject FruitsObj = Instantiate(RandomFruit, spawnPosition, Quaternion.identity);
            Order5.Add(FruitsObj);

            GameObject FruitNameObj = new GameObject("FruitNameText");
            string fruitName = FruitsObj.name.Replace("(Clone)", "");
            FruitNameObj.AddComponent<TextMeshProUGUI>().text = fruitName;
            TextMeshProUGUI textMeshPro = FruitNameObj.GetComponent<TextMeshProUGUI>();
            textMeshPro.font = customFont;
            textMeshPro.color = Color.black;
            textMeshPro.fontSize = 15;
            RectTransform rectTransform = FruitNameObj.GetComponent<RectTransform>();
            rectTransform.SetParent(Order5NameVertical.transform, false); //버티컬 레이아웃의 자식요소로 들어가게 함
            Order5Name.Add(FruitNameObj);
        }
        Vector3 spawnPositionBox = new Vector3(5f, yPosBox, 0);
        GameObject ReceiptObj = ReceiptPrefabs[0];
        ReceiptObj5 = Instantiate(ReceiptObj, spawnPositionBox, Quaternion.identity);
    }

    public void ReceiptManager()
    {
        if (Order1.Count == 0)
            Destroy(ReceiptObj1);
        if (Order2.Count == 0)
            Destroy(ReceiptObj2);
        if (Order3.Count == 0)
            Destroy(ReceiptObj3);
        if (Order4.Count == 0)
            Destroy(ReceiptObj4);
        if (Order5.Count == 0)
            Destroy(ReceiptObj5);
    }

    public void DestroyOrder(List<GameObject> Order, List<GameObject> OrderName)
    {
        for (int i = 0; i < Order.Count; i++)
        {
            Destroy(Order[i]);
        }
        Order.Clear();

        for (int i = 0; i < OrderName.Count; i++)
        {
            Destroy(OrderName[i]);
        }
        OrderName.Clear();
    }

    public void moneyManager()
    {
        money += 1;
    }

    public void PlaySuccessSound()
    {
        audioSource.clip = successSound;
        audioSource.Play();
    }

    // public void ClearClickedObj()
    // {
    //     TotalClickedFruits.Clear();
    //     for (int i = 0; i < TotalFruitImageObject.Count; i++)
    //     {
    //         Destroy(TotalFruitImageObject[i]);
    //     }
    //     TotalFruitImageObject.Clear();
    // }

    // 2차원 리스트로 과일 주문 5개 생성하기 - 근데 어려워서 포기
    // public void SpawnFruits()
    // {
    //     for (int i = 0; i < 5; i++)
    //     {
    //         int fruitCount = Random.Range(3, 6);
    //         float xPos = -5.5f + 2.25f * i;
    //         for (int j = 0; j < fruitCount; j++)
    //         {
    //             float yPos = 3.5f - 1 * j;
    //             Vector3 spawnPosition = new Vector3(xPos, yPos, 0);
    //             int randNum = Random.Range(0, FruitsPrefabs.Length);
    //             GameObject RandomFruit = FruitsPrefabs[randNum];
    //             GameObject FruitsObj = Instantiate(RandomFruit, spawnPosition, Quaternion.identity);
    //             TotalOrder.Add(new List<GameObject>{FruitsObj});
    //         }

    //         float yPosBox = 1.5f + 0.5f * (5 - fruitCount);
    //         Vector3 spawnPositionBox = new Vector3(xPos, yPosBox, 0);
    //         GameObject BoxObj = BoxPrefabs[fruitCount - 3];
    //         Instantiate(BoxObj, spawnPositionBox, Quaternion.identity);
    //     }
    // }
}

 

1학년이 겨우 C하나 배우고 작성한 코드이니 한 눈에 봐도 엄청나게 하드코딩이고 재사용이 불가능하게 써놓은 것이 보인다.

대충 세어봐도 한 스크립트 내에서 선언된 변수만 30개가 넘어가니 코드를 한눈에 파악하기 어렵고 유지보수 또한 굉장히 복잡하다.

이 코드를 직접 작성한 개발자(나)가 아니면 다른 사람이 수정하기도 어려울 것이다.

 

물론 처음에는 시도하는 것이 중요하지만, 개발을 할 땐 언제나 어떻게 하면 더 효율적이고 가독성이 좋은 코드를 짤지, 더 컴팩트하게 짤 수는 없을지 생각하는 논리적과정이 중요하다.

 

useState가 편하다고 그것만 사용한다면 위의 코드와 같은 사태가 또 다시 벌어질 것이다. 그러니 useReducer가 보기엔 어려울 지라도 써보려고 노력하는 습관을 들이려고 하자!