Basic CS HA 문제 review

김형주·2021년 4월 23일
0

시작하며

단순히 문제와 답안을 비교하는 것 뿐만아니라 놓치고 있던 개념들을 체크하고 주석으로 달아보는 것이 목적이다. 그렇기 때문에 당시 했던 내 생각이나 멘붕이 왔던 지점들을 하나하나 체크해보려고 한다. 확실히 놓쳤던 부분을 체크하는 것이 목적이기 때문이다. 솔직히 뭐든지 구글링하면 나오지만 놓친거는 체크안하면 평생 구글링하게 된다. 하아...

(*주의*) 혹시 다음 차수에 들어오는 사람이 있을까봐 답은 display : none 시켜두었다. 가능하면 읽지 말고 푸시는 걸 추천드린다.

성장이 목표라면 답을 보지 않는 편이 성장에 더 큰 도움이 됩니다.

1.구조분해(Destructuring)

문제 답안

문제의도 : 구조분해 문법을 사용할 줄 아는가?

당시 상황

초기에 내가 접근할 때에는 let { name, company, age } = original; 이 방식으로 새 객체를 만들 수 있다고 생각했다. 하지만 변수명에서 저렇게 하는 건, let name = original.name; , company = original.company, age = original.age; 이런식으로 객체 내부의 속성들을 분해해서 새 변수에 넣어주는 방식이다. 분명히 이 부분을 확실히 안다고 생각했는데 왜 이렇게 접근했는지 모르겠다.

문제를 추적하고 느낀점

명시적으로 변수를 만드는 것은 필요한 상황만을 한정하도록 해야한다.

아마도 새 객체를 만들때 명시적으로 변수에 담아서 리턴해야한다는 생각이 짙었기 때문이라고 생각한다. 객체를 리턴하던, 배열을 리턴하던, 익명으로 자료를 만들어서 리턴하는 방식에 익숙해지는게 좋을 듯 하다. 오늘 Toy Problem을 풀면서 크게 느꼈는데, 변수를 만든다는 건 Scope가 형성된다는 것을 의미하고, 그 범위는 내가 새롭게 파고들 때 고려하지 못할 가능성이 커지기 때문이다. 변경된 값을 리턴할 때는 최대한 값만 만들어서 리턴하는 방식에 익숙해져야겠다.

2.자료구조 - 큐(Queue)

문제 답안

문제의도 : 자료구조 '큐'를 구현할 줄 아는가?

당시 상황

이 문제에서 나는 queue기 때문에 앞뒤 번호를 붙여줘야했는데(rear,front,length) 초기에 길이와 앞번호로만 접근했다. 그러다가 다 삭제될 때 firstIndex가 0이 되지 않는 것을 알게되어 front와 rear로 나누어 생각해줬다. 근데 reference에는 firstIndex가 계속 증가하는 구조다. 사실 내부에서 어떻게 구동되는지는 몰라도되서 이렇게 구현을 하신건진 모르겠지만, 그냥 0보다 작을 때 firstIndex를 0으로 재 초기화 해주는게 나을거 같다.그게 훨씬 더 직관적이기도 하고 다른 사람이 봤을 때도 확실하게 알 수 있지 않나 그런 생각이 들었다.firstIndex = 0; 초기화 부분이 없어서 더 읽히기가 어려웠던 것 같다.

문제를 추적하고 느낀 점

여기에서 겪었던 문제는 this._storagethis.storage로 적어서 계속 통과가 되지 않았었다. 어떻게 보면 코드를 너무 대강 읽는 경향이 있는 것 같다. 이런 부분들이 디테일하지 못한 것 같다. 어떤 변수가 있고, 어떤 변수명인지 정확히 기억하면서 코드를 작성해야겠다는 생각을 했다. 통과가 안될때는 열받았지만 변수명이 틀린다는 생각을 전혀 하지못했다. 뭔가 Pass가 안되는 상황에서는 변수명을 가장 1순위로 확인해야겠다.

뭔가 잘 안된다면 일단 변수명을 확인해보자 ^^

3.상속(inheritance)

문제 답안

