이번에 회사에서 Node.js로 개발한 모바일애플리케이션의 백엔드부분을 받게 되었다. 그런데 아예 할줄 몰라서 공부가 좀 필요하다 느끼고 공부를 해보겠다.
나는 여지껏 java로만 개발을 해와서 다른 언어가 어떤식으로 작동하고 어떤문법을 가지고 있는지 감이 없다. java는 객체 지향 언어로 굉장히 딱딱정해주고 딱딱 맞춰서 개발해야하는 느낌이지만 javascript는 그렇지않다고는 알고 있었다.
한번 알아보도록 하겠다.
기본 문법
ㅇ 변수 선언
let x = 10; //값 변경 가능
const y = 20; //값 변경 불가능
var z = 30; //예전 방식
java에선 int, char 등 이렇게 타입을 지정해야하지만, javascript에서는 동적 타입이라 자동으로 타입이 결정된다고 한다.
참 편리해보인다.
ㅇ 데이터 타입
let str = "Hello";
let num = 100;
let isTrue = true;
let arr = [1, 2, 3];
let obj = {name: "Ryan", age: 25};
let func = function() {return "Hello";};
보는것과 같이 그냥 let으로 퉁치는것같다. 이게 어떻게 되지? 위에서 봤듯이 let으로 하면 변수변경이 가능하고, const를 사용하면 불변변수를 선언할 수 있다.
ㅇ 함수
function add(a, b) {
return a + b;
}
const multiply = function(a, b) {
return a * b;
};
const divide = (a,b) => a / b;
아니 이게 뭐지? 너무 간단하다. 그리고 맨밑에 화살표 함수는 엄청나게 함수를 간결하게 표현할 수 있다고 한다.
그리고 함수를 변수에 저장할 수도 있다고 한다.
ㅇ 객체
const user = {
name: "Ryan",
age: 30,
greet: function() {
return `Hello, my name is ${this.name}`;
}
};
class 없이 바로 선언해주면 객체를 만들 수 있고, this는 여기서도 쓰이나보다 싶다.
javascript의 객체는 key-value 구조로 되어있다고 한다.
ㅇ 비동기 처리
console.log("1. Start");
// 3초 동안 실행되는 동기 함수
function delaySync() {
const start = Date.now();
while (Date.now() - start < 3000) {} // 3초 대기 (이 동안 다른 작업 불가능)
}
delaySync();
console.log("2. End");
javascript는 비동기 방식을 지원한다고 한다. 동기/비동기 방식에 대해서는 아주 예전에 다뤘던 포스팅이 있다.
https://thcoding.tistory.com/159
기본기 닦기(1) - 스레드, 동기/비동기, JVM
ㅇ 스레드(Thread) 자바는 일반적으로 멀티 스레드 환경에 적합한 언어로 알고있다. 그런데 여기서 의문? 스레드가 뭔가? 나는 그저 작업의 한 단위 정도라고 생각을 했다. 자세히 알아보았다. 먼
thcoding.tistory.com
위의 코드를 실행하게 되면 delaySync함수가 실행되는 동안 다른 작업을 안받아준다. 그래서 UI가 멈출 수도 있고, 다른 호출이 있을 때 서버응답이 지연될 수도 있다.
javascript의 기본적인 비동기를 보자.
console.log("1. Start");
setTimeout(() => {
console.log("2. Inside setTimeout");
}, 2000); // 2초 후 실행
console.log("3. End");
setTimeout이 실행된다고 해서 밑의 console.log("3. End"); 가 기다리지 않고, 바로 실행된다.
콘솔에 어떻게 출력될까.
1. Start
3. End
2. Inside setTimeout
이렇게 나오게 된다. (* 참고로 setTimeout은 JavaScript엔진에서 제공하지않고, Web API에서 제공한다.)
이번엔 콜백함수를 보자.
콜백함수란, 특정 작업이 끝난 후, 실행될 함수를 인자로 전달하는 방식이다.
function fetchData(callback) {
setTimeout(() => {
console.log("Data Fetched!");
callback("Fetched Data");
}, 2000);
}
console.log("1. Start");
fetchData((data) => {
console.log("2. Received:", data);
});
console.log("3. End");
이렇게 된 코드를 실행하면 어떻게 출력이 될까?
1. Start
3. End
Data Fetched! (2초 후 실행)
2. Received: Fetched Data
가장먼저 console.log("1. Start"); 라인이 실행되고, 그 밑의 fetchData 함수가 실행되는데 2초 뒤에 실행되기 때문에 바로 밑에 console.log("3. End"); 라인이 실행되고 그 다음 fetchData가 실행되면서 저렇게 나온다.
이제, Promise객체를 보자. Promise는 비동기 작업이 완료될때(성공 or 실패) 특정 동작을 수행하는 객체다.
(* 참고로 Promise는 javascript 엔진에서 지원한다.)
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Promise Resolved!");
// reject("Promise Rejected!");
}, 2000);
});
console.log("1. Start");
myPromise
.then(result => {
console.log("2. Success:", result);
})
.catch(error => {
console.log("3. Error:", error);
});
console.log("4. End");
myPromise라는 Promise객체를 초기화 해준다. 그리고 resolve()를 호출하게 되면 then으로 가게 된다. 고로 결과는,
1. Start
4. End
2. Success: Promise Resolved!
이렇게 나온다.
만약 reject를 호출했다면? catch를 호출하게 되어 아래와 같이 나올것이다.
1. Start
4. End
3. Error: Promise Rejected!
다음으로 async/ await을 보자.
얘네는 Promise 기반의 비동기 처리를 동기 코드처럼 쉽게 생성할 수 있도록 도와주는 문법이다.
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Data Loaded!");
}, 2000);
});
}
async function fetchDataAsync() {
console.log("1. Start");
let result = await fetchData(); // fetchData()가 끝날 때까지 기다림
console.log("2. Success:", result);
console.log("3. End");
}
fetchDataAsync();
async가 붙은 fetchDataAsync에서 1. Start가 출력되고 await fetchData 해서 fetchData()가 끝날 때까지 3.End 가 출력이 되지 않는다.
1. Start
(2초 후)
2. Success: Data Loaded!
3. End
이렇게 나온다.
function fetchData(isError) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (isError) {
reject("Error: Something went wrong!");
} else {
resolve("Data Loaded Successfully!");
}
}, 2000);
});
}
async function fetchDataAsync() {
try {
console.log("1. Fetching Data...");
let result = await fetchData(false); // true로 변경하면 에러 발생
console.log("2. Success:", result);
} catch (error) {
console.error("3. Catch Error:", error);
} finally {
console.log("4. Done!");
}
}
fetchDataAsync();
이렇게 하면 성공 시,
1. Fetching Data...
(2초 후)
2. Success: Data Loaded Successfully!
4. Done!
실패 시,
1. Fetching Data...
(2초 후)
3. Catch Error: Error: Something went wrong!
4. Done!
이런 결과를 얻을 수 있다.
ㅇ 모듈
java에서 패키지나 라이브러리의 클래스나 메서드를 가져와서 사용할 때 import 하는것 처럼, Node.js에서 javascript 코드를 여러 파일로 나누려면 어떻게 해야할까?
// math.js
export function add(a, b) {
return a + b;
}
math.js 파일에서 add라는 함수를 export 했다. 그걸 main.js에서 쓰려면,
// main.js
import { add } from './math.js';
console.log(add(2, 3)); // 5
이렇게 import 해서 사용하면 된다.
뭐 문법을 알아야할게 더 있겠지만 자세히 알 시간이 없다.
이정도만 알고 넘어가겠다.