[JS Study #01] JS, 처음부터 다시 보는 이유 있는 기본
자바스크립트(JS)
자바스크립트(JavaScript)는 웹에서 동적인 동작을 구현하기 위한 대표적인 프로그래밍 언어입니다. HTML과 CSS로 만들어진 웹페이지에 생명력을 불어넣는 역할을 하죠.
이 글은 JS의 기초를 정리하면서 개념을 다지고, 프론트엔드 개발 관점에서 자주 쓰이는 문법을 정리하기 위한 목적입니다.
🔤변수 선언
변수(Variable)는 값을 저장해두는 이름 붙은 저장소입니다. 필요할 때 꺼내 쓰거나 바꿀 수 있어요.
let 이름 = '홍길동';
const 나이 = 30;
var 직업 = '개발자';
let
: 변경 가능한 변수 선언 (블록 스코프)const
: 변경 불가능한 상수 선언 (블록 스코프)var
: 예전 방식으로 함수 스코프를 가짐.호이스팅
문제로 지양됨
📌 프론트엔드 관점:
- 컴포넌트 상태나 DOM 제어 변수 →
let
- 설정값, 불변 데이터 →
const
var
는 사용하지 않는 것이 좋음
🧬 데이터 타입
데이터 타입(Data Type)은 값이 어떤 종류인지 나타내는 분류입니다.
▶️ 기본형 (Primitive Type)
string
: 문자열number
: 숫자boolean
: 참/거짓null
: 명시적으로 “없음”undefined
: 값이 할당되지 않음
▶️ 참조형 (Reference Type)
object
: 객체 (여러 속성을 가짐)array
: 배열 (값들의 순서 있는 집합)function
: 함수 (실행 가능한 코드 블록)
const 이름 = "임시언"; // string
const 나이 = 28; // number
const 개발자 = true; // boolean
const 취미 = {"코딩", "산책"}; // array
const 정보 = {이름 : "시언", 나이: 28}; //object
그렇다면 이 타입을 왜 나눠놨을까?
➡️ 다양한 종류의 데이터를 효율적이고 정확하게 처리하기 위해서
📌 프론트엔드 관점:
- API 응답 → 객체 또는 배열 형태가 많음
- 타입을 정확히 이해해야 렌더링 오류 방지 가능
- TypeScript와 연계 시 강력한 타입 체크 가능
👑 조건문
조건문은 특정 조건에 따라 실행할 코드를 분기합니다. 참/거짓에 따라 실행 코드를 다르게 만들 수 있어서 자주 사용합니다.
const 나이 = 29;
if (나이 >= 20) {
console.log("성인")
}else {
console.log("미성년자")
}
📌 프론트엔드 관점:
- 로그인 여부, 권한, 상태값에 따라 UI를 다르게 구성할 때 자주 사용됩니다.
✅ 삼항 연상자
삼항 연산자는 리액트에서 어떤 컴포넌트를 생성했을 때, props
로 설정해둔 값을 받아 다른 결과를 보일 때 제일 자주 사용했던 기억이 납니다.
그렇다면 삼항 연산자란 무엇일까요?
삼항연산자(termary operator)는 세 개의 피연산자를 사용하는 조건 연산자로, 조건에 따라 값을 선택할 때 짧고 간결하게 조건문을 표현할 수 있는 문법입니다.
// 기본형
조건 ? 참일 때 값 : 거짓일 때 값
const 상태 = (나이 >= 20) ? "성인" : "미성년자";
console.log(상태);
>>> 성인
삼항 연산자는 간단한 조건 분기에는 유용하지만, 복잡한 조건에서 중첩되면 가독성이 떨어집니다.
사용을 지양합니다!
📌 프론트엔드 관점:
- 컴포넌트 조건부 렌더링 (
{조건 ? A : B}
) - 버튼 상태, 색상 등 UI 조건 분기에 자주 쓰임
🔍헷깔릴 수 있는 문법 : 널 병합 연산자
오늘 TestScript를 작성하면서 헷깔려 잘못 설명한 개념이 있어서 이 기회에 다시 정의하려고 합니다.
바로 ??
를 사용하는 널 병합 연산자(Null Coalescing Operator)입니다.
JavaScript
에서 ??
기호로 쓰이며, null
, 또는 undefined
인 경우에만 대체값을 제공하는 연산자 입니다.
➡️ 피연산자가 null
또는 undefined
일 경우에만 오른쪽 값을 반환
값1 ?? 값2
값1이 null
또는 undefined
라면 값2를 반환합니다.
값1이 그외의 값(0
, false
, ""
…)이라면 값1을 반환합니다.
//예시
let name;
let hiName = name ?? "이름없음";
console.log(hiName);
>>> 이름없음
name
이 undefined
니까 이름없음
이 출력됩니다.
✅ 사용자 입력에서 0
, false
, ""
같은 것을 유효한 값으로 인정해야할때 사용합니다. 오직 null
과 undefined
를 찾아 관리하기 위한 용도로 용이합니다.
✅ ||
와 차이점은?
||
는 falsy한 값을 전부 판단합니다.
const nickname = "" || "익명"
console.log(nickname)
>>> 익명
const nickname = "" ?? "익명"
console.log(nickname)
>> ""
""
는 ||
에선 falsy이기 때문에 "익명"
으로 넘어가지만,
??
에서는 null
또는 undefined
가 아니므로 ""
그대로 사용됩니다.
-
falsy한 값의 예
false
,0
,""
,null
,undefined
,NaN
등
🔁반복문
같은 코드를 여러 번 실행하고 싶을 때 사용합니다.
👉 for문
for (let i = 0; i < 3; i++) {
console.log(i); // 0, 1, 2 출력
}
i
라는 초기값을 설정하고 중간에는 범위 그리고 마지막에는 어떻게(?) 저 범위까지 갈 것인지를 설정하여 for문을 사용합니다.
👉 while문
let i = 0;
while (i < 3) {
console.log(i);
i++;
}
**👉 forEach(배열 반목문)**
const 색상 = ["빨강", "파랑", "노랑"];
색상.forEach((색) => {
console.log(`색상: ${색}`);
});
널 병합 연산자 (??
)
값1 ?? 값2
값1
이null
또는undefined
일 때만값2
반환0
,false
,""
는 유효한 값으로 인정
let name;
let displayName = name ?? "이름 없음"; // "이름 없음"
📌 프론트엔드 관점:
- 사용자 입력값이 비어있을 때 기본값 설정
- 옵션값에만 fallback 값을 줄 때 유용
🔄 ||
와 비교
||
는 falsy한 값 전부 판단 (0
,false
,""
,null
,undefined
,NaN
등)
"" || "기본" // "기본"
"" ?? "기본" // ""
🔁 반복문
같은 동작을 여러 번 반복할 때 사용하는 문법입니다.
▶️ for문
for (let i = 0; i < 3; i++) {
console.log(i); // 0, 1, 2
}
▶️ while문
let i = 0;
while (i < 3) {
console.log(i);
i++;
}
▶️ forEach (배열 반복)
const 색상 = ["빨강", "파랑", "노랑"];
색상.forEach((색) => {
console.log(`색상: ${색}`);
});
📌 프론트엔드 관점:
- 리스트 렌더링 (
.map()
과 함께) - 배열 기반 데이터 순회 처리에 필수
🔧 함수 선언과 호출
함수(Function)는 반복적으로 사용되는 로직을 하나로 묶어두는 코드 덩어리입니다.
function 인사(이름) {
return `안녕하세요, ${이름}님!`;
}
console.log(인사("시언")); // 안녕하세요, 시언님!
📌 프론트엔드 관점:
- 이벤트 핸들러, API 호출, 상태 변경 처리 등에서 자주 사용
📦 배열과 객체 다루기
배열과 객체는 둘 다 값을 여러 개 저장할 수 있는 자료구조입니다. 그러나 이 둘의 차이점은 아래 표를 보고 알 수 있습니다.
✅ 핵심 차이점 요약
구분 | 배열 (Array) | 객체 (Object) |
---|---|---|
구조 | 순서 있는 값들의 집합 | 키-값 쌍의 집합 |
접근 방식 | 인덱스(숫자) 기반 | 키(문자열 또는 심볼) 기반 |
사용 목적 | 목록, 리스트 형태의 데이터 | 속성, 설정값 등 구조화된 데이터 |
대표 사용 예시 | 댓글 목록, 상품 리스트 | 사용자 정보, 설정값, API 응답 |
자바스크립트에서 배열도 객체의 일종입니다. 하지만 내장 함수와 자료 구조 목적이 다르기 때문에 구분해서 사용합니다.
상황 | 배열 사용 | 객체 사용 |
---|---|---|
댓글, 상품, 유저 리스트 | ✅ | ❌ |
한 명 유저의 정보 (이름, 나이, 이메일) | ❌ | ✅ |
JSON API 응답 처리 | 둘 다 혼합됨 → 보통 배열 안에 객체들 |
실무에서 배열 안에 객체 구조를 자주 사용하는데, 어쩔때 쓰는 걸까??
➡️ 동일한 구조를 가진 여러 데이터를 표현할 때 사용하는 방식
const user = [
{id : 1, name : "길동", age: 29},
{ id: 2, name: "지민", age: 31 },
{ id: 3, name: "윤서", age: 27 },
];
console.log(user[0].name);
>>> 길동
여기서 user
는 사용자 정보를 담은 객체들이 들어있는 배열이고 각각의 객체는 한 사람에 대한 정보입니다.
❓왜 이렇게 사용하는 것 일까?
배열 형태이니 순서대로 반복이 가능하며 객체니까 각 항목에 이름(key)를 붙여 의미있는 데이터를 담을 수 있습니다.
▶️ 배열 접근
const 색상 = ["빨강", "초록", "파랑"];
console.log(색상[1]); // "초록"
▶️ 객체 접근
const 사람 = { 이름: "시언", 나이: 29 };
console.log(사람.이름); // "시언"
📌 프론트엔드 관점:
-
리스트 렌더링, API 응답 처리, 컴포넌트 Props 관리 등 핵심 요소
-
리스트 렌더링
{users.map(user => ( <div key={user.id}> <p>{user.name}</p> <p>{user.age}</p> </div> ))}
-
API 응답 처리
{ "status": "success", "data":[ {"id": 1, "title": "제목", "author": "홍길동"}, {"id": 2, "title": "제목", "author": "박길동"}, {"id": 3, "title": "제목", "author": "최길동"}, ] }
-
🎯 이벤트 처리 (DOM)
이벤트(Event)는 유저의 행동에 반응하여 발생하는 동작입니다.
const 버튼 = document.querySelector("button");
버튼.addEventListener("click", () => {
alert("버튼 클릭됨!");
});
📌 프론트엔드 관점:
- 사용자 입력 처리 (클릭, 키 입력 등) → 리액트에선
onClick
,onChange
등으로 사용
⏱️ 비동기 처리 (Promise / async-await)
JS는 기본적으로 동기적으로 동작하지만, 네트워크 요청처럼 시간이 걸리는 작업은 비동기로 처리합니다.
▶️ Promise 예시
fetch("https://api.example.com")
.then(res => res.json())
.then(data => console.log(data));
▶️ async-await 예시
async function getData() {
const res = await fetch("https://api.example.com");
const data = await res.json();
console.log(data);
}
📌 프론트엔드 관점:
- API 통신, 사용자 인증, 로딩 처리 등에 필수
👑 배열 고차함수 (Array Higher0Order Functions)
배열을 가공하거나 변형할 때 자주 사용되는 함수 입니다.
JS에서 배열의 각 요소를 순회하거나, 조건에 맞게 걸러내고, 새로운 배열을 만들 때 유용합니다.
✅ 고차함수란?
함수를 인자로 받거나, 함수를 반환하는 함수를 말합니다.
➡️ 배열 고차함수는 배열에 대해 어떤 동작(함수)을 반복 적용하는 것입니다.
🔑 자주 쓰는 배열 고차함수
함수 | 설명 | 반환값 |
---|---|---|
forEach() |
반복만 함 | 없음 (undefined ) |
map() |
배열 변형 | 새로운 배열 |
filter() |
조건에 맞는 요소만 추출 | 새로운 배열 |
find() |
조건을 만족하는 첫 번째 요소 반환 | 요소 1개 or undefined |
some() |
하나라도 조건을 만족하면 true | Boolean |
every() |
모두가 조건을 만족해야 true | Boolean |
reduce() |
누적 계산 (합계, 평균 등) | 어떤 값이든 가능 |
▶️ forEach()
- 단순 반복
const 색상 = ["빨강", "파랑", "노랑"];
색상.forEach((색, i) => {
console.log(`${i}번 색상은 ${색}`)
})
단순 출력이나 DOM 조작 등에 사용합니다.
📌 반환값이 없음
▶️ map()
- 배열 변형
const 숫자 = [1, 2, 3];
const 제곱 = 숫자.map(n => n * n);
console.log(제곱); // [1, 4, 9]
📌 새로운 배열 반환
리스트 렌더링 시에 많이 사용합니다.
▶️ filter()
- 조건에 맞는 요소만 추출
const 숫자 = [1, 2, 3, 4, 5];
const 짝수 = 숫자.filter(n => n % 2 === 0);
console.log(짝수); // [2, 4]
조건을 만족하는 모든 요소를 뽑아낸 배열입니다.
📌 프론트엔드 관점:
- 리스트 렌더링, 조건 필터링, 데이터 가공 시 필수 활용
▶️ find()
- 조건에 맞는 첫 요소
const 사람들 = [
{id: 1, name: "길동"},
{id: 2, name: "흥부"}
];
const 찾은사람 = 사람들.find(p => p.id === 2);
console.log(찾은사람); // {id : 2, name: "흥부"}
▶️ some()
/ every()
const 나이들 = [19, 20, 23];
console.log(나이들.some(age => age < 20)); //true
console.log(나이들.every(age => age >= 18)); // true
some
: 하나라도 true면 trueevery
: 모두가 true여야 true
▶️ reduce()
- 누적 계산
const 점수 = [80, 90, 100];
const 합계 = 점수.reduce((acc, cur) => acc + cur, 0);
console.log(합계); //270
📌acc
: 누적값, cur
: 현재값
합계, 곱, 평균, 객체 그룹화 등에 사용
.map()
→ 리스트 렌더링.filter()
→ 검색/조건 필터.reduce()
→ 장바구니 총합 계산.find()
→ 특정 요소 찾기 (예: 유저 ID).some()
→ 체크박스 중 하나라도 선택됐는지 확인
🧩 구조 분해 할당 / 객체 단축 표기법
▶️ 구조 분해 할당 (Destructuring Assignment)
객체나 배열에서 원하는 값을 꺼내는 문법입니다.
코드의 간결성과 가독성 향상에 유리합니다.
const 사람 = { 이름: "시언", 나이: 29 };
const { 이름, 나이 } = 사람;
console.log(이름); // "시언"
-
사람.이름
,사람.나이
를 따로 접근하지 않아도 변수로 바로 꺼냅니다. -
변수명은 객체 키 이름과 일치해야합니다.
function Profile({name, age}) { return <div>{name} - {age}</div>; }
▶️ 배열 구조 분해
const 색상 = ["빨강", "노랑"];
const [첫번째, 두번째] = 색상;
-
순서 기준으로 값을 꺼냅니다.
-
객체처럼 이름 기반이 아니라 인덱스 기준입니다.
const [, onlySecond] = ["a", "b", "c"]; console.log(onlySecond); >> "b"
중첩 구조 분해 할당
const user = {
name: "언",
address: {city: "서울", zip: "12345"}
};
const {
address: {city}
} = user;
console.log(city);
>> "서울"
##### 객체 구조 이해
user
객체
{
name: "언",
address:{
city: "서울",
zip:"12345"
}
}
그래서 user.address.city
로 서울
에 접근할 수 있다.
이 user
객체에서 city
값만 꺼내고 싶을때 구조 분해를 사용하면 더 간결하게 쓸 수 있습니다.
구조분해 문법
const {
address: {city}
} = user;
user
라는 객체 안에 address
라는 키가 있고, 그 값도 객체입니다.
그 address
객체 안에 있는 city
값을 꺼내서 변수 city
로 선언하는 겁니다.
📌 주소를 꺼내는 것이 아니라 주소 안의 city만 꺼내서 const city
가 되는 것입니다.
중첩된 구조가 정확히 존재해야해서 user.address.city
가 없으면 에러가 발생할 수 있습니다.
선택적 체이닝을 같이 쓰면 더 안전!
const city = user?.address?.city;
▶️ 객체 단축 표기법
변수명을 키로 사용할 때 키와 값이 같으면 생략가능합니다.
const 이름 = "시언";
const 나이 = 29;
const 사람 = { 이름, 나이 }; // { 이름: "시언", 나이: 29 }
{이름: 이름, 나이: 나이}
를 줄여쓴 상태로 import
하고 객체를 구성할 때 특히 유용합니다.
📌 프론트엔드 관점:
- 컴포넌트 Props 처리, API 데이터 가공 시 매우 자주 사용됨
댓글남기기