문제의도 : class keyword와 상속 구현을 할 줄 아는가?

당시 상황

super() 부모 생성자에 부모 전달인자를 넣어야되는건 알고 있었지만, 자식 생성자에 부모 전달인자를 꼭 넣어야되는지를 잘 모르고 있었다. 그래서 초기에 super(name)은 넣었지만, constructor(name, color)가 아니라, constructor(color)만 넣었다. 전부 상속받았다면 자식 생성자에 상속받은 전달인자도 넣어야된다는 걸 알게 되었다.

문제를 추적하고 느낀 점

이것도 되게 사소한 문제지만, 중요한 포인트였다. super()키워드를 쓸 때 어떻게 써야하는지 명확하게 알 수 있는 계기가 되었다. 상속을 받았을 때, 모든 property를 상속받았다면 부모 생성자에서 초기화하는 값들의 전달인자들도 자식 생성자에 모두 전달해주어야한다.

  • 부모 생성자함수의 전달인자들을 자식 생성자함수에서도 적어주어, 둘다 생성되도록 만들어줘야 한다.
  • 부모의 메소드명와 자식의 메소드명이 같을 때 오버라이딩되어 어떤 메소드를 부를지 결정하는 것이 아니라, 인스턴스에서 더 가까운 메소드를 부르게 된다. 예를 들어, 부모 클래스의 인스턴스라면 부모의 메소드를 부르게 되고 자식 클래스의 인스턴스라면 자식의 메소드를 부르게 된다.
  • 김홍식 엔지니어님께서 말씀해주셨던 것 중에, 오버라이딩에 대한 설명을 잊지 않도록 해야겠다.

4.상속(inheritance)

문제 답안

문제의도 : 재귀 함수 사용에 익숙한가?

당시 상황

나는 당연히 input이 1차원 배열인 줄 알고, 너무 쉬운 문제가 나왔다고 생각했다. length가 0이 되는 순간 탈출조건을 두고, console.log(arr.shift());를 이용해서 하나씩 뽑아서 console을 찍고 나머지가 된 배열을 바로 return으로 재귀로 보내서 하나하나 찍는 전략을 선택했다. 계속해서 12,345가 잘못찍힌다는 식으로 나왔는데 아마도 배열 안에 [12,345] 이런식으로 만들어진 요소가 있어서 12,345가 그대로 찍혔던 것 같다. 이때 눈치를 챘어야되는데 꽤 오랜 시간 계속 돌려보고 있었다. 이후에 이상하다는 점을 파악하고 array객체 내장 메소드인 flat()메소드를 이용해서 차원을 낮춰주고 console.log로 해결할 수 있었다.

문제를 추적하고 느낀 점

답안을 보니, 아무래도 다차원 배열이 들어왔을 때 이걸 분기로 풀어내고 console을 찍을 수 있냐고 물어보는 문제인 것 같다.탈출조건은 동일한데, 원본 배열을 array 내장 메소드인 slice를 이용해서 복사해서 해결했다. 원본을 바꾸는 것이 일단은 안 좋은데, 그냥 편하게 하고 싶어서 선택한 방법이긴 했다. 추적해보니 중간 분기를 보니 물어보는 목적을 정확히 이해할 수 있었다. 총 2개로 분기를 하게 되는데(else if와 else를 통해서 1가지로 분기한다고 쳤다.)

  • if(Array.isArray) : 배열안의 겹배열, 그니까 다차원 배열일 경우를 분기시킨다.
  • else if(temp), else : falsy값을 분기시킨다. 예를 들어 배열에 중간에 null, 0,

undefined, NaN, false, ""와 같은 요소들이 있을때는 잘라내고 새로 재귀를 보낸다. 만약 falsy값이 아니면 값이 배열이 아닌 값이라는 뜻이므로, log를 찍는다. 근데 왜 이렇게 분기를 하셨는지 이상하다. 0도 요소긴 해서 console을 해주셔야 할텐데, falsy값으로 필터링을 하면 0은 사라져버린다. 이 부분을 위해서 flat() 메소드와 falsy 필터링을 자세히 블로깅 해봐야겠다.

  1. 원본으로 받은 input은 가능하면 변경시키지 않도록 한다.(slice > splice)
  2. 희소배열을 필터링하는 방법에 대해서 더 자세히 공부해보자.

