목차
고유 식별자(ID)
고유 문자열은 숫자와 문자가 포함된 문자 값을 말한다. 포함된 문자열 길이가 길어서 두 번 생성하는 것이 거의 불가능한 고유한 값이다.
const uniqueId1 = '577ac755d7fef11100753579'
const uniqueId2 = '5b4ef18839cd6500114e04d2'
고유 식별자를 생성하려면 다음과 같은 코드를 사용할 수 있다. 전달된 length 인수 값에 따라 문자 개수를 설정하고, 고유한 문자값을 반환한다.
function generateUniqueString(length) {
return Math.random().toString(36).substring(2, 2 + length)
}
- Math.random() 메서드: 0에서 1 사이 소수점 뒤 16자리의 난수(random number)를 생성한다.
- .toString() 메서드: 진법(radix) 인수를 전달받아서 해당 진수의 문자열을 반환한다. 위 함수는 최대치인 36진수(0~9, a~z)로 변환한다.
- .substring() 메서드: 문자열의 일부를 선택할 수 있다. 첫 번째 인수로 전달한 인덱스 값부터 두 번째 인수로 전달한 값의 이전 인덱스까지 글자를 선택한다. 위 함수에서 첫 번째 인수가 2인 이유는 문자열의 ’0.’을 제외한 나머지 글자를 선택하기 위해서다.
목록의 항목을 식별하거나 동적으로 추가하고 삭제할 때 중복 걱정 없이 관리할 수 있다. 하지만 고유 식별자는 일반적으로 서버에서 생성되기 때문에 필요할 때 가져와서 사용할 수 있다.
타임아웃(Timeout)
setTimeout() 함수는 특정 작업을 일정 시간 이후에 수행하고 싶을 때 사용할 수 있는 함수다.
setTimeout(callback, wait)
- callback: 지연 후 실행할 함수(콜백 함수)
- wait: 콜백 함수를 실행하기 전 대기 시간(밀리초 단위)
setTimeout() 함수의 콜백에 더 많은 인수를 전달할 때는 wait 인수 뒤에 추가한다.
function callTheAvengers(...superHeroes) {
superHeroes.forEach((hero) => {
console.log(`${hero} 도착!`)
})
}
setTimeout(callTheAvengers, 1000, '아이언맨', '헐크', '토르')
// 위 코드와 아래 코드는 동일하게 작동
setTimeout(() => {
callTheAvengers('아이언맨', '헐크', '토르')
}, 1000)
setTimeout() 함수가 실행되면 특정 시간 뒤 코드 실행을 중단할 수 있는 아이디(ID)를 반환한다. clearTimeout() 함수에 타임아웃 식별자 값을 전달해 코드 실행을 취소할 수 있다.
// 타임아웃 설정
const timeoutId = setTimeout(() => {
console.log('setTimeout 콜백 실행')
}, 1000)
// 타임아웃 취소
clearTimeout(timeoutId)
setTimeout()에 전달한 콜백의 실행 시점은 정확한 시간을 보장하지는 않는다. 이벤트 루프와 콜스택 상태에 따라 지연될 수 있기 때문이다.
인터벌(Interval)
setTimeout() 함수가 특정 시간 뒤에 코드를 한 번 실행한다면, setInterval() 함수는 특정 시간 마다 코드를 반복해 실행한다.
setInterval(callback, intervalTime)
- callback: 지연 후 실행할 함수(콜백 함수)
- intervalTime: 콜백 함수를 실행하기 전 대기 시간(밀리초 단위)
setInterval() 함수의 콜백에 더 많은 인수를 전달할 때는 intervalTime 인수 뒤에 추가한다.
let count = 0
function callTheAvengers(...superHeroes) {
console.log(`${superHeroes[count]} 도착!`)
count = count + 1
}
setInterval(callTheAvengers, 1000, '아이언맨', '헐크', '토르')
// 위 코드와 아래 코드는 동일하게 작동
setInterval(() => {
callTheAvengers('아이언맨', '헐크', '토르')
}, 1000)
setInterval()에 등록된 콜백은 사용자가 페이지를 떠나거나, 새로고침하기 전까지는 영원히 반복 실행된다. 여기에서 clearInterval() 함수를 사용하면 취소할 수 있다. setTimeout() 함수처럼 setInterval() 함수도 실행되면 식별자(ID)를 반환한다. 반환된 식별자를 사용해 인터벌을 중단할 수 있다.
let count = 0
function callTheAvengers(...superHeroes) {
const hero = superHeroes[count]
if (!hero) {
console.info('%c인터벌 중단!', 'color: #787878')
return clearInterval(intervalId)
}
console.log(`${hero} 도착!`)
count += 1
}
const intervalId = setInterval(callTheAvengers, 1000, '아이언맨', '헐크', '토르')
setInterval() 역시 전달한 콜백의 실행 시점이 정확한 시간을 보장하지 않는다.
비동기 자바스크립트 - AJAX
AJAX(에이젝스)는 Asynchronous JavaScript and XML(비동기 JavaScript 및 XML)의 약자로, 웹 페이지를 새로고침하지 않고도 서버와 데이터를 주고받을 수 있게 해주는 기술이다. 이를 통해 더 나은 사용자 경험을 제공할 수 있다. 이름에 XML이 들어있지만, 여러 다양한 데이터 포멧을 주고 받을 수 있다. 이제는 XML보다 JavaScript와 호환성이 좋고, 더 간결한 구문을 제공하는 JSON 포맷을 더 많이 사용한다.
AJAX의 주요 특징은 다음과 같다.
- 비동기 통신: 페이지 새로고침 없이 서버와 데이터 교환
- 백그라운드 처리: 사용자가 페이지를 계속 사용하는 동안 데이터 처리
- 부분 업데이트: 전체 페이지가 아닌 필요한 부분만 업데이트
서버에서 데이터를 받으려면 먼저 서버로 무언가 보내야 한다.
- 요청(Request): 서버에 보내는 데이터
- 응답(Response): 서버가 보내는 데이터
이처럼 요청을 보내고, 받는 작동 과정을 페치(fetch)라고 부른다.
서버에 AJAX 방식으로 요청을 보내려면 먼저 XMLHttpRequest 객체를 생성해야 한다. 서버에서 응답이 언제 오는 지 알고 싶다면 이 객체의 load 이벤트를 수신해야 하고, open()으로 이어서 요청을 구성할 수 있다. 그리고 마지막으로 구성된 요청을 서버에 보내야 한다.
// 1. XHR 객체 생성
const request = new XMLHttpRequest()
// 2. 응답 이벤트 리스너 설정
request.addEventListener('load', (e) => {
// 응답 처리
const data = JSON.parse(e.target.response);
console.log(data)
})
// 3. 요청 구성
request.open('GET', 'https://api.github.com/users/yamoo9/repos')
// 4. 요청 전송
request.send()
open()으로 받는 인수는 다음과 같다.
- method: 서버에 요청을 보내는 방법 지정
- link: 요청을 받는 서버의 URL(요청된 정보는 리소스(resources)라고도 한다.)
서버는 클라이언트 측의 요청을 수락하거나 거부할 수 있다. 이런 정책을 CORS라고 부른다. 서버가 클라이언트 측의 요청을 수락하지 않으면 오류가 발생한다. "No 'Access-Control-Allow-Origin' header is present"
무분별한 요청은 API를 다운시킬 수 있다. 그래서 API 요청을 제한하기도 한다. 한도를 초과해서 요청하면 403(Forbidden) 오류가 발생한다.
비동기 자바스크립트 - JSON
오늘날 브라우저와 서버 사이에서 정보를 전달하는 주요 포맷으로 XML이 아닌 JSON을 사용한다. JSON(JavaScript Object Notation)은 브라우저와 서버 간 데이터 교환에 가장 널리 사용되는 포맷이다. JavaScript 객체와 유사하지만 몇 가지 중요한 차이점이 있다.
JavaScript 객체 | JSON |
키에 따옴표 선택적 | 키에 큰따옴표(") 필수 |
다양한 데이터 타입 지원 | 문자열 형태로만 존재 |
메서드 포함 가능 | 데이터만 포함 가능 |
JavaScript와 JSON은 다음의 방법을 사용해 서로 변환할 수 있다.
- JavaScript → JSON: JSON.stringify() - 객체를 JSON 문자열로 변환. space 매개변수를 사용하면 문자열 간격을 조정할 수 있다.
- JSON → JavaScript: JSON.parse() - JSON 문자열을 객체로 변환
// JavaScript to JSON
JSON.stringify(macbookPro, null, 2) // '\t' 문자값도 사용 가능
// JSON to JavaScript
const parsedObject = JSON.parse(jsonString)
// 원래 객체와 동일한 구조의 JavaScript 객체로 복원
XMLHttpRequest 객체의 응답(Response)은 JSON 포맷이다. 이 JSON 포맷은 문자열로 되어있다. JavaScript에서 응답받은 데이터를 사용하려면 객체로 해석해야 하는 데 이 과정을 파싱(Parsing)한다고 한다.
너무 많은 정보는 처리에 부담이되므로 필요한 정보만 남기고 줄이는 작업이 필요하다. 이런 과정을 데이터 정리(Massaging the data)라고 부른다. 데이터를 정리하려면 어떤 데이터가 필요한지 알아야 한다.
오늘 하루를 돌아보며
오늘부터 JavaScript에서 아주 중요한 개념을 배우기 시작했다. 강사님이 비동기 자바스크립트에 대해 몇 번 언급은 하셨지만, 본격적으로 배우기 시작하지 너무 어려웠다. 이해가 잘 안 되니까 집중도 잘 안 됐다. 주말에 다시 살펴봐야겠다.
그래도 오전에 배운 고유 식별자를 만드는 부분은 재밌었다. 짧게 지나가긴 했지만, 고유 문자열을 만들 수 있다는 게 신기했다. 난수를 생성해서 36진수로 변환하다니! 어쩌면 비밀번호를 추천하는 기능도 이런 기술을 사용하는 걸 수도 있겠다. 대신 특수문자도 들어가야 하니까 36진수가 아니라 그 이상이려나?