1. Github 에 로그인 한다.

2. 수정이 필요한 repository에 들어간다

3. Pull Requests 메뉴에 들어가서 잘못된 PR의  github의 주소를 확인

    예시) https://github.com/계정이름/레포지토리-이름/pull/8

4.  깃허브에 문의를 한다. 

    https://support.github.com/request

5. Remove data from a repository I own or control( https://support.github.com/request/remove-data )로 접속

6. Remove pull requests 클릭

7. 3 번에서 복사한 삭제할 pull request 주소를 입력하여 티켓을 생성

 

완전히 삭제되면 메일로 알람이 온다.

 

다음으로 할일은 잘 못 합쳐진 내용을 복구하기

만약에 develope 에 pr 해야할 것을 main 으로 하였다면

1. 로컬에서 main 으로 이동 git pull origin main 으로 동기화

2. git log 를 입력하여 커밋된 내용을 확인해서 PR 되기 바로 이전의 commit id 를 확인

3. git reset --hard  <commit id> 를 이용하여 바로 이전으로 되돌리기

4. git push origin main -f 를 이용하여 강제로 이전의 내용으로 덮어씌우기

 

너무 복잡해진다. pull request 를 할때 대상을 잘 지정하였는지 꼭 확인하자.

  • feat :  새로운 기능(feature) 추가
  • fix : 버그 수정
  • perf :  성능향상을 위한 코드 변경
  • refactor :  버그를 수정하지도 않고 새로운 기능을 추가하지도 않은 코드 변경  혹은 파일의 위치 변경/ 리팩토링
  • style :  코드 변경없이 여백, 들여쓰기 철자등을 수정,
  • test : test를 하기 위한 코드를 수정밑 추가
  • docs : 문서만 수정
  • chore :  코드 변경없이 설정을 변경(package.json, tsconfig.ts, 빌드 스크립트 수정 등등) 

Entity 관계를 수정했을 때?

- refactor: 엔티티 관계의 수정이 기존 기능에 영향을 주지 않으면서 코드의 설계나 내부 구조를 개선하기 위한 목적인 경우

- feat : 엔티티의 관계를 수정하는 것이 새로운 기능을 추가하거나 기존 기능의 동작 방식을 변경하는 경우

 

참고 자료

 

Conventional Commits

A specification for adding human and machine readable meaning to commit messages

www.conventionalcommits.org

 

 

angular/CONTRIBUTING.md at 22b96b96902e1a42ee8c5e807720424abad3082a · angular/angular

Deliver web apps with confidence 🚀. Contribute to angular/angular development by creating an account on GitHub.

github.com

 

 

[Git/Github] Commit Convention이란?

커밋 컨벤션에 대해 알아보자

kdjun97.github.io

 

코드 tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": true,
    "strictFunctionTypes": true,
    "useUnknownInCatchVariables": true,
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
  }
}
  • "module": "commonjs"  ▶ 생성될 모듈 코드 wlwjd
  • "declaration": true   ▶ 프로젝트 배포시 .d.ts 파일을 생성
  • "removeComments": true ▶ /*!로 시작하는 copy-right 헤더 주석을 제외한 모든 주석을 제거
  • "emitDecoratorMetadata": true ▶ 소스에 데코레이터 선언에 대한 설계-타입 메타 데이터를 내보냅니다.
  • "experimentalDecorators": true ▶ ES 데코레이터에 대한 실험적인 지원을 사용하도록 활성화합니다.
  • "allowSyntheticDefaultImports": true ▶  default export가 없는 모듈에서 default imports를 허용합니다. 코드 방출에는 영향을 주지 않으며, 타입 검사만 수행합니다
  • "target": "ES2021" ▶ JavaScript에 대한 버전을 설정합니다.
  • "sourceMap": true 해당하는 .map 파일을 생성합니다.
  • "outDir": "./dist" ▶ 컴파일된 파일들을 저장할 디렉토리를 지정합니다.
  • "baseUrl": "./" ▶ 상대 경로가 아닌 모듈이 기본적으로  위치한 기준 디렉토리를 설정합니다.
  • "incremental": true 프로젝트를 증분 컴파일할 수 있도록 .tsbuildinfo 파일을 저장합니다.
  • "skipLibCheck": true  모든 .d.ts 파일을 검사하는 형식을 건너뜁니다.
  • "strictNullChecks": true ▶ 엄격하게 null 과 undefined 타입을 허락하지 않는다.
  • "noImplicitAny": true ▶ any 타입으로 암시한 표현식과 선언에 오류를 발생시킵니다.
  • "strictBindCallApply": false ▶  함수에서 bindcall 그리고 apply 메서드의 더 엄격한 검사를 활성화합니다.
  • "forceConsistentCasingInFileNames": false 파일명에 대소문자 구분하지 않아도 되는 기능 사용 여부
  • "noFallthroughCasesInSwitch": true ▶ 스위치 문에 fallthrough cases에 대해 오류 보고를 사용하도록 설정합니다.
  • "strictFunctionTypes": true 함수를 할당할 때 매개 변수와 반환 값이 서브 타입과 호환되는지 확인합니다
  • "useUnknownInCatchVariables": true ▶ catch 절의 변수 유형을 any 대신 unknown으로 만듭니다.
  • "noImplicitReturns": true ▶ 함수의 모든 코드 경로에서 반환 값이 없을 때 오류를 보고합니다.
  • "noUnusedLocals": true ▶사용되지 않은 지역 변수에 대한 오류를 보고합니다.
  • "noUnusedParameters": true 사용되지 않은 매개변수에 대한 오류를 발생시킵니다

*증분컴파일 : 프로그램의 수정된 부분만 다시 컴파일하는 기술

 

참고자료

  1. https://typescript-kr.github.io/pages/compiler-options.html
  2. https://velog.io/@ez1211/tsconfig.json-%ED%95%9C%EA%B8%80-%EB%B2%88%EC%97%AD
  3. https://inpa.tistory.com/entry/TS-%F0%9F%93%98-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-tsconfigjson-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-%EC%B4%9D%EC%A0%95%EB%A6%AC
  4. https://velog.io/@ez1211/tsconfig.json-%ED%95%9C%EA%B8%80-%EB%B2%88%EC%97%AD

async 함수

async는 function 앞에 위치합니다.

function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환합니다. 

async function f(){
   return 1;
}

 

// 위와 같은 함수
async function f() {
  return Promise.resolve(1);
}

await 함수

await async 함수 안에서만 동작합니다. await는 말 그대로 프라미스가 처리될 때까지 함수 실행을 기다리게 만듭니다. 처리되면 그 결과와 함께 실행이 재개됩니다.

프라미스가 처리되길 기다리는 동안엔 다른 일(다른 스크립트를 실행, 이벤트 처리 등)을 할 수 있기 때문에, CPU 리소스가 낭비되지 않습니다.

 

예시

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("완료!"), 1000)
  });

  let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)

  alert(result); // "완료!"
}

f();

 

 

await promise.then보다 좀 더 세련되게 프라미스의 result 값을 얻을 수 있도록 해주는 문법입니다.

 

promise .then 을   async/await 로 변환 예시

 

promise chaning 에서의 예시

fetch('/article/promise-chaining/user.json')
  .then(response => response.json()) // json 읽기
  .then(user => fetch(`https://api.github.com/users/${user.name}`)) // 사용자 정보 읽기
  .then(response => response.json())
  .then(githubUser => new Promise(function(resolve, reject) { // 아바타 보여주기
    let img = document.createElement('img');
    img.src = githubUser.avatar_url;
    img.className = "promise-avatar-example";
    document.body.append(img);

    setTimeout(() => {
      img.remove();
      resolve(githubUser); // 
    }, 3000);
  }))
  // 3초 후 동작함
  .then(githubUser => alert(`${githubUser.name}의 이미지를 성공적으로 출력하였습니다.`));

 

async / await  로 변환

async function showAvatar() {

  // JSON 읽기
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();

  // github 사용자 정보 읽기
  let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
  let githubUser = await githubResponse.json();

  // 아바타 보여주기
  let img = document.createElement('img');
  img.src = githubUser.avatar_url;
  img.className = "promise-avatar-example";
  document.body.append(img);

  // 3초 대기
  await new Promise((resolve, reject) => setTimeout(resolve, 3000));

  img.remove();

  return githubUser;
}

showAvatar();

 

 

 

다른 사용예시들

(async () => {
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();
  ...
})();

 

 

에러 핸들링

try{ ... } catch { ... } 를 이용

async function f() {

  try {
    let response = await fetch('http://유효하지-않은-주소');
    let user = await response.json();
  } catch(err) {
    // fetch와 response.json에서 발행한 에러 모두를 여기서 잡습니다.
    alert(err);
  }
}

 

 

다시던지기를 이용한 코드 예시

 

.then 이용

class HttpError extends Error {
  constructor(response) {
    super(`${response.status} for ${response.url}`);
    this.name = 'HttpError';
    this.response = response;
  }
}

function loadJson(url) {
  return fetch(url)
    .then(response => {
      if (response.status == 200) {
        return response.json();
      } else {
        throw new HttpError(response);
      }
    })
}

// 유효한 사용자를 찾을 때까지 반복해서 username을 물어봄
function demoGithubUser() {
  let name = prompt("GitHub username을 입력하세요.", "iliakan");

  return loadJson(`https://api.github.com/users/${name}`)
    .then(user => {
      alert(`이름: ${user.name}.`);
      return user;
    })
    .catch(err => {
      if (err instanceof HttpError && err.response.status == 404) {
        alert("일치하는 사용자가 없습니다. 다시 입력해 주세요.");
        return demoGithubUser();
      } else {
        throw err;
      }
    });
}

demoGithubUser();

async/ awiat 이용

class HttpError extends Error {
  constructor(response) {
    super(`${response.status} for ${response.url}`);
    this.name = 'HttpError';
    this.response = response;
  }
}

async function loadJson(url) {
  let response = await fetch(url);
  if (response.status == 200) {
    return response.json();
  } else {
    throw new HttpError(response);
  }
}

// 유효한 사용자를 찾을 때까지 반복해서 username을 물어봄
async function demoGithubUser() {

  let user;
  while(true) {
    let name = prompt("GitHub username을 입력하세요.", "iliakan");

    try {
      user = await loadJson(`https://api.github.com/users/${name}`);
      break; // 에러가 없으므로 반복문을 빠져나옵니다.
    } catch(err) {
      if (err instanceof HttpError && err.response.status == 404) {
        // 얼럿 창이 뜬 이후에 반복문은 계속 돕니다.
        alert("일치하는 사용자가 없습니다. 다시 입력해 주세요.");
      } else {
        // 알 수 없는 에러는 다시 던져집니다.
        throw err;
      }
    }
  }


  alert(`이름: ${user.name}.`);
  return user;
}

demoGithubUser();

 

예제

 

aysnc / await 이용하여 코드변경

function loadJson(url) {
  return fetch(url)
    .then(response => {
      if (response.status == 200) {
        return response.json();
      } else {
        throw new Error(response.status);
      }
    })
}

loadJson('no-such-user.json')
  .catch(alert); // Error: 404

 

      변경

async function loadJson(url) { // (1)
  let response = await fetch(url); // (2)

  if (response.status == 200) {
    let json = await response.json(); // (3)
    return json;
  }

  throw new Error(response.status);
}

loadJson('no-such-user.json')
  .catch(alert); // Error: 404 (4)

 

 

참고자료

https://ko.javascript.info/async-await

프라미스화

콜백을 받는 함수를 프라미스를 반환하는 함수로 바꾸는 것을 '프라미스화(promisification)'라고 합니다.

이는 자바스크립트에서 비동기 작업을 더 깔끔하게 처리할 수 있게 해줍니다.

따라서 콜백보다는 프라미스가 더 편리하기 때문에 콜백 기반 함수와 라이브러리를 프라미스를 반환하는 함수로 바꾸는 게 좋은 경우가 생깁니다.

 

예시 코드

 콜백

function loadData(callback) {
  setTimeout(() => {
    callback('데이터 로드 완료');
  }, 1000);
}

loadData(data => {
  console.log(data); // 데이터 로드 완료
});

 

 프라미스화

function loadData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('데이터 로드 완료');
    }, 1000);
  });
}

loadData().then(data => {
  console.log(data); // 데이터 로드 완료
});

 

f가 두 개를 초과하는 인수를 가진 콜백, callback(err, res1, res2, ...)을 받는경우 처리하는 방법

새롭게 만든 함수를 promisify(f, true)형태로 호출

// 콜백의 성공 결과를 담은 배열을 얻게 해주는 promisify(f, true)
function promisify(f, manyArgs = false) {
  return function (...args) {
    return new Promise((resolve, reject) => {
      function callback(err, ...results) { // f에 사용할 커스텀 콜백
        if (err) {
          reject(err);
        } else {
          // manyArgs가 구체적으로 명시되었다면, 콜백의 성공 케이스와 함께 이행 상태가 됩니다.
          resolve(manyArgs ? results : results[0]);
        }
      }

      args.push(callback);

      f.call(this, ...args);
    });
  };
};

// 사용법:
f = promisify(f, true);
f(...).then(arrayOfResults => ..., err => ...)

 

 

참고자료

https://ko.javascript.info/promisify

+ Recent posts