5.this keyword

문제 답안

문제의도 : this가 어디에 바인딩되는지 알고있는가?

당시 상황

this가 당연히 본인 객체를 가르키고 있어서, 쓸 수 있다는 사실은 알고 있었는데, 배열이 그냥 players의 name속성만 배열로 만드는 것으로 착각하고 이름만 모아서 던졌다. 이 부분은 명확하게 코드를 읽지않고 쳤기에 그런 상황이 벌어진 것이다. 그리고 계속 reduce 사용에만 익숙한데, 뭔가를 가지고 하나로 만들어서 return해야하는 경우 map을 더 자주 활용하도록 노력하자. 초깃값이 없어도 바로 배열로 만들 수 있기 때문에 훨씬 고려해야할 것도 적고 인자도 그냥 요소만 던져주면되서 편하다.

문제를 추적하고 느낀 점

문제를 제대로 읽지않고 코드에 먼저 손이 간다는게 가장 큰 문제라는 생각이 든다. 뭘 출력해야되는지 속으로 정해놓고, 코드를 치고 안된다고 혼자 화내는 편이다. 항상 문제를 자세히 읽는 습관을 들이고, map, reduce, filter, forEach, sort 이런 고차함수를 상황에 맞는 녀석들로 골라서 사용할 수 있도록 하자.

문제를 제대로 읽자.
고차 함수를 상황에 맞는 놈으로 골라쓰자. reduce하나만 써서는 어림도 없지!
생각없이 코드 치지말고 멈춰!!!!

6.자료구조 - 트리(Tree)

문제 답안

문제의도 : 자료구조 'Tree'를 구현할 줄 알고, 응용할 줄 아는가?

당시 상황

addChild에 child가 들어있었지만 이게 왜 있는지에 대한 의문을 갖지않고 그냥 value로 생각을 하고 addChild를 완성시켰다. 그리고 나서 map에와서 재귀로 하려니까 너무 어려워서 재귀함수를 만들어 하나하나 가지고와서 복사하는 방법을 택했다. 재귀함수를 적으니까 원본객체와 복사한 객체를 구분해야했고, clone과 proto의 경계를 구분하는 것이 너무 복잡했다. 결국에는 정의 되지 않은 것까지 구분을 해서 ||연산자로 값을 넣어줘야했고 시간이 오래 걸렸다.

문제를 추적하고 느낀 점

의도를 파악하지 못한 불찰이 크다. 하지만 이걸 내가 이 방법으로 풀 수 있었을까 싶긴했다. map 메소드를 재귀로 사용하기 위해서 addChild에 instance가 들어오는 경우를 분기시켰고, instance가 들어와도 addChild할 수 있는 메소드로 바꿔줬다. 아예 this.children으로 계속해서 재귀에서 this가 바뀌는 것을 이용해서 굳이 클론과 원본객체를 구분하지 않고 원본객체만 돌면서 복사객체에 addChild를 할 수 있도록 했다. 여기에 reduce를 이용해서 순회하면서 addChild를 붙이고, 새 child에 map을 통해 callback을 적용하는 방식으로 자동으로 순회하면서 callback한 children들을 붙이는 식으로 구성했다. 내장고차함수를 이렇게 쓸 수도 있다는걸 테스트해봐야겠다.

reduce를 이용해서 객체의 children을 순회할 수 있다.
객체를 복사할때는 객체를 새로만들어서 reduce를 이용해 비교 대입가능할 수 있다.
addChild는 값을 이용한 인스턴스 생성말고도 인스턴스 자체를 삽입하는 메소드로 확장할 수 있다.

와미쳤다..
답 코드는 싹다 지웠다. 전부 노션으로 옮김

profile
만물에 관심이 많은 잡학지식사전이자, 새로운 도전을 꿈꾸는 주니어 개발자 / 잡학지식에서 벗어나서 전문성을 가진 엔지니어로 거듭나자!

0개의 댓글