😎디바운싱의 간단한 정리
"이벤트가 여러번 발생하면 가장 마지막으로 발생한 이벤트만 실행시키는 기법"
포탈사이트에서 검색어 입력시 keyup
이벤트가 있다고 생각해보습니다. 입력할때 마다 이벤트는 호출하지만 입력이 끝나고 마지막에 입력한 단어에 대한 관련 검색어 목록이 나옵니다. 만약 디바운싱 기법을 사용하지않으면 이벤트가 걸릴때마다 검색API를 호출하기때문에, 성능면에 있어서 문제가 될수 있습니다. 거기에 매일 호출가능 건수가 제한된다면, 이를 확장해야하하는 비용문제도 발생할 수 있습니다.
let keyupTimer=null;
const $input = document.querySelector('input');
$input.addEventListener('keyup',({target})=>{
clearTimeout(keyupTimer);
keyupTimer = setTimeout(()=>{
fetch(`domain.com?text=${target.value}`)
.then(response=>response.json())
.then(json=>{
//...
})
},1000);
})
처음에 keyupTimer
변수에 1초후에 실행되는 timer식별자를 담습니다. 이후, 입력 이벤트가 계속실행되면 clearTimeout
을 통해 keyupTimer는 스케쥴링이 계속 취소가 되고, 1초동안 입력이 없을경우 setTimeout안의 구현한 실행함수가 실행됩니다.
다른 수강생분의 과제에서는 keyup대신 input 이벤트를 많이 쓰더라고요. MDN문서에 정의되어있는 Input이벤트는 아래와 같이 설명합니다.
input
이벤트는 input,textarea,select의 value속성이 변경될때마다 발생하는 이벤트입니다.
기존의 keyup
이벤트는 문자열이 아닌 키를 눌렀을때도 발생 하기때문에, 문자열이 변경됐을때만 이벤트 처리를 하는게 좋겠다는 생각이 들었습니다.
기존 callback 방식은 여러번의 callback 호출이 필요할때는 아래와 같이 콜백 지옥을 양산합니다.
/*callback hell*/
A(function(result_a){
B(function(result_b){
C(function(result_c){
D(function(result_d){
......
}
}
}
})
기존의 콜백 지옥을 해결하기위해 promise
패턴이 사용됩니다.
new Promise를 호출할때 넘겨주는 콜백 함수 안에 비동기처리 코드를 작성합니다.
- 성공시 반환해줄 데이터를 담아
resolve
함수를 호출합니다. 이후then
으로 이동해 성공시 처리내용을 작성하면 됩니다.- 실패했을때는 실패했을때의 내용을 담아
reject
함수를 호출합니다. 이후catch
로 이동하여 실패했을때의 상태를 처리하면 됩니다.
function A(){
return new Promise((resolve,reject)=>{
const result_a = 'SuccessA!';
resolve(result_a);
})
}
function B(result_a){
return new Promise((resolve,reject)=>{
if(result_a === 'SuccessA!'){
resolve('SuccessB!')
}else{
reject('FailB!');
}
})
}
function C(result_b){
return new Promise((resolve,reject)=>{
if(result_b === 'SuccessB!'){
resolve('SuccessC!')
}else{
reject('FailC!');
}
})
}
function D(result_c){
return new Promise((resolve,reject)=>{
if(result_c === 'SuccessC!'){
resolve('Final Success!')
}else{
reject('Final Fail!');
}
})
}
A().then(result_a=>B(result_a))
.then(result_b =>C(result_b))
.then(result_c=> D(result_c))
.then(result_d=>{
if(result_d === 'Final Success!'){
alert('success')
}
})
.catch(e=>console.error(e));
promise
는 then() catch()
를 통한 체이닝 기법을 이용하여 콜백 처리를 조금더 편하게 할수 있습니다. 그리고 기존의 콜백 지옥보다는 가독성이 좋아지는 효과도 있습니다.
promise
패턴 다음으로 async~await
를 통해 비동기처리도 동기식 처리처럼 코드를 작성할수 있습니다.
😀async~await 사용 조건
function
키워드 앞에async
를 붙인다음,async
를 붙인 함수안에 비동기 promise객체를 변환하는 함수(ex.fetch, axios등) 앞에await
를 붙입니다.
function A(){
return new Promise((resolve,reject)=>{
const result_a = 'SuccessA!';
resolve(result_a);
})
}
function B(result_a){
return new Promise((resolve,reject)=>{
if(result_a === 'SuccessA!'){
resolve('SuccessB!')
}else{
reject('FailB!');
}
})
}
function C(result_b){
return new Promise((resolve,reject)=>{
if(result_b === 'SuccessB!'){
resolve('SuccessC!')
}else{
reject('FailC!');
}
})
}
function D(result_c){
return new Promise((resolve,reject)=>{
if(result_c === 'SuccessC!'){
resolve('Final Success!')
}else{
reject('Final Fail!');
}
})
}
async function runAsync(){
try{
const result_a = await A();
const result_b = await B(result_a);
const result_c = await C(result_b);
const result_d = await D(result_c);
if(result_d === 'Final Success!'){
alert('success')
}else{
throw(result_d);
}
}catch(e){
console.error(e)
}
}
runAsync();
기존의 promise
에서 then과 catch는 try~catch
구문으로 처리할수 있습니다.
async~await
패턴이 비동기처리를 일반적인 동기처리 처럼 소스를 작성할수 있어서 편하지만 비동기처리를 병렬로 하고싶을때는 await
키워드가 붙은 비동기 처리가 끝날때까지 작업이 멈추는 단점이 있습니다. 그래서, Promise.all([...프로미스 객체 배열 ])
처럼 promise
호출을 병렬식으로 한번에 하는것이 더 편안합니다.
컴포넌트의 역할 나누기와 느슨한 결합도 유지
리더님이 이번 세션 진입 하기전에 컴포넌트의 역할 나누기와 느슨한 결합도에 대해 엄청난 강조를 하셨습니다. 각 컴포넌트끼리는 , "서로 모르는 사이가 되어야한다" 즉, 관계가 있어서는 안된다고 했습니다. 그래서 각 컴포넌트는 render에만 신경을 써야하며, App컴포넌트를 통해 각 하위 컴포넌트의 state를 설정하고 render함수를 호출하는 방향으로 작업을 하는것이 좋다고 하셨습니다.
비동기 처리 방식에 대한 코딩 컨벤션
API서버는 가끔씩 클라이언트에게 올바른 값을 주지 않고, 항상 살아있다는 보장은 할수가 없기에, 기본적인 에러처리, 방어코드, 데이터 검사처리를 꼼꼼히 해야합니다. 예를 들어 fetchAPI는 try~catch
를 통한 오류 처리를 합니다. 하지만 try~catch
안에서는 fetchAPI의 http오류를 검출할수는 없어서 fetchAPI 이후에 반환되는 response객체에 있는 response.ok
또는 response.status
을 통해 http처리상태결과값을 이용해, 그에 맞는 대한 데이터 처리까지 해야합니다.
상수 분리코딩
기본 URL또는 alert에 나올 내용들은 상수로 관리하는 습관을 들이는것이 좋다는 이야기를 했습니다.
이번에는 디바운싱등 새로운 개발 기법들을 많이 배웠습니다. 디바운싱외에 쓰로틀링이나 레이지로딩같은 기법들도 있는데, 기회가 될때 적용해보고 싶다는 생각이 들었습니다. 다음주가 마지막 수업인데, 남은 한 주 후회없게 재밌게 해보겠습니다.