JavaScript

이강현·2025년 8월 17일

JavaScript Core & Data Handling: 심화 학습 노트


Part 3. JavaScript Essentials

Ch 1. Node.js와 NPM: JavaScript 개발 환경 구축

  • Node.js 개요 및 설치:

    • 정의: V8 JavaScript 엔진을 기반으로 하는 서버 사이드 런타임 환경. 브라우저에서만 동작하던 JavaScript를 서버, 데스크톱 애플리케이션 등 다양한 환경에서 실행할 수 있게 합니다.
    • 특징: 이벤트 기반(Event-driven), 논블로킹 I/O(Non-blocking I/O) 모델을 채택하여 적은 리소스로 높은 처리 성능을 보여주며, 실시간 데이터 처리에 강점을 가집니다.
    • 버전: LTS(Long Term Support) 버전은 안정성에 초점을 맞춘 장기 지원 버전으로, 실제 서비스 환경에 권장됩니다. Current 버전은 최신 기능을 포함하지만 안정성이 검증되지 않았을 수 있습니다.
  • NVM (Node Version Manager):

    • 필요성: 프로젝트마다 요구하는 Node.js 버전이 다를 경우, NVM을 통해 시스템에 여러 버전을 설치하고, nvm use <version> 명령어로 프로젝트에 맞는 버전으로 손쉽게 전환할 수 있습니다.
    • 주요 명령어: nvm install <version>, nvm use <version>, nvm ls.
  • NPM (Node Package Manager):

    • package.json: 프로젝트의 이름, 버전 같은 메타 정보와 의존성 패키지 목록을 관리하는 핵심 파일. npm init 명령어로 생성합니다.
    • dependencies vs devDependencies:
      • dependencies: 애플리케이션이 실제 운영 환경에서 동작하기 위해 필요한 패키지 (e.g., React, Express). npm install <package>로 설치.
      • devDependencies: 개발 과정에서만 필요한 패키지 (e.g., Webpack, ESLint). npm install <package> -D 또는 --save-dev 옵션으로 설치.
    • package-lock.json: 의존성 패키지들의 정확한 버전과 하위 의존성 정보까지 모두 기록하는 파일. 이를 통해 다른 개발 환경에서도 동일한 버전의 패키지를 설치하여 일관된 환경을 보장합니다(재현성).
  • 개발 서버 실행과 빌드:

    • package.jsonscripts 필드를 활용하여 npm run <script-name> 형태로 반복적인 명령어를 실행할 수 있습니다. (e.g., "start": "node index.js")
    • 빌드(Build): 개발용 코드를 실제 배포를 위해 압축하고 최적화하는 과정. Babel을 이용한 최신 문법 변환, Webpack 등을 이용한 모듈 번들링(여러 파일을 하나로 합치는 것)이 포함됩니다.
  • 유의적 버전 (SemVer): Major.Minor.Patch

    • Major: 하위 호환성이 보장되지 않는 큰 변경.
    • Minor: 하위 호환성을 유지하면서 새로운 기능이 추가된 변경.
    • Patch: 하위 호환성을 유지하면서 버그를 수정한 변경.
    • 버전 범위: ^ (캐럿)은 명시된 Major 버전 내에서 가장 최신 버전까지, ~ (틸드)는 명시된 Minor 버전 내에서 가장 최신 버전까지 설치를 허용합니다.

