Today's Plan
(1) Pair Game 마무리
Studying JavaScript knowledge
Training Coding Test with Python
(1) 시뮬레이션
(2) 백준코딩 테스트 기출 3문제
1. Pair Game 마무리
모든 기능 구현이 완료되었습니다. 다 정상적으로 작동은 합니다.
다만, 시간 딜레이에 따른 원치 않는 결과가 나옵니다.
상황은 이렇습니다.
제가 카드가 플립되는 시간을 위해 카드가 디스플레이되어 있는 시간을 setTimeout, 1500m을 줘서 해결했었습니다.
그런데 이렇게 하니 사용자가 그 시간보다 먼저 클릭하게 된다면 그 동작은 정상적으로 카운팅이 되지 않아 바로 결과계산이 나오지 않습니다.
만약 사용자가 매 클릭마다 고심해서 1.5초 후에 누른다면 게임은 정상적이긴 합니다만 의도한 게임의 모습은 아닙니다. 따라서 개선해보도록 하겠습니다.
(6)
/ .. 추가 공부가 너무 길었다. 오늘 시간이 좀 딜레이되어서 고치는 건 내일 ! .. /
라고 어제 Pair Game을 마무리했었는데요. 머리 식히고 다음 날 오면 오류가 눈에 잘 보입니다.
거의 1-2분만에 오류를 찾았습니다.
어제 문제였던 상황은, 카드가 클릭되었을 때, 두 카드가 다를 시 바로 뒤집히는게 아니라 내용을 확인할 수 있도록 시간딜레이를 줬고, 그게 전체 게임 이겼는지 판단하는 기능까지 미루게 했기 때문이었습니다.
그래서 전체 게임 이겼는지 판단하는 함수를 시간지연 안으로 끌고 들어와, 바로 체크 가능하게 고쳤습니다.
그리고 해당 프로젝트를 하면서 몇 가지 아리까리한 개념들을 다시 짚고 가려고 합니다.
다 공부한건데 막상 사용하려고 하면 확신이 안 생겨서 고민하게 되는 안타까운 시점들이 있었습니다.
1. setInterval, clearInterval 등 호출스케줄링, 해당 동작을 변수로 받아서 접근할 수 있는 변수 유효범위와 스코프 관련 개념
- setTimeout 문법 : 함수(간혹 문자열: 함수형태), 시간(밀리 초 단위), 인수(해당 함수에 전달할 인수, 화살표 함수 사용하면 필요 없지만, 이름으로 전달해줄 때 유용할 듯)
- setTimeout 사용할 때 유의할 건, 함수를 실행하는게 아니라 그 자체를 넘겨야한다. 함수 위치에 ()로 실행하면 결과밧을 넘겨주는 셈이고, 만약 리턴값 없는 함수면 undefined를 넘기게 된다.
- cleartTimeout: let [타이머식별자] = setTimeout([...]); 하고, 필요할 때 clearTimeout([그 타이머 식별자]) 로 사용 가능
- setInterval: setTimeout과 문법 동일, 다만 시간별로 반복하는 것
- clearInterval: clearTimeout과 문법 동일. setTImeout이랑 엮어서 삭제 시간도 지정 가능했던 재미있는 예제도 기억하자.
- 중첩 setTImeout : setTimeout 안에 setTimeout 호추. 호출 결과에 따라 지연시간 조절도 가능해서 유연한 사용법.
- setInterval vs 중첩setTimeout : setInterval은 지연시간 보장 못 한다. 함수 실행 반복과 동시에 카운트되어서, 반면 중첩setTimeout은 지연 시간 보장 가능하다. 해당 시간 다 마쳐야 새로 또 부르는 식이라서.
- 다만 실제로 사용해보니 setTimeout은 clear하기가 조금 까다로운 측면이 있었다. 잘 컨트롤할 수 있는 예시코드를 좀 더 봐야겠다 싶었다.
- 코드블록: 코드블록은 for, if , while등에서 쓰이는{...}도 포함해서 말하고 있음. 코드블록 외부에서는 내부 변수에 접근 불가능, - 반대로 내부에서 외부로 접근은 가능, 밑에서 말할 렉시컬 환경 접근 등의 설계적 이유로 가능한 것.
- 중첩함수: 함수 안의 함수. 리턴문에서 함수를 리턴하는 경우도 포함되고 이 경우에 내부에서 외부로 접근
가능한 특징을 사용해 중첩함수 내부에 변수를 안 두고 그 변수를 조작하게만 해서 바로 상위함수에 해당 변수 둬서, 반복 호출로 해당 변수 조작 가능.
- 렉시컬 환경 : 내부 숨김 연관 객체. 환경 레코드와 외부 렉시컬 환경에 대한 참조로 이루어져 있다.
- 환경 레코드: 모든 지역 변수를 프로퍼티로 저장하고 있는 객체. 여기서 지역 변수는 함수 등도 포함된다.
- 외부 참조: 말 그대로 상위 렉시컬 환경을 참조하고 있고, 외부 코드와 연결된다.
- 스크립트 전체가 전역 렉시컬 환경으로 기본 정의 되어 있고, 이것의 외부 참조는 null.
단계별 생성과 변경 흐름을 살펴볼 필요가 있다.
- 일단 스크립트 시작되면 전체 변수는 전역렉시컬환경에 올라간다. 값 있으면 값과 함께 없으면 undefined로.
- 이 때 서로에 대한 외부 참조도 같이 설정된다. 그래서 외부 렉시컬 환경이 정의될 수 있다.
- 이 때 함수선언문은 올라간 즉시에 그러니까 스크립트 시작시점부터 사용 가능하고, 함수 표현식은 해당 변수가 있는 코드에서 선언되어야 그 때 사용 가능하다. (이게 아래에서 또 살펴볼 차이점 중 하나)
- 참고로 렉시컬 환경에 대한 개발자의 직접적 조작은 안된다. 명세상 개념.
- 실제적으로 코드에서 변수에 접근할 때 내부에서 먼저 찾고 없으면 외부렉시컬 환경으로 타고 올라가서 거기서 찾는다. 찾아질 때까지 계속 올라간다.
- 위에서 말한 함수를 반환하는 함수 사례를 얘기할 때 중요한 개념이 [[Environment]]라는 숨김프로퍼티이다. 해당 숨김프로퍼티는 함수가 생성될 때 만들어지는데, 해당 함수가 만들어진 위치를 기억한다. 그 말은 본인의 외부 렉시컬 환경을 생성 위치 기준으로 저장하는 셈. 그래서 이 때 반환된 함수 안에 내부적으로 쓰일 변수가 그 중첩함수 자체에 있었으면 초기 생성 함수인 그 중첩함수를 계속 참조해서 그 변수를 조작하고 사용하게 되는 것이다.
- 위의 개념을 좋아한다. 말이 조금 웃긴데, 재밌고 유용한 느낌이어서 좋다.가끔 이런 괜히 좋은 개념들이 있다. 가상화 OS 등등
- 이와 관련된 용어가 클로저. 클로저는 외부 변수를 기억하고 이 외부 변수에 접근할 수 있는 함수를 말한다. 그러니까 위의 사례 속에서는 함수 내에서 리턴된 함수 같은 애.
- 클로저는 다른 언어에서는 구현이 불가능하거나 특수하게 함수를 구성해야 사용 가능한데 자바스크립트는 위의 환경, 숨김프로퍼티와 같은 기본적인 특성들 때문에 모든 함수가 클로저가 되는 것이 가능하다. 모든 함수는 자신의 숨김 프로퍼티인 [[Environment]]를 갖고 있고 본인의 생성 출처도 기억하고, 이를 통해 외부에 접근 가능하기 때문.
- 가비지 컬렉션: 함수 호출이 끝나면 기본적으로 그 함수에 대응되는 렉시컬 환경도 메모리에서 지워진다. 그러나 그 안에 중첩함수가 있다면 이와 연관되어 있으니 당연히 그 함수도 지워지지 않는다. 자체는 더 이상 쓰임이 없어졌을지라도!!
- 그래서 만약 위의 함수를 호출을 여러 군데에서 했으면 동일 렉시컬 환경도 여러 군데에서 쓰여서 이것들이 전부 지워지지 않는 이상 렉시컬환경도 남아있게 된다. '도달 가능'상태이기 때문에. (이 단어와 관련된 개념 정리는 다른 파트에서 했었다. 다시 볼 만한 중요한 내용)
- 이론상으로는 위의 설명과 같이 오래오래 남아있지만, 실제적으로는 자바스크립트엔진이 적절히 최적화 프로세스를 통해 정리해준다. 감사한 일이지만 이런 이유로 종종 디버깅 이슈를 만들어낸다. 시간이 지나 필요에 의해 해당 변수를 찾아 들어가면 뜬금없는 값을 뱉어내는 그런 경우가 생긴다고 한다. 아주 드물지는 않은 특성이라고 하니 나도 만날 수도 있겠다. 긴장 타며 대신 인식을 할 수 있어 이게 이런 이유 때문에 그랬을까라고 추측할 수 있길 바라며 개념 정리!
2. on<event>와 addEventListener 차이와 동작 방식 비교, 쓰임 정리
이벤트리스너 등록방법은 3가지가 있다. 1. HTML의 on<event>속성값에 문자열로 할당. 2. DOM 프로퍼티에 on<event>로 핸들러 함수 할당 3. addEventListener로 이벤트 할당.
우선 HTML의 on<event>와 DOM Property on<event>의 차이
1. HTML의 on는 간단한 짧은 코드등을 넣는데, 대소문자 구분도 안 한다. DOM Property는 대소문자 구분을 한다.
2. 만약 HTML에 속성으로 할당하면 브라우저는 그 속성값을 이용해 새 함수를 만들고 그 생성된 함수를 DOM 프로퍼티에 할당한다. 그러니까 DOM프로퍼티 할당과 동일하게 흘러들어가는 셈. 그래서 그냥 DOM프로퍼티 사용하는게 낫다.
3. 둘 다 짧은 코드는 바로 넣어도 무방하지만 길어지면 함수로 만들어서 할당해주는 것이 좋은데, HTML에서는 "함수()"의 식으로 할당한다. 꼭 호출기호도 넣어줘야 위에서 말했듯 함수를 '만들 수'있다. 반면 DOM Property로 넣으면 절대 호출해서 안된다. 그냥 함수를 전달한다.
4. setAttribute오 핸들러 할당은 하지 않는다. 함수가 문자열로 고정된다.
5. on<event> 삭제하려면 null을 새로 할당하면 된다.
위의 두 방법의 단점은 하나의 이벤트핸들러만 할당할 수 있다는 것이다. 그래서 새로 핸들러를 할당하면 이전것은 지워지고 새로운 핸들러 함수를 덮어씌운다. 그래서 등장한 것이 addEventListener
1.addEventListener는 반면 복수 개의 핸들러 할당이 가능하다. 그리고 options로 once, capture, passive등의 세부 조정도 가능하다.
2. addEventListner를 지울 떄는 removeEventListener를 사용하면 된다. 이 때 꼭 동일 이벤트 객체를 지워야하기 떄문에 addEventLister할당할 때 변수에 저장해두고 그 변수를 이용해야만 지울 수 있다. 함수 생긴 게 같아도 다른 건 다른거다.
헷갈리지 말아야 한다.
3. 특히 몇몇 이벤트 DOMContentLoaded같은 이벤트들은 on<event>가 안 되고 꼭 addEventListener로만 등록이 가능한 경우도 있다.
4. addEventListener를 통해 단순 함수뿐 아니라 객체나 클래스도 이벤트 핸들러로 할당이 가능하다. 꼭 이와 같은 사례 적용해서 사용해볼 것!
- 3방식 모두 이벤트 발생 시 이벤트 객체를 만든다.
3. 함수 선언문과 함수 표현식의 비교
https://ko.javascript.info/function-expressions
4. CSS연산자, CSS선택자
https://poiemaweb.com/css3-selector
https://code.tutsplus.com/ko/tutorials/the-30-css-selectors-you-must-memorize--net-16048
2.Training Coding Test with Python
(1) 시뮬레이션
아.. 진짜 시뮬레이션 너무 어렵다..
아니 어렵지는 않은건가.. 정답을 못 맞춘다. 어찌어찌 시간 쏟으면 최선의 로직은 나오는데 구현력이 딸려서 끝에 가서 코드 터지고, 내 머리 속은 박살이 난다.
그래도 별 수 있나. 자꾸 부딪혀야지. 기 죽지 말고 그냥 하자. 그냥 그냥 그냥
(2) 백준코딩 테스트 기출 3문제
그래도 어려운 문제 접하니까 실력은 느는 느낌이다. 힘든 거 즐기기 ~ 못 즐겨도 실컷 힘들어지기 ~
'Intro > Daily Study Note' 카테고리의 다른 글
[220729] Daily Study Note (0) | 2022.07.29 |
---|---|
[220728] Daily Study Note (0) | 2022.07.28 |
[220726] Daily Study Note (0) | 2022.07.26 |
[220725] Daily Study Note (0) | 2022.07.26 |
[ 모던 JavaScript 튜토리얼 ] 학습 진도 파트2. 브라우저:문서,이벤트, 인터페이스 (0) | 2022.07.25 |