JS
[JS] 자바스크립트 기본문법~부울형까지
coco030030
2025. 4. 2. 09:42
🧠 자바스크립트 기본 원리
자바스크립트의 핵심 특성
// 자바스크립트는 동적 타입 언어입니다
// 이유: 변수의 타입이 런타임에 결정되고 변경될 수 있음
let value = 10; // 숫자 타입
value = "Hello"; // 같은 변수가 문자열 타입으로 변경 가능
value = true; // 부울 타입으로도 변경 가능
// 자바스크립트는 인터프리터 언어입니다
// 이유: 코드가 위에서 아래로 한 줄씩 해석되고 실행됨
console.log("첫 번째 줄"); // 먼저 실행
console.log("두 번째 줄"); // 그 다음 실행
🧩 변수와 자료형
1️⃣ 변수 선언 방식의 논리적 비교
// 변수 선언의 세 가지 방식과 각각의 특성
const PI = 3.14; // 불변성(immutability): 값 변경 불가, 선언 시 초기화 필수
let count = 0; // 가변성(mutability): 값 변경 가능, 블록 스코프
var oldWay = "test"; // 함수 스코프: 호이스팅 발생, 재선언 가능 (사용 지양)
// 논리적 결정 과정:
// 1. 이 값이 변경될 필요가 있는가? NO → const 사용
// 2. 이 값이 변경될 필요가 있는가? YES → let 사용
2️⃣ 자료형의 체계적 분류
원시 타입 (값이 직접 저장)
// 숫자형(Number) - IEEE 754 표준의 64비트 부동소수점 사용
let integer = 10; // 정수
let float = 10.5; // 부동소수점
let exponential = 2e3; // 지수 표기법 (2000)
// 문자열형(String) - 텍스트 데이터
let singleQuotes = '안녕'; // 작은따옴표
let doubleQuotes = "안녕"; // 큰따옴표
let template = `${singleQuotes}하세요`; // 템플릿 리터럴(백틱)
// 부울형(Boolean) - 논리적 상태 표현
let isActive = true; // 참: 조건이 충족됨
let isComplete = false; // 거짓: 조건이 충족되지 않음
// null과 undefined - '값 없음'의 두 가지 상태
let intentionallyEmpty = null; // 개발자가 의도적으로 '값 없음' 설정
let uninitializedVariable; // 자동으로 undefined 할당됨
원시 타입 vs 참조 타입의 논리적 차이
// 원시 타입: 값이 직접 복사됨
let a = 5;
let b = a; // 값 5가 복사됨
a = 10; // a만 변경됨
console.log(b); // 5 (영향 받지 않음)
// 참조 타입: 메모리 참조가 복사됨
let arr1 = [1, 2, 3];
let arr2 = arr1; // 참조가 복사됨
arr1.push(4); // arr1 변경
console.log(arr2); // [1, 2, 3, 4] (arr2도 영향 받음)
🔢 데이터 처리
1️⃣ 타입 변환 - 명시적 vs 암시적
명시적 변환 (개발자 의도)
// 문자열 → 숫자
let strNum = "42";
let num1 = Number(strNum); // 기본 변환
let num2 = parseInt(strNum); // 정수로 변환
let num3 = parseFloat("3.14"); // 부동소수점으로 변환
// 숫자 → 문자열
let num = 42;
let str1 = String(num); // 기본 변환
let str2 = num.toString(); // 메서드 사용
let str3 = `${num}`; // 템플릿 리터럴
// 부울 변환
let bool1 = Boolean(1); // true
let bool2 = Boolean(""); // false
let bool3 = !!"hello"; // true (이중 논리 부정)
암시적 변환 (자동 변환) - 기술적 세부사항
// 숫자 + 문자열 → 문자열
console.log(5 + "10"); // "510" (연결)
// 문자열 - 숫자 → 숫자
console.log("10" - 5); // 5 (뺄셈)
// 부울 + 숫자 → 숫자
console.log(true + 1); // 2 (true는 1로 변환)
console.log(false + 1); // 1 (false는 0으로 변환)
// 비교 연산
console.log("5" > 3); // true (문자열 "5"가 숫자 5로 변환)
2️⃣ 연산자 우선순위 (체계적 참조)
// 연산자 우선순위 (높은 것부터)
// 1. 괄호 ()
// 2. 증감 (++, --)
// 3. 곱셈/나눗셈 (*, /, %)
// 4. 덧셈/뺄셈 (+, -)
// 5. 비교 (<, >, <=, >=)
// 6. 동등/일치 (==, ===, !=, !==)
// 7. 논리 AND (&&)
// 8. 논리 OR (||)
// 9. 할당 (=, +=, -=, 등)
// 복잡한 표현식의 예
let result = 5 + 3 * 2; // 11 (곱셈 먼저)
let result2 = (5 + 3) * 2; // 16 (괄호 먼저)
👁️🗨️ 헷갈리기 쉬운 개념
1️⃣ 동등(==) vs 일치(===) 연산자
// == (동등): 타입 변환 후 비교
// === (일치): 타입과 값 모두 비교
// 🧠 논리적 이해: == 사용 시 자바스크립트는 암시적 타입 변환을 수행
console.log(5 == "5"); // true (타입 변환 발생)
console.log(5 === "5"); // false (타입이 다름)
// 📋 체계적 비교:
console.log(0 == false); // true (둘 다 falsy 값)
console.log(0 === false); // false (숫자 vs 부울)
console.log(null == undefined); // true (둘 다 '값 없음'으로 간주)
console.log(null === undefined); // false (다른 타입)
2️⃣ 변수명 vs 변수 값 (혼동하기 쉬운 개념)
// 변수명: 식별자(이름표)
// 변수 값: 저장된 데이터
// 변수명 규칙:
// - 문자, $, _로 시작 (숫자로 시작 불가능)
// - 영문, 숫자, $, _만 포함 가능
// - 예약어 사용 불가
// ✅ 올바른 예시
let user_age = 30; // 변수명: user_age, 값: 30
let $element = document.getElementById("main");
let _private = "비공개 데이터";
let camelCase = "권장되는 방식";
// ❌ 잘못된 예시
// let 1user = "김철수"; // 숫자로 시작 불가
// let user-name = "홍길동"; // 하이픈 사용 불가
// let if = "조건"; // 예약어 사용 불가
3️⃣ 부울 평가에 대한 깊은 이해
// 자바스크립트에서 거짓으로 평가되는 값들
console.log(Boolean(false)); // false
console.log(Boolean(0)); // false
console.log(Boolean("")); // false (빈 문자열)
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean(NaN)); // false
// 그 외 모든 값은 true로 평가됨
console.log(Boolean("0")); // true (빈 문자열이 아님)
console.log(Boolean([])); // true (빈 배열도 true)
console.log(Boolean({})); // true (빈 객체도 true)
// 이 지식을 활용한 간결한 조건문
let username = "";
if (!username) {
console.log("사용자 이름을 입력하세요"); // 빈 문자열이므로 실행됨
}
// 논리 연산자를 활용한 기본값 설정
let userInput = "";
let displayName = userInput || "Guest"; // "Guest" (userInput이 falsy)
🛠️ 실용적 코드 패턴
1️⃣ 변수 선언 및 할당 패턴
// 👍 권장 패턴
// 1. 관련 변수 그룹화
const MAX_USERS = 100;
const MIN_AGE = 18;
const MAX_AGE = 65;
// 2. 변수 이름 명확하게 (의미 전달)
let currentUserCount = 42; // 'count' 보다 명확
let isUserActive = true; // 상태를 나타내는 변수는 'is' 접두사
// 3. 상수는 대문자와 언더스코어로 (관례)
const API_KEY = "abcd1234";
const DEFAULT_SETTINGS = { theme: "dark", notifications: true };
2️⃣ 코드 구조화 패턴
// 1. 체계적인 들여쓰기
if (condition) {
// 항상 2칸 또는 4칸 들여쓰기 일관되게 사용
console.log("조건 충족");
// 중첩된 블록도 동일한 들여쓰기 규칙 적용
if (anotherCondition) {
console.log("중첩 조건 충족");
}
}
// 2. 관련 코드 블록 구분
// 사용자 인증 관련
const userId = "user123";
const userRole = "admin";
// 데이터 처리 관련 (빈 줄로 구분)
const data = fetchData();
const processedData = processData(data);
📋 핵심 요약
🔍 개념적 이해
- ✅ 자바스크립트는 동적 타입 언어: 같은 변수에 다른 타입 할당 가능
- ✅ 원시 타입 vs 참조 타입: 값 복사 vs 참조 복사의 차이
- ✅ 타입 변환의 원리: 타입 강제 변환이 언제, 왜 발생하는지 이해
- ✅ 논리 평가 시스템: 어떤 값이 true/false로 평가되는지와 그 이유
📝 실용적 지침
- ✅ 변수 선언 시
const
를 기본으로 사용, 필요할 때만let
사용 - ✅ 비교 연산자는
===
(일치)를 사용하여 타입 오류 방지 - ✅ 변수명은 기능/역할을 명확히 표현하도록 작성
- ✅ 코드는 항상 일관된 들여쓰기와 구조로 작성
⚠️ 주의해야 할 함정
- ⚠️ 암시적 타입 변환으로 인한 예상치 못한 결과
- ⚠️ 변수 범위(스코프) 오해로 인한 접근 오류
- ⚠️ 부동소수점 계산의 정밀도 문제 (
0.1 + 0.2 !== 0.3
) - ⚠️
null
과undefined
의 차이점 혼동
🔄 균형 잡힌 학습 접근법
개념적 이해와 실용적 적용의 균형
// 개념: 자바스크립트 함수는 일급 객체입니다
// (이론적 이해 - N 성향)
function greeting(name) {
return `안녕하세요, ${name}님!`;
}
// 실용: 함수 즉시 호출하기
// (실제 적용 - S 성향)
console.log(greeting("홍길동")); // "안녕하세요, 홍길동님!"
계획된 구조와 유연한 탐색의 균형
// 구조화된 접근 (J 성향)
// 1. 변수 정의
const maxAttempts = 3;
let currentAttempt = 0;
// 2. 로직 구현
function login() {
currentAttempt++;
if (currentAttempt <= maxAttempts) {
console.log(`로그인 시도: ${currentAttempt}/${maxAttempts}`);
}
}
// 실험적 접근 (P 성향)
// 다양한 방식으로 시도해보기
login(); // "로그인 시도: 1/3"
// 다른 방식 시도
let attempts = Array(3).fill(0).map((_, i) => `시도 ${i+1}`);
console.log(attempts); // ["시도 1", "시도 2", "시도 3"]
심화 개념
// 1. 스코프와 클로저의 논리적 이해
function createCounter() {
let count = 0; // 외부에서 직접 접근 불가능한 변수
return {
increment: function() { count++; },
decrement: function() { count--; },
getValue: function() { return count; }
};
}
const counter = createCounter();
counter.increment();
console.log(counter.getValue()); // 1
// count 변수는 외부에서 접근 불가 (캡슐화)
// 2. 비동기 처리의 논리적 흐름
console.log("시작"); // 1
setTimeout(() => {
console.log("타이머 완료"); // 3
}, 0);
console.log("끝"); // 2
// 실행 순서: "시작" → "끝" → "타이머 완료"
// 이유: 이벤트 루프와 콜 스택의 작동 방식
학습 패턴
// 깊이 있는 개념 탐구
// 예: 프로토타입 상속 이해하기
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
return `안녕하세요, ${this.name}입니다`;
};
const person1 = new Person("김철수");
console.log(person1.greet()); // "안녕하세요, 김철수입니다"
// 자기주도적 실험
// 새로운 메서드 추가해보기
Person.prototype.farewell = function() {
return `${this.name}이(가) 작별 인사를 합니다`;
};
console.log(person1.farewell()); // "김철수이(가) 작별 인사를 합니다"
📊 데이터와 함수의 논리적 관계
데이터 변환 체인 (매우 논리적인 접근)
// 데이터 처리 파이프라인
const users = [
{ id: 1, name: "홍길동", age: 25, active: true },
{ id: 2, name: "김철수", age: 17, active: false },
{ id: 3, name: "이영희", age: 30, active: true }
];
// 함수형 접근으로 데이터 변환
const activeAdults = users
.filter(user => user.active) // 활성 사용자만 필터링
.filter(user => user.age >= 18) // 성인만 필터링
.map(user => `${user.name} (${user.age}세)`) // 원하는 형식으로 변환
.join(", "); // 결과 합치기
console.log(activeAdults); // "홍길동 (25세), 이영희 (30세)"
// 이유와 원리: 각 단계가 독립적으로 작동하며 입력을 받아 출력을 생성
순수 함수와 부수 효과 (논리적 코드 구조)
// 순수 함수: 동일 입력 → 항상 동일 출력, 부수 효과 없음
function add(a, b) {
return a + b; // 외부 상태 변경 없음
}
// 부수 효과가 있는 함수: 외부 상태 변경
let total = 0;
function addToTotal(value) {
total += value; // 외부 변수 변경 (부수 효과)
return total;
}
// 부수 효과 최소화의 논리적 이점:
// 1. 테스트 용이성
// 2. 예측 가능성
// 3. 재사용성
// 4. 병렬 처리 가능성
🧪 문제 해결 접근법
문제: 사용자 입력 검증 시스템 만들기
// 접근법 1: 구조적 접근 (J & S)
function validateUserInput(input) {
// 1. 명확한 단계별 검증
if (!input) {
return "입력값이 비어있습니다";
}
if (input.length < 3) {
return "입력값이 너무 짧습니다 (최소 3자)";
}
if (!/^[a-zA-Z0-9]+$/.test(input)) {
return "영문자와 숫자만 허용됩니다";
}
return "유효한 입력입니다";
}
// 접근법 2: 유연한 패턴 기반 접근 (P & N)
function createValidator(rules) {
return function(input) {
for (const rule of rules) {
const result = rule.test(input);
if (!result.valid) {
return result.message;
}
}
return "유효한 입력입니다";
};
}
const userValidator = createValidator([
{
test: input => ({ valid: !!input, message: "입력값이 비어있습니다" }),
reason: "빈 입력 방지"
},
{
test: input => ({ valid: input.length >= 3, message: "입력값이 너무 짧습니다" }),
reason: "최소 길이 보장"
}
]);
// 두 방식 모두 활용하기
console.log(validateUserInput("a1")); // "입력값이 너무 짧습니다 (최소 3자)"
console.log(userValidator("a1")); // "입력값이 너무 짧습니다"
🔧 현실적 코딩 전략
1. 깊이 있는 독립적 분석
// 목표: 특정 기능의 작동 방식 이해하기
// 예: Array.reduce() 메서드 분석
// 1단계: 기본 사용법 이해
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((total, current) => total + current, 0);
console.log(sum); // 15
// 2단계: 직접 구현해보기
function myReduce(array, callback, initialValue) {
let accumulator = initialValue !== undefined ? initialValue : array[0];
const startIndex = initialValue !== undefined ? 0 : 1;
for (let i = startIndex; i < array.length; i++) {
accumulator = callback(accumulator, array[i], i, array);
}
return accumulator;
}
// 3단계: 테스트하기
const mySum = myReduce(numbers, (total, current) => total + current, 0);
console.log(mySum); // 15
2. 논리적 디버깅 접근법
// 문제: 예상치 못한 결과가 나왔을 때
// 나쁜 예: 무작정 코드 수정
function calculateTotal(prices) {
let total = 0;
for (let i = 0; i < prices.length; i++) {
total += prices[i]; // NaN이 나오는 이유는?
}
return total;
}
// 좋은 예: 논리적 단계별 분석
function debugCalculateTotal(prices) {
let total = 0;
for (let i = 0; i < prices.length; i++) {
console.log(`현재 값: ${prices[i]}, 타입: ${typeof prices[i]}`);
// 타입 검사 및 변환
if (typeof prices[i] !== 'number') {
prices[i] = Number(prices[i]);
console.log(`변환 후: ${prices[i]}`);
}
total += prices[i];
console.log(`현재 합계: ${total}`);
}
return total;
}
// 예상치 못한 결과의 원인: 문자열이 포함된 경우
debugCalculateTotal([100, "200", 300]); // 정상적으로 600 반환
📝 자바스크립트 마스터플랜
1. 심층적 개념 이해
- ✅ 실행 컨텍스트와 호이스팅의 원리
- ✅ 프로토타입 상속과 객체지향 개념
- ✅ 클로저의 작동 원리와 활용 사례
- ✅ 비동기 프로그래밍의 기본 패러다임
2. 균형 잡힌 실습
- ✅ 개념 학습 후 즉시 작은 예제 구현
- ✅ 체계적 프로젝트와 자유로운 실험 병행
- ✅ 코드 분석과 직접 작성 모두 연습
- ✅ 명확한 목표가 있는 프로젝트와 탐색적 코딩 모두 시도
3. 코드 품질 향상 전략
- ✅ 코드 리팩토링 연습: 같은 문제를 여러 방식으로 해결
- ✅ 논리적 오류 찾기: 의도적으로 버그 심어놓고 찾기
- ✅ 독립적 학습: 공식 문서 읽고 요약하기
- ✅ 깊은 이해: 자바스크립트 엔진의 내부 작동 원리 탐구