Ch 2. JavaScript 기본 문법

  • 데이터 타입:

    • 원시 타입 (Primitive Type): String, Number, Boolean, null, undefined, Symbol, BigInt. 변수에 값 자체가 저장됩니다.
    • 참조 타입 (Reference Type): Object (배열, 함수, 정규식 포함). 변수에 데이터가 저장된 메모리 주소가 저장됩니다.
    • typeof 연산자: typeof nullobject로 반환되는 것은 초기 JavaScript의 설계 오류이므로 주의해야 합니다.
  • 연산자:

    • 동등과 일치: ==는 타입을 강제로 변환하여 비교하므로 예측이 어려울 수 있습니다. 타입까지 엄격하게 비교하는 === 사용이 권장됩니다.
    • 논리 연산자: &&||는 단축 평가(Short-circuit evaluation)를 수행합니다. 예를 들어 expr1 && expr2에서 expr1false이면 expr2는 평가되지 않습니다.
    • Truthy / Falsy: false, 0, '', null, undefined, NaN 6가지 값을 제외한 모든 값은 true로 평가됩니다.
  • 변수 유효범위 (Scope):

    • var: 함수 레벨 스코프. 함수 내 어디서든 접근 가능하며, 중복 선언이 가능하여 실수를 유발할 수 있습니다.
    • let, const: 블록 레벨 스코프. {} (블록) 내에서만 유효하며, const는 재할당이 불가능한 상수를 선언할 때 사용됩니다.
    • TDZ (Temporal Dead Zone): let, const로 선언된 변수는 스코프 시작부터 변수 선언 지점까지 일시적으로 접근할 수 없는 구간이 존재합니다.

Ch 3. 함수

  • 화살표 함수:

    • 문법: function 키워드와 return을 생략하여 코드를 간결하게 만들 수 있습니다.
    • Lexical this: 화살표 함수는 자신만의 this를 갖지 않고, 자신을 감싸고 있는 상위 스코프의 this를 그대로 물려받습니다. 이 특징 때문에 이벤트 핸들러나 메소드 내 콜백 함수에서 유용하게 사용됩니다.
  • 호이스팅 (Hoisting):

    • JavaScript 엔진이 코드를 실행하기 전, var 변수 선언과 함수 선언문을 해당 스코프의 최상단으로 끌어올리는 동작.
    • var 변수는 undefined로 초기화되어 끌어올려지지만, letconst는 초기화되지 않은 상태로 끌어올려져 TDZ에 빠집니다.
    • 함수 표현식은 변수 호이스팅 규칙을 따르므로, 선언 전에 호출할 수 없습니다.
  • 콜백 (Callback):

    • 고차 함수 (Higher-Order Function): 함수를 인수로 받거나, 함수를 결과로 반환하는 함수.
    • 콜백 함수는 이러한 고차 함수의 인수로 전달되는 함수를 의미하며, 비동기 작업(e.g., 서버 요청, 타이머)이 완료된 후 실행될 로직을 정의하는 데 필수적으로 사용됩니다.

Ch 4. 클래스

  • 생성자 함수와 prototype:

    • prototype은 해당 생성자 함수로 생성된 모든 인스턴스(객체)들이 공유하는 공간입니다.
    • 메소드를 prototype에 정의하면, 각 인스턴스가 메소드를 개별적으로 소유하지 않아 메모리를 효율적으로 사용할 수 있습니다.
    • 프로토타입 체인: 어떤 객체의 속성이나 메소드에 접근하려 할 때, 해당 객체에 없다면 그 객체의 prototype을, 거기에도 없다면 그 prototypeprototype을 연쇄적으로 탐색하는 과정.
  • this:

    • 함수 호출: this는 전역 객체(window 또는 global)를 참조 (단, 엄격 모드에서는 undefined).
    • 메소드 호출: 점(.) 앞의 객체를 참조 (e.g., user.getName()에서 thisuser).
    • 생성자 함수 호출: new 키워드로 생성된 인스턴스를 참조.
    • call, apply, bind: this를 명시적으로 지정할 수 있는 메소드.
  • ES6 Classes:

    • prototype 기반의 동작 원리를 문법적으로 더 깔끔하게 포장한 Syntactic Sugar(문법 설탕).
    • constructor: 인스턴스 생성 시 호출되는 초기화 메소드.
    • super: 상속 관계에서 부모 클래스의 생성자(super())나 메소드(super.methodName())를 호출할 때 사용.

Part 4. JavaScript Level up

