3.1 조건문
조건문이란?
조건문은 주어진 조건에 따라 다른 코드 블록을 실행하는 제어 구조입니다. JavaScript는 if/else, switch, 삼항 연산자를 지원합니다.
if / else 문
기본 구조
const temperature = 25;
if (temperature > 30) {
console.log("덥네요!");
} else if (temperature > 20) {
console.log("적당한 날씨입니다.");
} else if (temperature > 10) {
console.log("쌀쌀합니다.");
} else {
console.log("춥네요!");
}
// "적당한 날씨입니다."
중괄호 생략 (권장하지 않음)
// 한 줄일 때 중괄호 생략 가능하지만...
if (condition) doSomething();
// 중괄호 없으면 버그 발생 가능!
if (condition)
console.log("첫 번째");
console.log("두 번째"); // 조건과 무관하게 항상 실행!
// 항상 중괄호 사용 권장
if (condition) {
console.log("첫 번째");
}
console.log("두 번째"); // 명확하게 조건 밖
복합 조건
const age = 22;
const hasID = true;
// AND: 모두 참이어야
if (age >= 19 && hasID) {
console.log("입장 가능합니다.");
}
// OR: 하나만 참이어도
const isWeekend = true;
const isHoliday = false;
if (isWeekend || isHoliday) {
console.log("쉬는 날!");
}
// NOT: 부정
const isLoggedIn = false;
if (!isLoggedIn) {
console.log("로그인이 필요합니다.");
}
switch 문
여러 가지 경우를 비교할 때 if-else 체인보다 가독성이 좋습니다.
기본 구조
const day = "월요일";
switch (day) {
case "월요일":
case "화요일":
case "수요일":
case "목요일":
case "금요일":
console.log("평일입니다.");
break;
case "토요일":
case "일요일":
console.log("주말입니다!");
break;
default:
console.log("알 수 없는 요일");
}
fall-through 주의
const grade = "B";
let message;
switch (grade) {
case "A":
message = "최우수";
break; // break 없으면 다음 case로 계속!
case "B":
message = "우수";
break;
case "C":
message = "보통";
break;
default:
message = "기타";
}
// 의도적 fall-through 활용
const month = 2;
let days;
switch (month) {
case 2:
days = 28;
break;
case 4:
case 6:
case 9:
case 11:
days = 30;
break;
default:
days = 31;
}
return으로 switch 정리
function getDayType(day) {
switch (day) {
case "토요일":
case "일요일":
return "주말";
default:
return "평일";
}
}
console.log(getDayType("토요일")); // "주말"
console.log(getDayType("월요일")); // "평일"
삼항 연산자 (Ternary Operator)
간단한 조건 표현에 사용합니다.
// 기본 구조: 조건 ? 참일때 : 거짓일때
const age = 18;
const status = age >= 19 ? "성인" : "미성년자";
console.log(status); // "미성년자"
// 함수 반환값
function getDiscount(isMember) {
return isMember ? 0.2 : 0.05;
}
// 템플릿 리터럴에서
const score = 85;
const result = `점수: ${score} — ${score >= 60 ? "합격" : "불합격"}`;
console.log(result); // "점수: 85 — 합격"
// 중첩 삼항 (가독성 주의)
const grade = score >= 90 ? "A"
: score >= 80 ? "B"
: score >= 70 ? "C"
: "F";
단락 평가 패턴
논리 연산자를 이용한 조건부 실행 패턴입니다.
// && 패턴: 조건이 true일 때만 실행
const isAdmin = true;
isAdmin && console.log("관리자 메뉴 표시");
// 조건부 객체 프로퍼티 추가
const includeAdmin = true;
const menuItems = [
"홈",
"프로필",
includeAdmin && "관리자", // false면 이 항목 제외 (하지만 false가 배열에 들어감!)
].filter(Boolean); // false/null/undefined 제거
// || 패턴: 기본값
const userName = "" || "익명 사용자";
const port = process.env.PORT || 3000;
// ?? 패턴: null/undefined일 때만 기본값
const config = userConfig ?? defaultConfig;
const timeout = options.timeout ?? 5000;
조기 반환 (Early Return) 패턴
중첩을 줄이고 코드를 평탄화하는 핵심 패턴입니다.
// 나쁜 예: 과도한 중첩
function processUser(user) {
if (user) {
if (user.isActive) {
if (user.hasPermission) {
// 실제 처리 코드
return doProcess(user);
} else {
return "권한 없음";
}
} else {
return "비활성 사용자";
}
} else {
return "사용자 없음";
}
}
// 좋은 예: 조기 반환으로 평탄화
function processUser(user) {
if (!user) return "사용자 없음";
if (!user.isActive) return "비활성 사용자";
if (!user.hasPermission) return "권한 없음";
// 실제 처리 코드 (주요 로직이 명확하게 보임)
return doProcess(user);
}
가드 패턴
함수 입력 유효성 검사에 사용합니다.
function divide(a, b) {
// 가드: 잘못된 입력을 먼저 처리
if (typeof a !== "number" || typeof b !== "number") {
throw new TypeError("숫자만 입력하세요");
}
if (b === 0) {
throw new Error("0으로 나눌 수 없습니다");
}
return a / b;
}
// 실전: API 핸들러
async function getUserById(req, res) {
const { id } = req.params;
if (!id) return res.status(400).json({ error: "ID가 필요합니다" });
const user = await db.findUser(id);
if (!user) return res.status(404).json({ error: "사용자를 찾을 수 없습니다" });
if (!user.isActive) return res.status(403).json({ error: "비활성 계정" });
res.json(user);
}
switch vs if-else 선택 기준
// switch가 적합한 경우: 단일 변수의 다양한 값 비교
function getStatusText(statusCode) {
switch (statusCode) {
case 200: return "OK";
case 201: return "Created";
case 400: return "Bad Request";
case 401: return "Unauthorized";
case 404: return "Not Found";
case 500: return "Internal Server Error";
default: return "Unknown";
}
}
// if-else가 적합한 경우: 범위 비교, 복잡한 조건
function categorize(score) {
if (score >= 90) return "A";
if (score >= 80) return "B";
if (score >= 70) return "C";
if (score >= 60) return "D";
return "F";
}
// 객체 매핑이 더 나을 때도 있음 (switch 대체)
const statusMessages = {
200: "OK",
404: "Not Found",
500: "Server Error",
};
const message = statusMessages[code] ?? "Unknown";
고수 팁
조건 단순화: 복잡한 조건을 변수로
// 나쁜 예: 조건이 길고 의미 파악 어려움
if (user.age >= 19 && user.isActive && !user.isBanned && user.subscription === "premium") {
showPremiumContent();
}
// 좋은 예: 의도를 이름으로 표현
const isAdult = user.age >= 19;
const isEligible = user.isActive && !user.isBanned;
const isPremium = user.subscription === "premium";
if (isAdult && isEligible && isPremium) {
showPremiumContent();
}
전략 패턴으로 조건문 대체
// 많은 조건이 있을 때 전략 패턴이 깔끔
const discountStrategies = {
vip: (price) => price * 0.7,
member: (price) => price * 0.9,
student: (price) => price * 0.8,
guest: (price) => price,
};
function calculatePrice(price, userType) {
const strategy = discountStrategies[userType] ?? discountStrategies.guest;
return strategy(price);
}
console.log(calculatePrice(10000, "vip")); // 7000
console.log(calculatePrice(10000, "student")); // 8000
console.log(calculatePrice(10000, "unknown")); // 10000