본문 바로가기
스파르타코딩클럽/내일배움캠프

[TIL] 내일배움캠프 React 과정 2023.01.02

by heereal 2023. 1. 2.

Today I Learned

  • Firebase로 구현한 투두리스트 리팩토링

 


input 태그의 속성-value와 defaultValue

input 태그의 속성인 defaultValue와 value에 값을 넣으면 둘 다 input 박스에 처음부터 보여진다.

  • defaultValue: input tag에서 처음 보여줄 값
  • value: input tag에서 계속 보여줄 값

defaultValue를 지정하고 input 박스에 값을 입력하면 값이 수정이 된다. 반면, value를 지정하고 input 박스에 값을 입력하면 값이 입력되지 않고 지정해준 value만 계속해서 보여준다.

 

출처 https://velog.io/@e_juhee/defaultValue-value

 

 

npm update 에러 생길 때

리액트 프로젝트 clone할 때마다 이유는 모르겠지만 npm update를 해야 하는데 에러가 발생했다. 검색해 보니 버전이 충돌하는 거 같은데 충돌이 일어나도 강제로 설치하라는 명령어를 추가하니 에러 없이 잘 설치할 수 있었다.

npm update --legacy-peer-deps

참고 https://tesseractjh.tistory.com/234

 

 

firestore에서 onSnapshot으로 데이터 가져오기

useEffect(() => {
   getTodos();
}, [todos]);

// firestore에서 데이터 가져오기
const getTodos = async () => {
    const array = [];
    const querySnapshot = await getDocs(collection(dbService, "todos"));
    querySnapshot.forEach((doc) => array.push({id: doc.id,...doc.data()}));
    setTodos(array)
};

기존에 firestore 데이터를 불러오기 위한 코드는 이러했다. useEffect의 의존성 배열을 이용해서 todos에 변경이 생길 때마다 setTodos에 가져온 데이터를 넣어달라는 구조였는데 이상하게 데이터를 너무 많이 읽는 바람에 firestore 기본 제공 읽기 횟수(5만)를 추가하는 일이 발생하기도 했다.

 

그런데 이게 알고 보니 거의 무한루프를 돌고 있는 거였다. 일단 렌더링이 되면 useEffect를 통해 getTodos가 실행된다. 그럼 setTodos가 작동해서 todos가 변경되고 그럼 또다시 getTodos가 실행되고 이 과정이 반복된다. 데이터를 무한으로 불러오는 것이다ㅋㅋ 동기 분의 찰떡같은 표현을 빌리자면 '마치 물 한 잔 마시겠다고 정수기 물 나오는 버튼을 24시간 눌러놨던'것이었다. 😱

 

useEffect(() => {
    const q = query(
      collection(dbService, "todos"),
      orderBy("createdAt", "desc")
    );

    onSnapshot(q, (snapshot) => {
      const newTodos = snapshot.docs.map((doc) => {
        const neWTodo = {
          id: doc.id,
          ...doc.data()
        };
        return neWTodo
      });
      setTodos(newTodos);
    });
}, []);

그래서 getDocs가 아닌 onSnapshot 메서드를 이용해서 실시간으로 데이터를 받기로 했다.

  • onSnapshot() 메서드로 문서를 리슨할 수 있습니다. 사용자가 제공하는 콜백이 최초로 호출될 때 단일 문서의 현재 콘텐츠로 문서 스냅샷이 즉시 생성됩니다. 그런 다음 콘텐츠가 변경될 때마다 콜백이 호출되어 문서 스냅샷을 업데이트합니다.
  • 출처 https://cloud.google.com/firestore/docs/query-data/listen?hl=ko

 

onSnapshot 메서드를 이용해서 데이터를 읽어오는 것으로 코드 수정 후에 데이터 읽기 횟수가 2.4천->73으로 현저하게 줄어든 것을 확인할 수 있다.

 


Programmers 문제 풀기

배열 뒤집기

나의 풀이