Ch 1. JS 데이터 심화

  • 배열 메소드:

    • 원본 변경: push, pop, shift, unshift, splice, sort, reverse
    • 새 배열 반환: map, filter, slice, concat, join
    • 기타: forEach(반환값 없음), reduce(하나의 값으로 누적)
  • 객체와 데이터 구조:

    • 구조 분해 할당: 객체나 배열에서 값을 추출하여 변수에 할당. 기본값을 지정하거나, 나머지 요소를 ...rest 변수에 할당할 수 있습니다.
    • 전개 연산자: 배열이나 객체를 복사하거나 병합할 때 매우 유용. 참조 관계를 끊고 새로운 배열/객체를 생성합니다(단, 얕은 복사).
  • 불변성 (Immutability):

    • 중요성: 참조형 데이터를 직접 수정하면, 해당 데이터를 참조하는 모든 곳에서 예기치 않은 사이드 이펙트가 발생할 수 있습니다. 불변성을 지키면 데이터의 흐름을 예측하기 쉬워지고 디버깅이 용이해집니다.
    • 실천: 참조형 데이터를 수정할 때는 원본을 바꾸지 않고, 전개 연산자나 slice 등의 메소드를 활용해 복사본을 만들어 수정 후 반환하는 패턴을 사용합니다.
  • 얕은 복사와 깊은 복사:

    • 얕은 복사: 객체의 1단계 깊이까지만 복사. 내부에 중첩된 객체는 원본과 같은 메모리 주소를 참조합니다.
    • 깊은 복사: 객체 내부의 모든 중첩된 객체까지 재귀적으로 복사하여 완전히 독립된 사본을 생성합니다.
      • 간단한 방법: JSON.parse(JSON.stringify(obj))는 함수, undefined 값 등을 유실하는 단점이 있습니다.
      • 안정적인 방법: lodash 라이브러리의 cloneDeep 메소드를 사용하는 것이 일반적입니다.

Ch 2. JS 데이터 실습

  • 모듈 (ESM):

    • Named Exports: export { a, b } / import { a, b } from './file.js'. 여러 개를 내보낼 수 있으며, 가져올 때 원래 이름을 사용해야 합니다.
    • Default Export: export default a / import myA from './file.js'. 파일 당 하나만 가능하며, 가져올 때 원하는 이름으로 지정할 수 있습니다.
  • fetch() API와 Promises:

    • 외부 API에 데이터를 요청할 때 fetch() 함수를 사용. 이 함수는 Promise 객체를 반환합니다.
    • Promise는 비동기 작업의 최종 성공 또는 실패를 나타내는 객체.
    • .then(callback)으로 성공 시의 결과를, .catch(callback)으로 실패 시의 에러를 처리하며, .finally(callback)으로 성공/실패와 무관하게 마지막에 실행될 로직을 정의합니다.

Ch 3. 정규표현식

  • 주요 패턴(표현):
    • 앵커(Anchor): ^는 문자열의 시작, $는 문자열의 끝에 일치.
    • 수량자(Quantifiers): *(0개 이상), +(1개 이상), ?(0개 또는 1개), {n,m}(n개 이상, m개 이하).
    • 그룹(Group): (...)는 패턴을 그룹화하고, 일치된 부분을 캡처. (?:...)는 캡처하지 않는 그룹.
    • 문자 집합(Character Set): [abc]는 a, b, c 중 하나와 일치. [a-zA-Z]는 모든 알파벳과 일치.
    • (?<=A)B (긍정형 후방 탐색): A가 앞에 있는 B를 찾음 (A는 결과에 포함되지 않음).
    • A(?=B) (긍정형 전방 탐색): 뒤에 B가 있는 A를 찾음 (B는 결과에 포함되지 않음).
  • 실용 예제 (이메일 검증): /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ 와 같이 복잡한 규칙을 가진 문자열을 검증하는 데 효과적으로 사용됩니다.
profile
백엔드 개발자 지망생입니다.

0개의 댓글