회고

[취업준비일지] - 114

Happy Programmer 2023. 2. 11. 23:16

1.리액트의 불변성을 지켜야 한다는 이야기는 자주 들었고
대략적으로 무엇을 의미하는지는 알고 있었고
sideEffect 방지를 위해 필요하다는 정도로 알고 있었다.

하지만 "왜" 그런지에 대해서는 정확하지 않았는데
아래와 같은 작업을 수행할 경우 a는 1에서 2로 값이 변하지만
같은 메모리 영역에 저장되는 것이 아니었다.

let a = 1 //메모리 영역 1
a = 2     //메모리 영역 2

 

 

기존에 이해하고 있는 부분은 배열 및 객체는 heap에 주소값이 저장되기 때문에
sideEffect가 발생할 수 있으니 조심하자는 정도로만 생각했지만
주소값의 변경이 필요하다는 부분까지만 정답이고 중요한 것은 메모리 영역이라는 것을 몰랐다.

아래와 같이 [1,2,3]이라는 배열의 주소값이 메모리 영역 1에 저장되어 있고 
그 주소값에 직접적으로 값을 변경하거나 추가한다면 그대로 메모리 영역 1에서 바뀔 뿐이고
이는 "메모리 영역에서 값이 변하지 않는다"는 불변성을 어기는 것이다.

let arr = [1,2,3] //메모리 영역 1
arr[3] = "a"      //메모리 영역 1 변경
arr.push(5)       //메모리 영역 1 변경
arr.pop()         //메모리 영역 1 변경


하지만 새로운 배열을 만들어 구조분해할당 또는 직접 값을 추가하는 경우
그 배열은 새로운 메모리 영역에 저장되기 때문에 메모리 영역 1의 값을 바꾼 것이 아니고
이는 "메모리 영역에서 값이 변하지 않는다"는 불변성을 지키면서 새로운 값을 할당하는 것이다.

let arr = [1,2,3]               //메모리 영역 1
arr = [...arr, 4, 5]            //메모리 영역 2 
let arr2 = new Array(3).fill(0) //메모리 영역 3
arr = arr2                      //메모리 영역 3

 

 

불변성 불변성 하면서도 왜 숫자나 문자열등은 마음대로 집어넣으면서
배열 및 객체는 새로 선언 후 재작성 또는 구조분해할당을 사용해야 하는지에 대해서
조금은 의아함을 가지고 있었는데

값 자체가 중요한 것이 아닌 메모리 영역 자체의 비교라는 것을 알고나니
기존에 얉은 비교 때문에 구조분해할당을 사용해햐 한다는 것은 알았지만
React가 얉은 비교를 수행하기 때문에 사용해야 한다는 것과
이를 통해 더 빠른 비교를 할 수 있다는 장점이 된다는 것도 이해할 수 있었다.

마지막으로 새로운 배열을 반환해 불변성을 유지할수 있는 방식은
구조분해할당(...arr), map, filter, slice, reduce 등이 있으며
push, pop, splice등은 기존 배열을 수정하기 때문에 불변성을 위반한다.

예시를 들자면
불변성은 아파트 내부에 뭐가 변했는지 파악하기 어려우니
새로운 인테리어를 하고 싶은 경우 주소를 바꾸라는 느낌과 같다.

이름이 불변성이라 헷갈릴 수 있지만
사실은 "불변"이 포인트가 아니라 변헀다는 티를 잘 내달라는 느낌이다.


2.변수명을 선정할 때 페이텔슨의 3단계 모델이라는 것이 있는데 아래의 3가지 규칙이 있다.

1.이름에 포함할 개념을 선택한다.
2.각 개념을 나타낼 단어를 선택한다.
3.이 단어를 사용해 이름을 구성한다.

 

 이름의 의도, 충돌성, 영어 형식에 맞춘 구성을 고려해야 한다.
 
또한 curioustore.com 에서 변수명 짓기 기능을 제공하고 있기 때문에
원하는 정보의 키워드를 입력시 자주 사용되는 변수명을 알려준다.

함수들의 이름을 정할 때는 함수가 하는 기능을 명시하는 것도 나쁘진 않지만
작은 기능들이 통합된 경우 상위 함수들의 이름 통일성을 고려해 추상화해주는 것이 더 좋을 수 있다.

processor, data, info 등 어디에나 사용될 수 있는 단어는 사용을 자제하거나
추가적인 정보를 추가해 명확하게 만들어야 하며 
보편적인 이름은 이해 및 검색이 어려울 수 있기 때문에 구체적인 이름을 사용해야 한다.

