쁘띠 TFT 프로젝트

오늘은 프로젝트를 마치고 발표 및 피드백을 받게되는 날이였고, 피드백에 관한 생각들을 정리해보았다.

피드백

트랜잭션의 최적화

  • 트랜잭션 내부에 await을 다중으로 사용하는 경우 트랜잭션 작업속도가 느려질 수 있다.

    => 트랜잭션 속도가 느려지면, 격리수준에 따른 잠금으로 인해 데드락/성능저하 가 심해질 수 있다.

  • 해결책

    1. 트랜잭션 외부에서 await을 통해 비동기 처리를 미리 해두어 트랜잭션 내부에선 최소한의 작업이 되도록 만들기

       const data = await fetchData(); // 트랜잭션 외부에서 비동기 작업 수행
      
       await db.transaction(async (trx) => {
           await trx('table').insert(data); // 트랜잭션 내부 작업 최소화
       });
      
    2. Promise.all()을 이용해 병렬적 실행하기

       // 트랜잭션 내부
       await Promise.all([
           trx('table1').insert(data1),
           trx('table2').update(data2),
       ]);
      
  • 실험

Promise.all()을 이용하면 동시호출과 실행순서가 지켜지면서, 병렬적으로 시스템을 실행하기 때문에 실행시간이 적어진다는데 이를 확인해보자

  • for문과 await을 이용해 동기적으로 실행하기
async function test() {
    const list = [3000, 2000, 3000, 4000, 1000, 1000, 2000, 3000];
    // num으로 받은 숫자만큼 타이머 실행 후 num 반환
    const testFunction = function (num) {
        return new Promise((resolve) => setTimeout(() => resolve(`${num}`), num));
    }
    //시간 측정
    console.time()
    // for 과 await 사용
    for (let i = 0; i < list.length; i++) {
        //list의 내부 시간만큼 타이머 실행 이후 값을 반환
        const result = await testFunction(list[i]);
        console.log(result);
    }
    //측정 끝
    console.timeEnd()
}

await실험1

=> 순차적 시간이 끝날 때마다 나왔으며, 실행된 시간은 3 + 2 + 3 + 4 + 1 + 1 + 2 + 3 = 17 ≓ 19 초가 나왔다.

  • Promise.all()과 map()을 이용해 비동기적으로 실행하기
async function test() {
    const list = [3000, 2000, 3000, 4000, 1000, 1000, 2000, 3000];
    // num으로 받은 숫자만큼 타이머 실행 후 num 반환
    const testFunction = function (num) {
        return new Promise((resolve) => setTimeout(() => resolve(`${num}`), num));
    }
    //시간측정
    console.time()
    // Promise.all 과 map() 사용
    //list의 내부 시간만큼 타이머 실행 이후 값을 반환
    Promise.all(list.map((e) => testFunction(e)))
        .then((results) => {
            console.log(results)
            // 측정 끝
            console.timeEnd() 
         })
}

await실험2

=> 이번엔 순서대로 나왔지만, 최대값인 4초를 기준으로 프로세스가 마무리 되었다!

  • 결론

앞으로 트랜잭션의 실행시간을 줄이기 위해 반복문 내부 await의 경우 Promise.all()을 이용해야겠다.

RESTful API 형식 미비

RESTful한 API 형식이 제대로 반영되지 않은 것 같다고 하여 튜터님께 문의를 하였다!

RESTful API에서 조회 및 검색 기능의 경우 query string을 이용해 구현하는 경우가 많다는 설명을 듣게 되었다.

  • query string

    URL에 매개변수값을 저장하는 방법으로 URL에서 ?(물음표 기호)다음에 나오는 내용을 의미한다.

  • query string의 구조

    대부분의 구조는 field(필드이름) = value (값) 으로 구성되어 있으며,

    URL에서 여러 필드값을 저장하기 위해 <?field1=value1&field1=value2&field2=value3> 이런 형식을 사용한다.

  • query string의 장점

    필드와 변수명이 URL에 저장되어 있기에 여러 사용자에게 똑같은 화면을 공유하기 수월하다

Reference

스파르타코딩클럽
Github Page 로컬테스트
Jekyll 공식사이트
RubyInstaller(Window)