til

리액트 입문 3일 차 @개인 프로젝트 90%+10%

fpzmfks 2024. 8. 12. 20:52

오늘은 놀라운 성과를 낸 날이다. 저번 주 금요일만 해도 이런 진행속도로는 과제를 제때 제출하지 못할지도 모른다며 주말 작업을 각오했는데, 매니저님이 전체 방송으로 만류해서 그만뒀었다. 그리고 오늘 시간을 쏟아서 프로젝트를 진행하니 무려! 프로젝트 필수 요건을 모두 충족한 것이다! 어쩌면 난 좀 잘하는 편일지도 모른다고 생각했는데, 이어서 추가 요건을 만족하려고 코드를 손대다보니 어느새 저녁이 되어 있고, 완성된 건 되다만 추가 기능 하나뿐이었다. 아마 내일 제출 때까지 이 프로젝트를 200% 완성하는 건 불가능할 것으로 보인다. 

 

일단 오늘 한 것들을 나열하자면

  • 업데이트 기능 추가(글 작성 중 오류 발견...)
  • 삭제 기능 추가
  • 컴포넌트 분리
  • input 박스를 컴포넌트로 분리
  • css 조금
  • 정렬

이다. 


먼저 글 작성 중에 오류를 발견해버린 업데이트 기능을 살펴 보자면, 분명 업데이트 기능을 완성했던 당시에는 잘 작동했던 것을 떠올려 보면 list를 출력하기 전에 sort했던 문제 때문에 findindex 메서드가 잘못된 값을 찾아버린 것 같다. 

{list.sort((a,b)=>(b.gold)-(a.gold)).map((ele)=>{
          return (<List key={ele.id} ele={ele} list={list} setList={setList}/>)
        })}
//업데이트(Update) 함수
  const updateList = () => {
    const updateDataIndex = list.findIndex((li)=>(country===li.country));
    const updateData = {
      id:new Date().getTime(),
      country:country,
      gold:gold,
      silver:silver,
      bronze:bronze
    }
    list.splice(updateDataIndex,1,updateData)
    setList([...list])
    inputReset()
  }

이 문제는 업데이트 함수의 list에도 sort를 돌려버리면 해결이 되는 문제이기는 하지만, 좀 더 본질적으로 문제를 해결하지 않으면 다른 곳에서도 문제가 발생할 여지가 있는 부분이니 내일 제출 전에 반드시 list배열을 항상 정렬된 상태로 저장하는 등의 방법을 강구해둘 필요가 있다. 


다행히 삭제 기능은 자식 컴포넌트에서 선언하고 활용하는 국소적인 영향력을 가지고 있기 때문에 별 문제가 없었다. 


컴포넌트 분리는 생각보다 간단했다. 사실 처음부터 컴포넌트 분리를 고려하면서 코드를 작성했기 때문에 크게 문제될 점이 없었다. 다만 내가 엉뚱한 변수명을 지었다가 수정하는 일을 반복했기 때문에 그 부분만은 좀 문제였다... 다음부터는 변수명을 처음부터 신중하게 지어야겠다. 


input 박스를 컨포넌트로 분리하는 작업에는 발상의 전환이 좀 필요했는데, 저번주 금요일에 input 박스를 자식 컴포넌트로 로 넘기려고 할 때 정말 문제가 되었던 것은 자식 컴포넌트의 값을 다시 가져오는 것이 아니라 주고 받을 데이터를 선별하는 것이었다. 부모 컨포넌트로부터 input 컴포넌트로 보내야 하는 값은 총 3개로, 기존에 하던대로 배열을 map으로 돌리는 방식으로는 1개의 값밖에 보낼 수가 없었다. 오늘 시행착오를 하다가 이것저것 살펴보다 문득 떠오른 생각이, 바로 객체 배열이었다! 배열이 한 번에 하나의 값 밖에 보낼 수 없는 게 문제라면, 객체배열로 만들어서 여러 개의 값을 가질 수 있도록 할 수 있다는 것을 저번에 로컬스토리지를 다루면서 배웠었다. 그래서 필요한 값들을 가지는 객체로 배열을 선언해서 해당 배열로 map을 돌려 input 박스를 자식 컨포넌트로 분리할 수 있었다. 

//input박스 생성에 필요한 배열
  const dataArr = [{name:'국가명', data:country, func:addCountry},
    {name:'금메달', data:gold, func:addGold},
    {name:'은메달', data:silver, func:addSilver},
    {name:'동메달', data:bronze, func:addBronze}];
{dataArr.map((data)=>{
          return (
            <MedalInput key={data.name} data={data}/>
          )
        })}
//input 박스 컴포넌트
const MedalInput = ({data}) => {
    if(data.name==='국가명') {
      return (
      <div>
        <label>{data.name}</label>
        <input type='text' value={data.data} onChange={data.func} placeholder='국가명을 입력하시오'/>
      </div>)
    } else {
      return (
      <div>
        <label>{data.name}</label>
        <input type='number' value={data.data} onChange={data.func}/>
      </div>)
    }
}

다음으로 설명할 건 앞서 설명한 정렬과 css인데, 정렬은 설명했으니 css를 살펴보자면 리액트에서 어떤 방식으로 css를 다루는 게 맞는지 아직 좀 헷갈린다는 답을 할 수 있겠다. 

 

어림짐작하기로는 컴포넌트 내에서 css 객체를 선언하고 집어넣는 것이 가장 깔끔한 방법인 것 같으나, jsx파일의 코드가 길어지는데다가 여태껏 css파일 형식에서 자동완성으로 편히 다루던 것을 jsx 파일에서 다루려니 여간 성가신 게 아니었다. 

 

그렇다고 각 컴포넌트에 className을 할당해주고 css파일에서 컨트롤하려니 코드를 작성하는 와중에 컴포넌트의 위치를 확인하기가 번거로워졌다. 

 

일단 오늘은 이 둘 중 무엇도 아닌 '태그에 css적용'이라는 방식을 사용하였지만, 이러한 방식은 복잡한 페이지를 작성할 때 사용할 수 없는 방식이니 또 따로 방법을 강구해보아야겠다. 

 

어쩌면 컴포넌트 내에서 style 적용을 포기하고 그냥 눈 어림짐작으로 컴포넌트의 위치를 찾아낼 수 있게 되는 게 더 빠를지도 모르겠다.