특이하게도 length, count, size, capacity 등 유사한 의미라도 다르게 사용되야 하는데
length는 문자열 등 연속적인 요소, count는 느슨한 구성 요소
size는 최대 크기, capacity는 할당된 메모리 등을 지칭할 때 사용해야 한다.


3.주석을 달 때는 이 주석이 쓸모없는 주석이 아닌지를 먼저 생각해봐야 하는데
(90%의 주석은 적을 필요가 없는데 적혀있다고 한다)
코드만 봐도 누구나 이해할 수 있는 내용은 주석을 적을 필요가 없으며
일반적인 함수, 변수명은 선언할 때 작명에 신경써야지 주석으로 해결하려고 해서는 안된다.

일반적으로 주석을 써야 하는 이유는 코드가 이 방식인 이유, 결함, todo, 특이동작, 계획 등
전반적인 흐름 또는 특이사항을 공유하기 위함이라고 볼 수 있다.
(코드의 흐름 뿐 아니라 비지니스 관련 흐름 등도 가능한 것 같다)

요약하면 주석은 how가 아닌 why를 설명해야 한다.


4.클래스형 컴포넌트는 거의 사용되지 않지만 유지보수 또는 예전 라이브러리 등을 사용할 때
함수형 컴포넌트가 지원되지 않아 사용해야 하는 경우가 있다.

기존 함수형이  아래와 같은 형태라고 한다면 

function TodoList({title, content}){
  return(
    <div>
      <div>{title}</div>
      <div>{content}</div>
    </div>
  )
}


클래스형 컴포넌트는 아래와 같은 형태라고 할 수 있다.

class TodoList extends Components{
  render(){
    const {title, content} = this.props;
    return(
      <div>
        <div>{title}</div>
        <div>{content}</div>
      </div>
    )
  }
}


차이점은 Components를 react에서 import해야 한다는 것과
render()를 사용해 내부에 넣어줘야 한다는 것
그리고 this.props에서 props를 구조분해할당으로 꺼내야 한다는 것이다.

상태의 선언은 constructor 내부에 this.state로 설정하거나
바로 state를 선언해줄 수 있다.
하지만 state에 값을 넣을 때는 useState와는 다르게 객체로 감싸서 넣어야 한다.

number = 0           //틀린 방법(component 느낌의 선언)
state = {number : 0} // class형 state 선언


사용하고 싶은 함수는 let, const등으로 선언하는 것이 아니라
class에서 메서드를 선언하듯 함수명과 동작을 작성하면 된다.
또한 상태 변경은 setState를 사용해 접근한다.

addNumber = () => {
  this.setState({
     number: this.state.number + 1
  })
}






(1).백준 4949 균형잡힌 세상은 글자 여부와 관계없이 괄호들이 제대로 닫히는지에 대한 문제였다.
글자는 무시했고 괄호처리가 되었는지를 확인하는 balanceCheck라는 함수를 만들었고
balanceCheck함수는 stack에 열린 괄호들을 저장하며
만약 닫힌 괄호가 나올 경우 balanceMatch에 담긴 대응하는 괄호와
pop으로 꺼낸 stack의 마지막 괄호를 비교해 다를 경우 false("no")를 return하고
열린 괄호가 스택에 남아있는 경우를 stack.length로 한번 더 체크해줬다.

const input = `So when I die (the [first] I will see in (heaven) is a score list).
[ first in ] ( first out ).
Half Moon tonight (At least it is better than no Moon at all].
A rope may form )( a trail in a maze.
Help( I[m being held prisoner in a fortune cookie factory)].
([ (([( [ ] ) ( ) (( ))] )) ]).
 .
 (()
.`.split('\n')

const result = []

const balanceCheck = (str) => {
    let isBalance = "yes"
    const stack = []
    const balanceMatch = {"]":"[", "}":"{", ")":"("}
    
    for(let i = 0 ; i < str.length ; i++){
        if(["[","{","("].includes(str[i])){
            stack.push(str[i])
        }
        else if(["]","}",")"].includes(str[i])){
            const checkNow = stack.pop()
            if(balanceMatch[str[i]] !== checkNow){
                return "no"
            }
        }
    }
    if(stack.length){
        return "no"
    }
    return isBalance
}

for(let i = 0 ; i < input.length-1 ; i++){
    result.push(balanceCheck(input[i]))
}

console.log(result.join('\n'))