And Brain said,
JavaScript, 시작은 미약하였으나 그 끝은 창대하리라 본문
목차
1. 객체, 프로토타입, 클래스와 상속
2. 고차 함수와 배열 메소드
3. 비동기 프로그래밍과 Promise, async/await
4. 서버사이드 자바스크립트(Node.js, Express)
5. 모듈과 패키지 관리
6. 에러 처리와 디버깅
7. 자바스크립트 디자인 패턴
8. 함수형 프로그래밍
9. 자바스크립트 웹 API(Axios, WebSockets)
10. 웹 스토리지(localStorage, sessionStorage)
11. 프론트엔드 프레임워크 소개(React, Vue, Angular)
12.웹 성능 최적화
13. Progressive Web Apps(PWA) 소개
JavaScript는 그닥 잘 설계된 언어도 아니었으며, Java의 유명세에 묻어가려고 이름부터 JavaScript로 짓는 등, 아주 비루하게 시작한 언어지만, 엄청난 확장성을 바탕으로 현재 가장 영향력 있는 프로그래밍 언어이며 아직까지도 무궁무진하게 성장 중인 언어이다.
오늘은 이 무한한 확장성의 언어 JavaScript와 간단한 웹 개발 기법에 대해 알아보도록 하자.
1. 객체, 프로토타입, 클래스와 상속
자바스크립트에서 객체는 키(key)와 값(value)의 쌍을 저장하는 컨테이너로, 객체를 생성하는 가장 간단한 방법은 중괄호({})를 사용하는 리터럴 표기법이다.
const person = {
name: 'Sanghyun Kim',
age: 26,
greet: function() {
console.log('Hello, my name is ' + this.name);
}
};
console.log(person.name); // Sanghyun Kim
person.greet(); // Hello, my name is Sanghyun Kim
프로토타입은 객체지향 언어에서 상속을 지원하는 메커니즘 중 하나로, 자바스크립트에서 모든 객체는 다른 객체를 프로토타입으로 가질 수 있다.
이 프로토타입 객체에는 메소드와 속성이 포함되어 있어, 해당 프로토타입을 상속하는 객체도 이들을 사용할 수 있다.
const animal = {
speak: function() {
console.log(`${this.name} makes a noise.`);
}
};
const cat = Object.create(animal);
cat.name = 'Horang2';
cat.speak(); // Horang2 makes a noise.
ES6에서는 class 키워드를 사용해 클래스를 정의할 수 있다.
클래스를 사용하면 객체지향 프로그래밍이 더 쉬워지고, 상속을 포함한 다양한 기능을 쉽게 구현할 수 있게 된다.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Cat extends Animal {
speak() {
console.log(`${this.name} meow.`);
}
}
const cat = new Dog('Horang2');
cat.speak(); // Horang2 meow.
2. 고차 함수와 배열 메소드
고차 함수는 다른 함수를 인수로 받거나, 함수를 결과로 반환하는 함수로, 자바스크립트에서 함수는 일급 객체(first-class objects)로 취급되므로, 변수에 할당하거나 다른 함수에 전달할 수 있다.
function greet() {
console.log('이리오너라!');
}
function callFunction(fn) {
fn();
}
callFunction(greet); // 이리오너라!
자바스크립트 배열에는 고차 함수를 사용하는 메소드가 많이 있는데, 이를 통해 배열을 쉽게 처리하고 변환할 수 있다.
// map은 배열의 각 요소에 함수를 적용하고 결과를 새 배열로 반환한다.
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter는 배열의 요소 중 조건으 ㄹ만족하는 요소만 새 배열로 반환한다.
const evenNumbers = numbers.filter((number) => number % 2 === 0);
console.log(evenNumbers); // [2, 4]
// reduce 배열의 요소를 순차적으로 처리하면서 누적 값을 반환한다.
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 15
// forEach는 배열의 각 요소에 대해 함수를 실행하고 반환 값은 없다.
numbers.forEach((number) => console.log(number)); // 1, 2, 3, 4, 5
이러한 고차 함수와 배열 메소드를 사용하면 코드를 더 간결하고 이해하기 쉽게 작성할 수 있다.
3. 비동기 프로그래밍과 Promise, async/await
자바스크립트는 싱글 스레드로 동작하기 때문에, 시간이 오래 걸리는 작업을 처리하면 실행이 차단되어 웹 페이지가 멈춰 보일 수 있는데, 이를 해결하기 위해 비동기 프로그래밍이 사용된다.
비동기 프로그래밍을 사용하면, 시간이 오래 걸리는 작업을 백그라운드에서 처리하고 완료되면 결과를 반환할 수 있다.
Promise는 비동기 작업의 최종 완료(또는 실패)를 나타내는 객체로, Promise는 세 가지 상태를 가지는데: 대기(pending), 이행(fulfilled), 거부(rejected)이다.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise resolved!');
}, 1000);
});
promise.then((result) => {
console.log(result); // 'Promise resolved!'
});
async/await는 자바스크립트의 비동기 프로그래밍을 더 간결하고 가독성 좋게 작성할 수 있는 문법으로, async 키워드는 함수에 적용되며, 해당 함수는 항상 Promise를 반환하고, await 키워드는 Promise가 이행될 때까지 기다린 후 결과를 반환한다.
await는 반드시 async 함수 내에서만 사용할 수 있다.
async function fetchData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
}
fetchData();
비동기 프로그래밍과 Promise, async/await를 사용하면, 자바스크립트에서 시간이 오래 걸리는 작업을 효과적으로 처리할 수 있다.
이를 통해 웹 애플리케이션의 성능과 사용자 경험을 향상시킬 수 있다.
4. 서버사이드 자바스크립트(Node.js, Express)
Node.js는 자바스크립트를 서버 사이드에서 실행할 수 있게 해주는 런타임 환경입으로, 이를 통해 웹 서버, API 서버, 데스크톱 애플리케이션 등 다양한 분야에서 자바스크립트를 활용할 수 있게 되었다.
Node.js의 주요 특징으로는 이벤트 드리븐 아키텍처를 통해 비동기 I/O 처리로 높은 성능과 확장성을 제공한다.
npm이라는 강력한 패키지 관리 시스템으로 다양한 라이브러리와 모듈을 손쉽게 사용할 수 있다.
하지만 Node.js의 가장 큰 장점으로는 JavaScrip를 사용한다는 그 자체인데, 프론트엔드와 백엔드 모두 자바스크립트를 사용하여 개발할 수 있어 언어를 따로 배울 필요가 없다는 점이다.
Express.js는 Node.js를 위한 가장 인기 있는 웹 프레임워크로, 간결한 API를 제공하며, 미들웨어를 통한 확장성과 다양한 템플릿 엔진을 지원한다.
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Express야, 이리오너라!');
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Node.js와 Express.js를 활용하면, 서버 사이드 자바스크립트로 빠르게 웹 애플리케이션을 개발할 수 있는데, 이를 통해 효율적인 웹 서비스를 제공할 수 있으며, 실시간 통신 및 스트리밍 등 다양한 분야에서 활용할 수 있다.
5. 모듈과 패키지 관리
자바스크립트에서는 다양한 모듈 시스템이 존재하는데, 이를 통해 코드를 재사용하고, 의존성을 관리할 수 있다.
CommonJS (CJS)는 Node.js에서 사용되는 모듈 시스템으로, require() 함수와 module.exports 객체를 사용하여 모듈을 불러오거나 내보낸다.
AMD (Asynchronous Module Definition): 비동기적인 모듈 로딩을 지원하는 모듈 시스템으로, 주로 브라우저에서 사용되며, RequireJS와 같은 라이브러리를 사용하여 구현할 수 있다.
UMD (Universal Module Definition)는 AMD와 CommonJS를 모두 지원하는 모듈 시스템으로, 브라우저와 Node.js 환경 모두에서 사용할 수 있는 모듈을 작성할 수 있다.
ES Modules (ESM)은 ECMAScript 표준 모듈 시스템으로, 현재 대부분의 자바스크립트 환경에서 지원되며, import와 export 키워드를 사용하여 모듈을 불러오거나 내보냅니다.
웹에서 사용되는 자바스크립트는 이런 모듈을 처리하기 위해 번들러를 사용하는데, 이는 모듈을 하나의 파일로 묶어주고, 최적화 작업을 수행한다.
가장 인기 있는 자바스크립트 번들러는 Webpack으로, 플러그인을 통해 다양한 최적화와 변환 작업을 수행할 수 있다.
자바스크립트에서는 패키지 관리자를 사용하여 다양한 라이브러리와 모듈을 관리하는데, 패키지 관리자는 소프트웨어의 의존성을 효과적으로 관리하고, 프로젝트에 필요한 모듈을 쉽게 설치할 수 있도록 도와준다.
npm은 Node.js의 기본 패키지 관리자로, 가장 많은 패키지를 가지고 있다.
package.json 파일을 통해 의존성을 관리하며, npm install 명령어를 사용해 패키지를 설치하고, 또한, npm ci 명령어를 사용하면 빠르고 안정적인 의존성 설치 할 수 있다.
yarn은 페이스북에서 개발한 패키지 관리자로, npm과 호환된다.
빠른 속도와 오프라인 캐시 기능을 제공하며, 작업 공간(Workspaces) 기능으로 모노레포(Monorepo) 구조를 지원한다.
또한, 패키지 버전 관리와 업데이트를 효율적으로 수행하기 위해 npm-check-updates, yarn upgrade-interactive와 같은 도구들을 사용할 수 있어, 이를 통해 프로젝트의 안정성과 유지보수성을 높일 수 있다.
6. 에러 처리
try-catch-finally문을 통해 예외가 발생할 수 있는 코드를 try 블록에 넣고, catch 블록에서 예외를 처리하며, finally에서 예외 발생 여부와 관계없이 실행되는 코드를 작성할 수 있다.
try {
// 예외가 발생할 수 있는 코드
} catch (error) {
// 예외 처리 코드
console.error(error);
} finally {
// 항상 실행되는 코드
}
또한, 자바스크립트에서는 사용자 정의 에러를 만들어 에러 처리를 더 세밀하게 할 수 있는데, 사용자 정의 에러를 만들려면, Error 클래스를 상속받아 새로운 클래스를 정의하고, 생성자에서 super() 메소드를 호출해야 한다.
이렇게 하면 에러 메시지 및 스택 트레이스 등의 기능을 사용할 수 있다.
class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
}
}
try {
throw new CustomError("This is a custom error");
} catch (error) {
if (error instanceof CustomError) {
console.log(`${error.name}: ${error.message}`); // "CustomError: This is a custom error"
} else {
console.log("Unknown error:", error);
}
}
CustomError 클래스는 사용자 정의 에러를 나타내며, Error 클래스의 모든 기능을 상속받는다.
이렇게 정의된 사용자 정의 에러는 표준 에러와 마찬가지로 throw 문과 함께 사용할 수 있으며, catch 블록에서 처리할 수 있고 또한, instanceof를 사용해 에러의 타입을 확인할 수 있어, 에러 처리가 더 세밀하게 가능해진다.
7. 자바스크립트 디자인 패턴
디자인 패턴은 소프트웨어 개발에서 반복적으로 발생하는 문제를 해결하는 재사용 가능한 솔루션으로, 자바스크립트에서도 다양한 디자인 패턴을 사용하여 코드의 효율성과 유지 보수성을 높일 수 있다.
여기서는 대표적인 패턴들인 모듈 패턴(Module Pattern), 싱글턴 패턴(Singleton Pattern), 팩토리 패턴(Factory Pattern)패턴 세 가지만 살펴보도록 하자.
먼저, 모듈 패턴은 캡슐화와 정보 은닉을 통해 코드의 구조를 개선하고, 전역 변수의 사용을 줄이는 데 도움이 됩니다.
const myModule = (function () {
let privateVar = "Private Variable";
function privateMethod() {
return privateVar;
}
return {
publicMethod: function () {
return privateMethod();
},
};
})();
console.log(myModule.publicMethod()); // "Private Variable"
다음으로, 싱글턴 패턴은 클래스의 인스턴스가 오직 하나만 존재하도록 보장하는 패턴으로, 이를 통해 애플리케이션 전체에서 공유되는 리소스를 관리할 수 있다.
class Singleton {
constructor() {
if (!Singleton.instance) {
Singleton.instance = this;
}
return Singleton.instance;
}
}
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2); // true
마지막으로, 팩토리 패턴은 객체를 생성하는 로직을 추상화하고, 인스턴스 생성을 간소화하는 데 사용된다.
class Animal {
constructor(name) {
this.name = name;
}
}
class AnimalFactory {
createAnimal(name) {
return new Animal(name);
}
}
const factory = new AnimalFactory();
const cat = factory.createAnimal("Cat");
const dog = factory.createAnimal("Dog");
이외에도 다양한 디자인 패턴이 있으니, 프로젝트의 요구 사항에 따라 적절한 디자인 패턴을 적용하여 코드의 품질을 향상시킬 수 있다.
8. 함수형 프로그래밍
함수형 프로그래밍(Functional Programming, FP)은 애플리케이션의 상태 관리를 최소화하고, 코드의 가독성과 예측 가능성을 높이는 데 중점을 둔 프로그래밍 패러다임으로, 자바스크립트는 기본적으로 함수형 언어다.
그렇기에 이번 섹션에서는 함수형 프로그래밍의 심화 기법들을 한 번 살펴보자.
먼저, 부분 적용(Partial Application)은 함수의 일부 인수를 고정하여 새로운 함수를 생성하는 기법으로, 이를 통해 재사용 가능한 함수를 쉽게 만들 수 있다.
Function.prototype.bind()를 사용해 부분 적용을 구현해보자.
// 일반 함수
function greeting(greeting, name) {
return `${greeting}, ${name}!`;
}
// 부분적용을 사용한 함수
function greetHello(name) {
return greeting('까꿍', name);
}
console.log(greetHello('Horang2')); // '까꿍, Horang2!'
다음으로, 렌즈(Lenses)는 객체의 속성에 안전하게 접근하거나 수정하는 함수형 프로그래밍 기법으로, getter와 setter 함수를 이용해 객체의 속성을 쉽게 다룰 수 있게 한다.
const get = (lens, obj) => lens.get(obj);
const set = (lens, value, obj) => lens.set(value, obj);
const makeLens = prop => ({
get: obj => obj[prop],
set: (value, obj) => ({ ...obj, [prop]: value }),
});
const nameLens = makeLens('name');
const person = { name: 'Sanghyun', age: 26 };
console.log(get(nameLens, person)); // 'Sanghyun'
const updatedPerson = set(nameLens, 'Horang', person);
console.log(updatedPerson); // { name: 'Horang', age: 1 }
이 예제에서 makeLens 함수는 속성에 대한 렌즈를 생성하고, get과 set 함수를 통해 객체의 속성을 읽거나 수정할 수 있게 된다.
다음 배워볼 것은 커링(Currying)으로, 커링은여러 개의 인자를 받는 함수를 인자 하나만 받는 함수들의 연쇄로 변환하는 기법으로, 이를 통해 부분적으로 인자를 적용한 새로운 함수를 만들고 코드의 재사용성을 높일 수 있다.
// 커링 예제
const multiply = (a, b) => a * b;
// 커링 함수를 정의합니다.
const curry = (fn) => {
const arity = fn.length; // 함수의 인자 개수를 가져옵니다.
const curried = (...args) => {
if (args.length >= arity) {
return fn(...args);
} else {
return (...rest) => curried(...args, ...rest);
}
};
return curried;
};
// multiply 함수를 커링합니다.
const curriedMultiply = curry(multiply);
// 부분적으로 인자를 적용한 새로운 함수를 생성합니다.
const multiplyByTwo = curriedMultiply(2);
console.log(multiplyByTwo(5)); // 10
console.log(multiplyByTwo(10)); // 20
이 예제에서 curry 함수는 다중 인자 함수를 인자 하나만 받는 함수들의 연쇄로 변환하는데, multiply 함수를 커링하여 curriedMultiply를 생성하고, 이를 사용해 multiplyByTwo 함수를 만든다.
값이 null이나 undefined인 경우 변환하지 않고 그대로 반환하여 안전하게 값 변환 작업을 수행할 수 있게 된다.
다음으로, 지연 평가(Lazy Evaluation)는 함수형 프로그래밍에서 계산을 연기하는 기법으로, 계산이 필요할 때까지 값을 평가하지 않고, 필요한 시점에 실제 계산을 수행하여, 이를 통해 불필요한 계산을 피하고 성능을 최적화할 수 있다.
자바스크립트의 제너레이터 함수를 사용하여 지연 평가를 구현해보자.
// 제너레이터 함수를 사용한 지연 평가 예제
function* range(start, end) {
let current = start;
while (current <= end) {
yield current;
current += 1;
}
}
// 제너레이터 함수를 사용하여 1부터 10까지의 값 생성
const numbers = range(1, 10);
// 제너레이터에서 값을 가져옴
console.log(numbers.next().value); // 1
console.log(numbers.next().value); // 2
// 필요한 시점에 다음 값을 가져올 수 있음
console.log(numbers.next().value); // 3
이 예제에서 range 제너레이터 함수는 start와 end 사이의 값을 생성한다.
numbers 제너레이터 객체를 사용하여 값을 순차적으로 가져올 수 있으며, 필요한 시점에 값을 평가할 수 있다.
마지막으로, 모나드(Monad)는 연속된 계산을 순차적으로 수행할 수 있게 해주는 객체로 특정 값을 감싸고, 값에 대한 변환 작업을 수행할 수 있는 메서드를 제공한다.
// Maybe 모나드 생성자
function Maybe(value) {
this.value = value;
}
// Maybe 모나드의 map 메서드
// 함수 f를 받아서, 현재 감싸고 있는 값을 변환하고 새로운 Maybe 모나드를 반환합니다.
Maybe.prototype.map = function (f) {
// 값이 null이나 undefined인 경우, 변환하지 않고 그대로 Maybe 모나드를 반환합니다.
if (this.value === null || this.value === undefined) {
return new Maybe(this.value);
}
// 값이 존재하는 경우, 함수 f를 적용하여 새로운 Maybe 모나드를 반환합니다.
return new Maybe(f(this.value));
};
const addOne = (x) => x + 1;
const maybeValue = new Maybe(5);
const maybeResult = maybeValue.map(addOne);
console.log(maybeResult.value); // 6
const maybeNull = new Maybe(null);
const maybeNullResult = maybeNull.map(addOne);
console.log(maybeNullResult.value); // null
이 예제에서 Maybe 모나드는 value를 감싸고 있으며, map 메서드를 사용하여 값을 변환할 수 있다.
9. 자바스크립트 웹 API(Axios, WebSockets)
웹 API는 웹 애플리케이션에서 서버와 통신하기 위한 다양한 방법을 제공하는데, 여기에서는 Axios, WebSockets 두 가지만 알아보도록 하자.
Ajax와 Fetch API를 사용할 수도 있지만, 최근 들어서 자주 사용하지는 않는 추세이다.
Ajax, Fetch, Axios는 모두 HTTP 요청을 처리하는 데 사용되는 기술이며, 서로 다른 인터페이스와 기능을 제공하며, 이 세 기술은 주로 요청-응답 패턴을 사용하며, 웹 서버와 클라이언트 간에 일반적인 데이터 교환을 수행하는 데 사용된다.
Axios는 Fetch API와 유사한 기능을 제공하지만, 더 많은 기능과 구성 옵션을 포함하며 취소 기능, 요청 및 응답 인터셉터 등의 기능을 제공한다.
import axios from "axios";
axios
.get("https://api.example.com/data")
.then((response) => console.log(response.data))
.catch((error) => console.error("Axios error:", error));
반면에 WebSockets은 조금 다른 목적을 가진 기술인데, 웹 서버와 클라이언트 간의 양방향 통신을 위한 프로토콜로서, 실시간 애플리케이션 구현에 주로 사용된다.
WebSocket은 연결이 한 번 맺어지면, 클라이언트와 서버가 지속적으로 데이터를 주고받을 수 있는 통신 채널을 유지하는 특성 때문에 실시간 채팅 애플리케이션, 게임, 실시간 알림 등에 적합한 기술이다.
const socket = new WebSocket("wss://example.com/socket");
socket.onopen = () => {
console.log("WebSocket connection opened");
socket.send("Hello, server!");
};
socket.onmessage = (event) => {
console.log("Message from server:", event.data);
};
socket.onclose = () => {
console.log("WebSocket connection closed");
};
10. 웹 스토리지(localStorage, sessionStorage)
웹 스토리지는 웹 브라우저에 데이터를 저장할 수 있는 클라이언트 사이드 기술인데, 주로 사용자 설정, 로그인 정보, 캐싱 데이터 등을 저장하는데 사용된다.
웹 스토리지에는 크게 두 가지 유형이 있는데, localStorage와 sessionStorage가 그 예이다.
localStorage는 브라우저가 닫히거나 컴퓨터가 재시작되더라도 데이터가 영구적으로 저장되어 특정 기간동안 유지되어야 하는 정보를 저장하는데 적합하다.
// 데이터 저장
localStorage.setItem('key', 'value');
// 데이터 읽기
const data = localStorage.getItem('key');
// 데이터 삭제
localStorage.removeItem('key');
// 모든 데이터 삭제
localStorage.clear();
sessionStorage는 데이터가 현재 세션 동안만 저장되며, 브라우저를 닫으면 데이터가 삭제되어 일시적인 정보를 저장하는데 적합하다.
// 데이터 저장
sessionStorage.setItem('key', 'value');
// 데이터 읽기
const data = sessionStorage.getItem('key');
// 데이터 삭제
sessionStorage.removeItem('key');
// 모든 데이터 삭제
sessionStorage.clear();
웹 스토리지는 간단한 키-값 쌍의 데이터를 저장할 수 있으며, 보안적인 부분에서 유의해야 하니, 중요한 정보나 민감한 데이터는 암호화하거나 서버에 저장하는 것이 좋다.
11. 프론트엔드 프레임워크 소개(React, Vue, Angular)
프론트엔드 프레임워크는 웹 애플리케이션 개발을 보다 쉽고 빠르게 할 수 있도록 도와주는 도구로, 주요 프론트엔드 프레임워크는 React, Vue, Angular가 있으며, 각각의 특징과 장점이 존재한다.
먼저, React는 페이스북에서 개발한 오픈소스 라이브러리로, 선언적인 방식으로 사용자 인터페이스를 구축할 수 있고, 가상 DOM을 사용하여 성능을 최적화하며, 다양한 플랫폼(웹, 모바일)에서 사용할 수 있다.
https://theworldaswillandidea.tistory.com/139
다음으로,Vue는 Evan You가 개발한 오픈소스 프레임워크로, 가볍고 빠르며 유연한 구조를 가지고 있고, React와 유사한 방식으로 사용자 인터페이스를 구축할 수 있으며, 간결한 문법과 직관적인 API를 제공한다.
이 블로그에 Vue에 관한 글도 여럿 있으니 참고해보시길 바란다.
마지막으로, Angular는 구글에서 개발한 오픈소스 프레임워크로, TypeScript 기반으로 작성되어 있다.
Angular는 꽉찬 육각형 프론트 프레임워크로 정말 다양한 기능과 함께 대규모 애플리케이션 개발에 적합한 구조를 갖추고 있다.
12. 웹 성능 최적화
이 장에서는 웹 성능 최적화 전략들에 대해 다양하고 간단하게 짚고 넘어가보자.
웹 애플리케이션의 성능을 최적화하는 것은 사용자 경험(UX) 향상과 웹 사이트의 전반적인 효율성에 큰 영향을 준다.
웹 성능 최적화를 통해 페이지 로딩 속도를 줄이고, 반응성을 향상시킬 수 있는데, 다음은 웹 성능 최적화의 주요 전략들이다.
12.1 리소스 최적화
이미지 최적화: 압축, 적절한 해상도, 웹용 이미지 포맷 사용
CSS와 JavaScript 최소화(minification) 및 병합(concatenation)
코드 스플리팅(code splitting)을 통한 초기 로딩 시간 감소
12.2 캐싱 전략
브라우저 캐싱 활용: 캐시 헤더 설정을 통해 변경되지 않은 리소스를 재요청하지 않도록 함
CDN(Content Delivery Network) 사용: 전 세계에 분산된 서버를 통해 리소스를 빠르게 전달
12.3 렌더링 최적화
Critical Rendering Path 최적화: 초기 렌더링에 필요한 리소스만 우선적으로 로드
Lazy Loading 적용: 필요한 시점에 리소스를 로드하여 초기 로딩 시간 감소
JavaScript 실행 최적화: requestAnimationFrame, Web Workers 등을 사용하여 비동기 처리
12.4 네트워크 최적화
HTTP/2 프로토콜 사용: 다양한 최적화 기능 제공 (스트림 병렬화, 헤더 압축 등)
서버와 클라이언트 간 지연 시간 최소화: 적절한 서버 위치, DNS 프리페치 등
웹 성능 최적화는 지속적인 프로세스로, 개발 단계부터 고려되어야 한다.
웹 애플리케이션의 성능을 모니터링하고 지속적으로 개선해 나가는 것은 중요한 일인데, 성능 최적화를 위한 도구로는 Lighthouse, PageSpeed Insights, WebPageTest 등이 있으니, 이러한 도구들을 활용하여 웹 애플리케이션의 성능을 분석하고 개선해보도록 하자.
13. Progressive Web Apps(PWA) 소개
Progressive Web Apps (PWA)는 웹과 네이티브 앱의 장점을 결합한 현대적인 웹 애플리케이션이다.
Progressive Web Apps (PWA)는 웹 애플리케이션을 네이티브 앱과 유사한 사용자 경험을 제공하도록 개선한 기술로,
서비스 워커를 사용하여 앱의 리소스를 캐싱할 수 있는데, 이를 통해 오프라인에서도 웹 앱이 작동하게 만들 수 있다.
또한, 매니페스트를 사용하여 사용자가 웹 앱을 홈 화면에 설치할 수 있게 만들 수 있어, 사용자가 웹 앱을 네이티브 앱처럼 사용할 수 있게 된다.
추가적으로 PWA는 웹 앱에 푸시 알림 기능을 추가할 수 있게 해주는데, 이를 통해 사용자의 참여도를 높이고 앱과의 상호 작용을 증가시킬 수 있다.
또, 캐싱 및 코드 스플리팅과 같은 성능 최적화 기법을 사용하여 빠른 로딩 시간을 제공할 수도 있어. 이를 통해 사용자 경험을 향상시킬 수 있다.
하지만, 이런 PWA 또한 단점은 존재하는데, PWA 기능 중 일부는 아직 모든 브라우저에서 완벽하게 지원되지 않는다.
그리고, PWA는 웹 기술에 기반을 두고 있기 때문에, 네이티브 앱에서 사용할 수 있는 일부 기능에 대한 접근이 제한될 수 있다.
PWA를 개발하고 유지 관리하려면 다양한 웹 기술과 개념을 이해하고 적용해야되서 개발 및 유지 관리의 복잡성을 증가시킬 수 있다.
총론적으로, PWA는 웹 앱의 사용자 경험을 향상시키고 네이티브 앱과 유사한 기능을 제공하기 때문에 많은 경우에 유용한 선택이 될 수 있지만, 브라우저 지원, 네이티브 기능 제한 및 개발 복잡성과 같은 단점을 고려하여 프로젝트의 목표와 요구사항을 고려해 PWA를 사용할지 결정해야한다.
사용하기로 결정하였다면, 최근 프론트엔드 프레임워크들은 PWA 설정들을 포함하고 있는 추세이니, 각 공식 문서에서 확인하여 구현해보시길 바란다.
끝으로,
이렇게, JavaScript에 관한 개괄적인 글이 끝났습니다. 오늘 여러분들은 JavaScript의 다양한 측면을 이해하고 활용하는 방법을 배웠습니다. 이제, 이를 바탕으로 여러분들의 프로젝트에 적용해보시면서 JavaScript의 매력에 더 빠져보시길 바랍니다.
마지막으로, 여러분들의 성장을 위해서는 언제나 트렌드와 기술의 변화에 발맞춰서 새로운 것들을 배우는 것이 중요합니다. 오늘 배운 지식과 기술들을 익히시고 더 풍부하고 전문적인 기술들을 배워나가시길 바랍니다.
여기까지 JavaScript 였습니다. 이 글이 여러분들의 성장에 조금이나마 도움이 되길 바라며,
Thanks for watching, Have a nice day.
References
https://developer.mozilla.org/ko/docs/Web/JavaScript
https://ko.javascript.info
http://www.tcpschool.com/javascript/intro
'IT > Language & BackEnd' 카테고리의 다른 글
Generic, 프로그래밍 언어의 대명사(Pronouns) (0) | 2023.04.06 |
---|---|
SOLID, 5가지 객체지향의 원칙 (0) | 2023.03.18 |