1. 웹 개발의 역사
자바스크립트
- 1990년대 : 마이크로 소프트의 인터넷 익스플로러, 넷스케이프 커뮤니케이션즈의 넷스케이프 내비게이터 를 가장 많이 사용
- 1995년대 : 넷스케이프의 브랜든 아이크는 웹의 다양한 콘텐츠를 표현하기 위해 플러그인 요소를 쉽게 조합 할 수 있는 새로운 언어가 필요하다고 생각 => 자바스크립트의 탄생
- 익스플로러의 Jscript vs 넷스케이프의 Javasciprt : 둘다 사용자에게 유의미한 편의성은 제공하지 못함
자바스크립트의 표준, ECMAScript
- 경쟁관계이던 익스플로러와 넷스케이프는 자신들의 브라우저 기능을 빠르게 늘리기 시작
- 추가된 기능은 각자의 브라우저에서만 동작해, 웹페이지가 다르게 동작하거나 제대로 동작하지 않는 크로스 브라우징 이슈 발생
- 개발자들은 어떤 기능을 추가하기 위해서 두 개의 스크립트를 따로 개발해야 했음
사용자가 새로운 버전이 아닌 구 버전의 브라우저를 사용하거나, 브라우저가 지원하지 않는 코드도 실행시켜 줘야 함.
=> 폴리필(polyfill)과 트랜스파일(transpile) 등장
폴리필 : 브라우저가 지원하지 않는 코드를 브라우저에서 사용할 수 있도록 변환한 코드 조각이나 플러그인.
ex) core.js, polyfill.io
트랜스파일 : 최신 버전의 코드를 예전 버전의 코드로 변환하는 과정
ex) Babel
둘 다 최신 기능을 구버전의 실행환경에서 동작할 수 있게 바꿔주는 역할을 한다.
- 당시 브라우저 호환성 이슈 때문에, 제이쿼리같지 호환성을 고민하지 않고 한 번에 개발할 수 있는 라이브러리가 유행 함
- 언제까지 라이브러리에 기대어 해결할 수 없이니 근본적인 문제 해결을 위한 표준화 필요성이 제기
"모든 브라우저에서 동일하게 동작하는 표준화된 자바스크립트가 필요하다" - 넷스케이프는 컴퓨터 시스템의 표준을 관리하는 Ecma 인터내셔널(국제표준화기구)에 자바스크립트의 표준화를 위한 자바스크립트 기술 규격을 제출했고, EC-MAScript하는 이름으로 자바스크립트 표준화를 공식화했다.
웹사이트에서 웹 애플리케이션으로의 전환
웹 사이트 : 누구에게나 같은 정보를 보여주며 사용자와 상호작용하지 않음 (정적 사이트, 단방향으로 정보를 제공)
웹 애플리케이션 : 사용자가 직접 정보를 생산하고 공유할 수 있음 (동적 사이트, 쌍방향 소통)
개발 생태계의 발전
대규모 웹 어플리케이션이 등장하면서 개발 생태계도 이런 흐름에 맞춰 변화되었다.
- 웹페이지를 통으로 개발하는게 아닌, 컴포넌트 단위로 개발 (CBD, 컴포넌트 베이스 개발)
component based development(CBD)
서비스에서 다루는 데이터를 구분하고 그게 맞는 UI를 표현할 수 있게 컴포넌트 단위로 개발하는 접근 방식
재사용할 수 있는 컴포넌트를 개발 또는 조합해서 작은 컴포넌트에서 큰 컴포넌트를 만들어 나간다.
- Ajax로 전체를 새로고침하지 않아도 자바스크립트의 비동기 요청을 사용해서 페이지의 일부 데이터를 로드
- PC, Mobile, 테블릿 등 다양한 디스플레이가 등장하며 사용자의 디바이스에 최적화된 UX/UI 필요
개발자 협업의 필요성 증가
한달 전에 만든 함수를 쉽게 파악할 방법은 없을까? 다른 사람이 만든 함수를 쉽게 이해할 수 있을까? 개발에 투입된 인원이 10명이 넘어가면 어떨까? 인원이 많아질 수록 코드를 파악하기 어려워지는 것은 당연 지사다. 결과물이 커졌기 때문에 서비스를 개발하고 나서 유지보수를 하는 데 협업의 중요성도 높아졌다. 대규모 프로덕트를 개발하고 나서 자바스크립트는 유지보수하기 적합한 언어였을까?
2. 자바스크립트의 한계
동적 타입 언어의 문제
자바스크립트는 동적 타입의 언어다.
let a = ??
//변수 a의 타입이 number인지 string인지는 실제 코드가 동작할때 a의 1, "1"인지에 따라 결정된다.
let a = 1 //number
let a = "1" //string
변수의 타입을 명시적으로 지정하지 않고 코드가 실행되는 런타임에 변수값이 할당될 때 해당 값의 타입에 따라 변수 타입이 결정된다.
//a,b를 더한 값을 반환하는 함수
const sumNumber = (a, b) => {
return a + b;
};
sumNumber(1, 2); // 3
//정상적인 동작
sumNumber(1); // NaN
//b에 값을 넣어주지 않아 NaN이 출력되지만 에러를 발생시키지 않음
sumNumber("a", "b"); // "ab"
//a,b가 문자열이기 때문에 문자열로 합쳐져서 출력됨 => 의도와는 다르게 동작하지만 여전히 정상적으로 동작
sumNumber는 두 숫자의 값을 더하기 위해 만들어진 함수지만 인자를 하나를 넣어도, 문자열을 넣어도 오류 없이 정상적으로 동작한다.
즉 개발자의 의도와는 다르게 동작하는건데, 그런데도 자바스크립트는 이 코드를 문제 없이 실행한다. 동적타입의 언어는 상당히 관대하다.
자바스크립트의 관대함은 이뿐만이 아니다. 자바스크립트 엔진은 오류를 발생시키는 대신 형변환을 진행한다.
sumNumber(1); // NaN
const sumNumber = (a, b) => {
//a만 인자를 넣어준 경우, b는 undefined로 인식
//+undefined는 NaN으로 형변환한 다음 실행을 이어간다.
return a + b;
};
한계 극복을 위한 해결 방안
- JSDoc : 모듈, 클래스, 매서드 등에 대한 API 문서 생성 도구. 주석의 성경을 지니고 있어 강제성을 부여해 사용하긴 어려움
/**
* 두 숫자를 더합니다.
* @param {number} a - 첫 번째 숫자
* @param {number} b - 두 번째 숫자
* @returns {number} 두 숫자의 합
*/
function add(a, b) {
return a + b;
}
- propTypes : 리액트에서 컴포넌트 props 타입을 검사하기 위해 사용, props의 유효한 값이 전달되었는지 확인할 수 있지만 전체 애플리케이션의 타입 검사를 하는데는 사용할 수 없다. 또한 특정 라이브러리에서만 사용할 수 있다는 점에서 한계가 있다.
import React from 'react';
import PropTypes from 'prop-types';
/**
* 사용자 카드 컴포넌트
* @param {Object} props - 컴포넌트의 props
* @param {string} props.name - 사용자 이름
* @param {number} props.age - 사용자 나이
* @param {boolean} props.isMember - 회원 여부
*/
function UserCard({ name, age, isMember }) {
return (
<div>
<h1>{name}</h1>
<p>Age: {age}</p>
<p>{isMember ? 'Member' : 'Guest'}</p>
</div>
);
}
UserCard.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
isMember: PropTypes.bool
};
export default UserCard;
- Dart(다트) : 구글이 자바스크립트를 대체하기 위해 사용한 언어로 정적 타입 언어이다. 위의 방법들 보다 근본적인 해결책으로 보였으나 자바스크립트가 자리매김한 상황에서 다트의 등장을 달갑지 않게 보는 시선이 강했다.
void main() {
String name = 'John';
int age = 30;
bool isMember = true;
print('Name: $name');
print('Age: $age');
print('Is Member: $isMember');
}
3가지 모두 해결 방안이였으나, 자바스크립트가 스스로 인터페이스를 기술할 수 있는 언어로 발전해야 된다는 목소리가 커졌다.
3. 타입스크립트의 등장
마이크로 소프트는 자바스크립트의 슈퍼셋 언어인 타입스크립트를 공개했다. 다트와 달리 자바스크립트 코드를 그대로 사용할 수 있고 단점은 극복할 수 있었기 때문에 많은 환영을 받았다.
*슈퍼셋(superset) : 기존 언어에 새로운 기능과 문법을 추가해서 보완하거나 향상하는 것을 말함
안정성 보장
타입스크립트는 정적 타이핑을 제공한다. 컴파일 단계에서 타입 검사를 해주기 때문에 자바스크립트를 사용했을 때 빈번하게 발생하는 타입 에러를 줄일 수 있고, 런타임 에러를 사전에 방지할 수 있어 안정성이 높아졌다.
개발 생산성 향상
VScode 등의 IDE에서 타입 자동완성 기능을 제공한다. 변수와 함수 타입을 추론할 수 있고, 어떤 props를 넘겨야하는지 매번 확인하지 않아도 사용부에서 바로 볼 수 있어서 개발 생산성이 향상된다.
협업에 유리
개발자가 작성한 코드의 의도를 명확하게 전달할 수 있어 유지보수하기 쉬워진다.
타입스크립트의 인터페이스는 복잡한 코드도 쉽게 이해할 수 있게 돕는다. 인터페이스는 객체 구조를 정의하는 역할을 하며, 특정 객체가 가져야 하는 속성과 매서드의 집합을 인터페이스로 정의해서 객체가 그 구조를 따르게 한다.
interface User {
name: string;
age: number;
isMember: boolean;
}
function getUserInfo(user: User): string {
return `${user.name} is ${user.age} years old. Member status: ${user.isMember}`;
}
자바스크립트에 점진적으로 적용 가능
자바스크립트의 슈퍼셋이기 때문에 일괄 전환이 아닌 점진적 도입이 가능하다.
'기술 > TypeScript' 카테고리의 다른 글
[에러] typescript import 오류 : Could not find a declaration file for module 모듈에 대한 선언 파일을 찾을 수 없습니다. (0) | 2024.03.18 |
---|---|
Interface vs Type 타입을 지정하는 또 다른 방법 (0) | 2023.12.21 |
여러 타입을 만족하는 하나의 타입, 타입 합치기(Intersection Type, union/&) (1) | 2023.12.19 |
readonly 타입 설정, 불변성을 갖도록 만들기 (0) | 2023.12.19 |
타입 축약과 타입의 확정 (Type Aliases 별칭, Narrowing, Assertion) (1) | 2023.12.18 |