제목처럼 프로젝트 캠프로 3주간의 직무교육과 7주간 참여 기업과 프로젝트를 진행합니다. 3주간 진행될 교육에는 아주 기초적인 변수, 데이터 타입, 객체와 함수 등부터해서 실행 컨텍스트와 클로저 같은 JS 심화 지식, 그 이후엔 Next.js 프로젝트에 필수적으로 알아야 할 리액트와 Next.js에 관한 교육이 이루어집니다.
팀원들과 리액트 딥 다이브 책을 공부하는데 생각보다 Next.js를 많이 다뤄주더군요. 그렇게 자연스럽게 Next.js가 어떠한 요구나 문제를 기반으로 탄생하였고, 이 Next.js가 지닌 장점을 알게 되면서 Next.js에, 정확히는 서버에서 다루는 일들이 궁금해졌었습니다. 그래서 네이버 부스트캠프 베이직 과정이 끝난 후 Next.js 프레임워크를 공부하고자 유데미 강의까지 구매했는데, 마침 공부는 물론 기업 연계 프로젝트까지 진행할 수 있는 캠프를 발견하게 된 것이죠. 제겐 두 마리 토끼를 다 잡을 수 있는 아주 좋은 기회였기에 지원을 하게 됐고, 감사하게도 심사에 합격해 참여할 수 있었습니다.
강사님이 generic
은 미리 데이터의 타입을 알 수 없는 경우 사용하는 타입이라고 설명을 해주셨는데, 이 얘길 듣고 "그렇다면 any 또는 unknown과의 차이점이 뭐지?🤔" "왜 generic 사용을 더 권장하는 것일까?"하는 질문이 떠올랐습니다. 그래서 gpt한테 물어봤더니 아래처럼 설명해주더군요.
any
는 어떤 타입이든 수용하지만, 컴파일 타임에 검사를 하지 않고 런타임에 타입을 검사하기 때문에 런타임 때 오류가 발생할 가능성이 매우 높습니다. 그래서 타입 안정성이 부족하다고 할 수 있죠.any
를 사용하면 해당 변수나 함수가 어떤 타입을 다루는지 알 수 없어서 다른 개발자가 봤을 때 코드의 의도를 파악하기가 어렵고, 유지보수도 쉽지 않습니다.unknown
은 any
와 비슷하나, 조금 더 안전합니다. 왜냐하면 unknwon
은 타입의 값을 사용할 때 값의 타입을 명시적으로 검사하거나 변환해주지 않으면 에러가 발생하기 때문이죠. 즉, 개발자가 명시적으로 타입을 전달해주지 않으면 any
와는 달리 런타임 전에 우리에게 "타입을 제대로 전달해줘! 타입 추론을 할 수가 없어!"라고 알려주는 것이죠.unknown
역시도 타입이 명확하지 않아 any
처럼 가독성을 해칩니다.generic
은 컴파일 타임에 타입을 검사합니다. 즉, 런타임 전에 타입 오류를 발견하고 수정할 수 있습니다. (타입 안전성👍)any
와 unknown
를 쓰면 어떤 타입이 반환될지 전혀 알 수 없는 반면 generic
은 어떤 타입을 다루는지 어느 정도 예측할 수 있습니다. generic
을 사용하는 것이 가독성에 더 좋은 것이죠. any
와 unknown
도 재사용할 순 있지만, generic
이 더 높은 수준의 타입 안전성과 명확성을 제공하므로 굳이 any
와 unknown
을 작성해서 재사용할 필요가 있을까 싶네요.강사님께선 자바스크립트 수업도 진행했었는데요, 그 중 클로저도 다루어주셨습니다. 원래 클로저를 알고 있었던 터라 복습한다는 느낌으로 들었는데 이 중 되짚고 싶었던 부분에 대해 정리해보겠습니다.
우선, 클로저 개념은 몰라도 프로그래밍을 하다보면 클로저를 활용한 함수를 활용할 떄가 있죠.(심지어 자신이 클로저를 활용했다는 사실은 모른채) 그래서 범용하기 좋은 실수가 바로 클로저를 해제시켜주는 작업을 빠트리는 것입니다. 애초에 클로저라는 개념을 잘 모르니까 하게 되는 실수이지 않나 싶습니다.
클로저라는 것은 실행 컨텍스트에서 파생된 개념인데요, ECMAScript에 따르면 클로저는 함수와 그 함수가 선언된 어휘적 환경(Lexical Environment)의 조합을 의미합니다. 클로저는 데이터 은닉, 상태 유지, 비동기 처리 등 다양한 상황에서 유용하게 활용되고 있는데, 이 클로저를 사용하면 함수가 자신이 선언된 환경(=스코프) 밖에서도 그 환경의 변수를 기억하고 접근할 수 있습니다.
그러나 클로저가 존재할 때, 자바스크립트 엔진은 클로저가 참조하는 변수들이 메모리에서 제거되지 않도록 관리하기 때문에 자칫 잘못 사용했다간 메모리 누수를 발생시킬 수도 있습니다. 따라서 더 이상 클로저가 필요하지 않게 되면 이를 해제시켜주는 작업을 추가적으로 해줘야 합니다. 예를 들어, 함수 실행 종료 이후에 null
을 선언해주는 것이죠.
뭐... 요즘은 메모리 용량이 커져서 메모리 걱정할 필요 없는 세상이라곤 하지만, 이 사실을 알고 있느냐 없느냐로 생각하며 코드를 작성하는 개발자인지 아닌지 여실히 드러나는 것 같습니다.
그리고 이는 리액트 훅과도 관련이 있죠. 리액트 훅 또한 (리액트 훅들도 클로저를 기반으로 만들어졌으므로) 이벤트를 추가해줬으면 이벤트 핸들러 제거 로직을 추가해줘야 합니다. 이 사실을 저도 최근에 알고 의식적으로 관련 로직을 추가해주려 노력하고 있는데요, 이번 계기로 다시 한번 되짚고 복습할 수 있어서 좋았던 것 같습니다.
강사님이 "이벤트 핸들러에 this를 적용할 적엔 화살표 함수로는 작성할 수 없다".고 하셨습니다.
이 말만 들었을 때는 잘 이해가 가지 않았습니다. 화살표 함수 또한 this 바인딩이 이루어지긴 할 텐데 왜 할 수 없다고 하시는 것이었을까요. 아마도 화살표 함수의 this가 일반 함수의 this와 다르게 바인딩 돼서 이렇게 말씀하시는 것 같은데, 자세히 잘 모르겠어서 gpt한테 물어봤습니다.
요약하자면,
이벤트 핸들러로 일반 함수를 사용하면, this는 이벤트가 바인딩된 요소를 가리킵니다.
화살표 함수는 렉시컬(lexical) 스코프에서 this를 바인딩합니다. 즉, 화살표 함수 내에서 this는 자신을 포함하는 외부 함수나 스코프의 this를 상속받습니다. 이벤트 핸들러로 화살표 함수를 사용하면, this는 전역 객체(window) 또는 외부 스코프의 this를 가리킵니다.
그래서 아래 예제처럼 화살표 함수를 이용해 이벤트 핸들러로 등록하면 버튼을 크릭했을 때 이벤트 핸들러 내에서 this는 클릭된 버튼 요소를 가리키지 않고, 이벤트 핸들러가 정의된 스코프의 this를 가리키게 됩니다. 즉, this가 window 객체를 가리키게 되어 우리가 흔히 사용하는 this의 의미에서 벗어나게 되는 것이죠.
// 화살표 함수 예제
const button = document.querySelector('button');
button.addEventListener('click', () => {
console.log(this); // 외부 스코프의 this를 가리킴, 보통은 window 객체
});
이러한 이유로, 강사님꼐서 이벤트 핸들러 내에서 this를 사용하고자 할 땐 화살표 함수는 작성할 수 없다고 말씀하신 것 같습니다.
이제 다음주부턴 본격적으로 리액트와 Next.js를 공부하게 될텐데, Next.js는 이론상으로만 접해서 좀 걱정되기도 하고, 설레이기도 하네요. 그래도 잘 배워서 프로젝트때 멋지게 사용해보고 싶습니다.