JavaScript에서는 세 가지 방식으로 변수를 선언할 수 있습니다.
var name = 'John';
var name = 'Jane'; // 재선언 가능 (문제가 될 수 있음)
let age = 25;
age = 26; // 재할당 가능
// let age = 30; // 재선언 불가 (에러 발생)
const PI = 3.14159;
// PI = 3.14; // 재할당 불가 (에러 발생)
// 객체와 배열의 경우 내용은 수정 가능
const user = { name: 'John' };
user.name = 'Jane'; // 가능
user.age = 30; // 가능
기존 함수 표현식을 더 간결하게 작성할 수 있습니다.
// 기존 함수 표현식
const add = function(a, b) {
return a + b;
};
// 화살표 함수
const add = (a, b) => {
return a + b;
};
// 한 줄일 경우 중괄호와 return 생략 가능
const add = (a, b) => a + b;
// 매개변수가 하나일 경우 괄호 생략 가능
const double = x => x * 2;
// 매개변수가 없을 경우
const greet = () => console.log('Hello!');
// 이벤트 핸들러
<button onClick={() => console.log('Clicked!')}>
Click me
</button>
// 컴포넌트 정의
const Button = () => {
return <button>Click me</button>;
};
// 더 간결하게
const Button = () => <button>Click me</button>;
모듈을 불러오고 내보내는 방법입니다.
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
// main.js
import { add, subtract } from './math.js';
// Button.js
const Button = () => <button>Click me</button>;
export default Button;
// App.js
import Button from './Button';
// utils.js
export const formatDate = (date) => { /* ... */ };
export const formatTime = (time) => { /* ... */ };
const utils = { /* ... */ };
export default utils;
// main.js
import utils, { formatDate, formatTime } from './utils';
const user = {
name: 'John',
age: 30,
email: 'john@example.com'
};
// 접근
console.log(user.name); // John
console.log(user['age']); // 30
// 수정
user.age = 31;
user['email'] = 'newemail@example.com';
// 추가
user.city = 'Seoul';
const { name, age } = user;
console.log(name); // John
// 별칭 지정
const { name: userName, age: userAge } = user;
// 기본값 설정
const { city = 'Unknown' } = user;
// 객체 복사
const newUser = { ...user };
// 객체 병합
const updatedUser = { ...user, age: 32, city: 'Busan' };
// 일부 속성 제외
const { age, ...userWithoutAge } = user;
const fruits = ['apple', 'banana', 'orange'];
console.log(fruits[0]); // apple
console.log(fruits.length); // 3
// push: 끝에 추가
fruits.push('grape');
// pop: 끝에서 제거
const lastFruit = fruits.pop();
// map: 변환된 새 배열 생성
const upperFruits = fruits.map(fruit => fruit.toUpperCase());
// filter: 조건에 맞는 요소만 선택
const longFruits = fruits.filter(fruit => fruit.length > 5);
// find: 조건에 맞는 첫 번째 요소
const foundFruit = fruits.find(fruit => fruit.startsWith('b'));
// reduce: 누적 계산
const total = [1, 2, 3, 4].reduce((sum, num) => sum + num, 0);
// 배열 복사
const newFruits = [...fruits];
// 배열 병합
const moreFruits = [...fruits, 'mango', 'kiwi'];
const allFruits = [...fruits, ...moreFruits];
// 배열 구조 분해
const [first, second, ...rest] = fruits;
조건에 따라 다른 값을 반환하는 간단한 조건문입니다.
// 기본 문법: 조건 ? 참일때값 : 거짓일때값
const age = 20;
const status = age >= 18 ? '성인' : '미성년자';
// React에서의 활용
const Component = () => {
const isLoggedIn = true;
return (
<div>
{isLoggedIn ? <WelcomeMessage /> : <LoginButton />}
</div>
);
};
// 중첩 사용 (가독성 주의)
const grade = score >= 90 ? 'A' :
score >= 80 ? 'B' :
score >= 70 ? 'C' : 'F';
Falsy 개념자바스크립트에서 falsy는 조건식에서 false로 평가되는 값들을 의미합니다. 조건문(if, while 등)이나 논리 연산에서 false처럼 동작하는 값들로, 아래 6가지로 고정되어 있습니다:
false0 (숫자 0)"" (빈 문자열)nullundefinedNaN특징
falsy 값은 조건문에서 false로 간주되지만, === (엄격한 동등 비교)로는 false와 동일하지 않습니다.
예: if (0) { ... } → 실행되지 않음, 하지만 0 === false는 false 반환.
falsy가 아닌 값은 truthy로 간주되어 조건문에서 true처럼 동작합니다.
예제
if (0) {
console.log("이건 실행 안 됨"); // falsy 값
} else {
console.log("0은 falsy"); // 실행됨
}
if ("hello") {
console.log("이건 실행됨"); // truthy 값
}
falsy값은 6개로 한정되어 있으니 암기하세요.
각falsy값을 조건문에 넣어 동작을 확인해보세요.
!!연산자(이중 부정)를 사용하면 값이truthy인지falsy인지 빠르게 확인 가능:
!!0 → false
!!"hello"→true
조건이 참일 때만 렌더링합니다.
// 기본 원리: 앞이 true면 뒤를 반환, false면 false 반환
const result1 = true && 'Hello'; // 'Hello'
const result2 = false && 'Hello'; // false
// React에서의 활용
const Component = () => {
const showMessage = true;
const items = ['item1', 'item2'];
return (
<div>
{showMessage && <p>메시지를 표시합니다</p>}
{items.length > 0 && <p>아이템이 있습니다</p>}
</div>
);
};
// 주의사항: 0은 falsy지만 렌더링됨
const count = 0;
return <div>{count && <p>카운트: {count}</p>}</div>; // 0이 렌더링됨
// 해결방법
return <div>{count > 0 && <p>카운트: {count}</p>}</div>;
기본값을 제공할 때 사용합니다.
// 기본 원리: 앞이 falsy면 뒤를 반환
const name = userName || 'Guest';
// React에서의 활용
const Component = ({ title }) => {
return <h1>{title || '기본 제목'}</h1>;
};
React에서 배열 데이터를 화면에 표시할 때 가장 많이 사용하는 패턴입니다.
const TodoList = () => {
const todos = [
{ id: 1, text: 'React 공부하기' },
{ id: 2, text: 'JavaScript 복습하기' },
{ id: 3, text: '프로젝트 만들기' }
];
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
};
const UserList = () => {
const users = [
{ id: 1, name: 'John', isActive: true },
{ id: 2, name: 'Jane', isActive: false },
{ id: 3, name: 'Bob', isActive: true }
];
return (
<div>
<h2>활성 사용자</h2>
<ul>
{users
.filter(user => user.isActive)
.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
const ProductList = () => {
const products = [
{ id: 1, name: '노트북', price: 1500000, inStock: true },
{ id: 2, name: '마우스', price: 30000, inStock: false },
{ id: 3, name: '키보드', price: 100000, inStock: true }
];
return (
<div className="product-list">
{products.map(product => (
<div key={product.id} className="product-card">
<h3>{product.name}</h3>
<p>가격: {product.price.toLocaleString()}원</p>
{product.inStock ? (
<button>구매하기</button>
) : (
<p style={{ color: 'red' }}>품절</p>
)}
</div>
))}
</div>
);
};
// 잘못된 예: index를 key로 사용
{items.map((item, index) => (
<li key={index}>{item}</li> // 순서가 바뀔 수 있는 경우 문제 발생
))}
// 올바른 예: 고유한 id 사용
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
import { useState } from 'react';
// TodoItem 컴포넌트
const TodoItem = ({ todo, onToggle, onDelete }) => {
return (
<li style={{
display: 'flex',
alignItems: 'center',
padding: '10px',
borderBottom: '1px solid #eee',
textDecoration: todo.completed ? 'line-through' : 'none',
color: todo.completed ? '#999' : '#333'
}}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => onToggle(todo.id)}
style={{ marginRight: '10px' }}
/>
<span style={{ flex: 1 }}>{todo.text}</span>
<button
onClick={() => onDelete(todo.id)}
style={{
padding: '5px 10px',
backgroundColor: '#ff4444',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
삭제
</button>
</li>
);
};
// App 컴포넌트
const App = () => {
// 상태 관리 - const 사용
const [todos, setTodos] = useState([
{ id: 1, text: 'React 공부하기', completed: false },
{ id: 2, text: 'JavaScript 복습하기', completed: true },
{ id: 3, text: '프로젝트 만들기', completed: false }
]);
const [inputValue, setInputValue] = useState('');
// 할 일 추가 - 화살표 함수 사용
const addTodo = () => {
if (inputValue.trim() === '') return;
const newTodo = {
id: Date.now(),
text: inputValue,
completed: false
};
// 스프레드 연산자로 배열 복사 및 추가
setTodos([...todos, newTodo]);
setInputValue('');
};
// 할 일 완료 토글
const toggleTodo = (id) => {
// map을 사용한 배열 조작
setTodos(todos.map(todo =>
todo.id === id
? { ...todo, completed: !todo.completed } // 스프레드 연산자로 객체 복사
: todo
));
};
// 할 일 삭제
const deleteTodo = (id) => {
// filter를 사용한 배열 조작
setTodos(todos.filter(todo => todo.id !== id));
};
// Enter 키 입력 처리
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
addTodo();
}
};
// 완료된 할 일 개수 계산
const completedCount = todos.filter(todo => todo.completed).length;
return (
<div style={{
maxWidth: '600px',
margin: '50px auto',
padding: '20px',
backgroundColor: '#f5f5f5',
borderRadius: '8px',
boxShadow: '0 2px 10px rgba(0,0,0,0.1)'
}}>
<h1 style={{ textAlign: 'center', color: '#333' }}>📝 Todo List</h1>
{/* 입력 영역 */}
<div style={{ display: 'flex', marginBottom: '20px' }}>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="할 일을 입력하세요..."
style={{
flex: 1,
padding: '10px',
fontSize: '16px',
border: '1px solid #ddd',
borderRadius: '4px 0 0 4px'
}}
/>
<button
onClick={addTodo}
style={{
padding: '10px 20px',
backgroundColor: '#4CAF50',
color: 'white',
border: 'none',
borderRadius: '0 4px 4px 0',
cursor: 'pointer',
fontSize: '16px'
}}
>
추가
</button>
</div>
{/* 통계 - 조건부 렌더링 && 사용 */}
{todos.length > 0 && (
<div style={{
marginBottom: '10px',
textAlign: 'center',
color: '#666'
}}>
완료: {completedCount} / 전체: {todos.length}
</div>
)}
{/* Todo 리스트 - map을 사용한 리스트 렌더링 */}
<ul style={{
listStyle: 'none',
padding: 0,
backgroundColor: 'white',
borderRadius: '4px'
}}>
{todos.length === 0 ? (
<li style={{
textAlign: 'center',
padding: '20px',
color: '#999'
}}>
할 일이 없습니다. 새로운 할 일을 추가해주세요!
</li>
) : (
todos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
onToggle={toggleTodo}
onDelete={deleteTodo}
/>
))
)}
</ul>
{/* 전체 삭제 버튼 - 조건부 렌더링 */}
{todos.length > 0 && completedCount === todos.length && (
<button
onClick={() => setTodos([])}
style={{
width: '100%',
marginTop: '20px',
padding: '10px',
backgroundColor: '#ff9800',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '16px'
}}
>
모두 삭제
</button>
)}
</div>
);
};
export default App;