function solution(num_list) {
    let array = [];
    for (let i = num_list.length-1; i>=0; i--) {
        array.push(num_list[i])
    }
    return array
}

for문을 돌리는데 i는 num_list.length-1부터 시작해서 0까지 하나씩 줄어든다. 만약 num_list = [1,2,3,4,5]라면 i는 4,3,2,1,0이 되는 것이다. 이렇게 for문으로 생성한 인덱스를 사용해서 array에 하나씩 추가한다.

 

 

다른 사람의 풀이

function solution(num_list) {
    return num_list.reverse()
}

reverse라는 간단한 메서드가 있었구나 ㅎㅎ

 

 

암호 해독

나의 풀이

function solution(cipher, code) {
    let array = [...cipher];
    let array2 = [];
    let answer = ''
    for (i=code-1; i<array.length; i+=code) {
        array2.push(array[i])
    }
    for (let char of array2) {
        answer += char
    }
    return answer  
}

원래 처음에는 이렇게 작성했었는데 for문을 하나 줄일 수 있을 거 같아서 코드를 수정했다.

 

function solution(cipher, code) {
    let array = [...cipher];
    let answer = ''
    for (i=code-1; i<array.length; i+=code) {
        answer += array[i]
    }
    return answer  
}

array2 과정을 생략하고 for문을 돌리면서 바로 answer에 텍스트를 넣어준다.

 

for문을 하나 줄이니까 연산 시간이 많이 줄어들었다. 시간 복잡도 최소화하기!

 

function solution(cipher, code) {
    let answer = ''
    for (i=code-1; i<cipher.length; i+=code) {
        answer += cipher[i]
    }
    return answer  
}

코드 더 간소화하기. 문자열에도 .length( )와 인덱스를 사용할 수 있다! (처음 알았음 ㅎㅎ) cipher 문자열의 length 안에서 for문을 돌리는데 i는 code-1에서 시작해서 code만큼 더해간다. 그리고 for문으로 생성한 index를 이용해서 answer에 문자열을 하나씩 더하면 된다. 그럼 answer에 하단 이미지처럼 문자열이 하나씩 쌓인다.

 

다른 사람의 풀이

function solution(cipher, code) {
    return cipher.split('').filter((v,i)=>(i + 1) % code === 0).join('');
}

cipher.split('')으로 문자열을 배열 안에 하나하나 쪼갠다. split으로 만든 배열을 filter를 이용해서 i+1 % code가 0인 요소만 남긴다. 마지막으로 join 메서드를 이용해서 배열의 모든 요소를 연결해 하나의 문자열로 만든다.

 

나처럼 for문을 사용해서 풀 수도 있지만 filter 사용한다는 아이디어도 너무 좋은 거 같다! 그리고 join메서드를 이 풀이를 보고 처음 알게 되었는데 앞으로 유용하게 쓸 수 있을 거 같다.

 

문자열 펼치기

  • [...string]
  • string.split('')
  • 결과 동일: "pfqallllabwaoclk" -> ['p', 'f', 'q', 'a', 'l', 'l', 'l', 'l', 'a', 'b', 'w', 'a', 'o', 'c', 'l', 'k']

 

join 메서드

const elements = ['Fire', 'Air', 'Water'];

console.log(elements.join());
// expected output: "Fire,Air,Water"

console.log(elements.join(''));
// expected output: "FireAirWater"

console.log(elements.join('-'));
// expected output: "Fire-Air-Water"

join() 메서드는 배열의 모든 요소를 연결해 하나의 문자열로 만든다.

출처 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/join

 


회고

오늘은 오랜만에 여유로운(?) 하루였던 거 같다. 오전에 튜터님이 올려주신 강의 보면서 코드 리팩토링하고 나니까 할 일이 없었다. 그래서 Programmers 문제도 풀고 firebase도 좀 공부했다. 저녁엔 또 팀플 회의 시간을 가졌다.

 

 

 

댓글