yarn create

terminal
1
2
3
4
5
# npx create-react-app my-app
yarn create react-app my-app

# npx create-electron-app my-app
yarn create electron-app my-app
  • 보통 보일러플레이트로 프로젝트를 시작할 때 npx를 사용한다
  • yarn createcreate로 시작하는 패키지를 설치할 때 npx와 동일하게 동작한다

npx vs. npm i -g

  • 보일러플레이트로 시작할 때 크게 두 가지 방법이 있는데,
  • npx로 시작하는 방법과, 글로벌 설치 후 cli로 시작하는 방법이 있다
  • 보통 보일러플레이트 패키지는 npx를 권장하는데, 이유는 npx는 항상 최신 버전으로 설치해준다
  • 반면 글로벌로 설치해서 사용하는 경우, 시간이 지나면 구버전이 되고, 업데이트는 하려면 수동으로 해줘야 한다

참고

gh-pages 사용하기

열심히 만든 웹을 Github Pages를 통해 자랑해보자
이때 사용할 수 있는 간편한 패키지가 있다

terminal
1
2
3
4
5
6
npm i -D gh-pages
gh-pages -d dist

# or

npx gh-pages -d dist

gh-pages

  • Github Pages 기능을 통해 정적 웹을 호스팅 할 수 있다
  • gh-pages라는 패키지를 사용하면 간편하게 배포할 수 있다
  • gh-pages를 설치하고 gh-pages -d {빌드 디렉터리} 명령을 하면,
  • gh-pages라는 브랜치가 자동으로 생성되고 빌드 디렉터리의 내용이 깃헙 저장소에 올라간다
  • github pages 세팅도 자동으로 된다
  • package.json이 프로젝트 루트 디렉터리에 존재해야 한다
  • 바닐라 웹 프로젝트를 진행한 경우에도 gh-pages를 사용하고 싶다면,
  • npm init -y 명령으로 임시로 package.json을 생성하고
  • npx로 gh-pages를 실행하면 된다

옵션 사용하기

terminal
1
npx gh-pages -d dist -b dist --dotfiles --tag \"🚀update\"
  • -d dist dist 디렉터리를
  • -b dist 원격 레포의 dist 브랜치에
  • --dotfiles 닷 파일을 포함하고,
  • --tag \"🚀update\" 태그도 지정해 줄 수 있다
  • 더 많은 옵션은 -h로 확인

nextjs 배포하기

terminal
1
2
touch .nojekyll
npx gh-pages -t true -d out
  • .nojekyll 파일을 생성해 줘야 한다
  • gh-pages는 기본적으로 지킬 기반으로 동작한다
  • 그러면 _로 시작하는 파일들을 제대로 동작하지 않는다
  • 그래서 지킬을 사용하지 않는다는 것을 .nojekyll파일을 생성하여 알릴 수 있다
  • gh-pages로 배포할 때 -t true 옵션을 사용하는데,
  • .(dot)으로 시작하는 파일을 포함하여 배포하라는 뜻이다
  • 옵션을 사용하지 않는 다면 .nojekyll이 제외된다

참고

비공개 npm package 만들어보기

  • 깃허브 레지스트리를 통해 (비공개) 패키지를 만들어보자
  • PAT을 통해 퍼블릭하지 않게 패키지를 배포해 볼 수 있다
  • 물론, 공개 패키지도 가능하다
  • 패키지 생성은 동일하고, 패키지를 받을 때만 차이가 있다
  • PAT : personal access token

PAT 발급

저장소, 패키지 만들기

  • package.json에 필수적으로 채워야 하는 항목들이 있어서,

  • 브라우저로 github에 접속해서 저장소 하나를 만들어 로컬로 클론하고
    npm init -y 하는 것을 추천한다

  • 타입스크립트로 만든다

terminal
1
2
3
git clone https://github.com/chinsun9/hello-package.git

tsc --init

디렉터리 구조

디렉터리 구조
1
2
3
4
5
6
7
8
9
10
11
12
.
├── dist
│ ├── index.d.ts
│ └── index.js
├── src
│ └── index.ts
├── .gitignore
├── .npmignore
├── .npmrc
├── package.json
├── README.md
└── tsconfig.json
  • 디렉터리 구조는 마음대로

  • 나는 위처럼 구성했다

  • src 밑에 ts 코드를 작성하고,

  • tsc 명령으로 dist 아래 트랜스파일 된 js를 배포하는 방식이다

src 작성

src/index.ts
1
2
3
4
5
export class MyClassA {}

export class MyClassB {}

export class MyClassC {}
  • 원하는 기능을 구현하고 외부에서 사용 가능하도록 export키워드를 붙여준다

tsconfig.json 설정

  • 타입스크립트로 코드를 작성하고,
  • tsc로 트랜스파일한다. 결과로 js파일이 생성된다
  • 패키지를 인스톨한 사람들은 js파일을 사용하게 된다
tsconfig.json
1
2
3
4
5
6
7
8
9
10
11
{
"compilerOptions": {
// ...
"declaration": true /* Generates corresponding '.d.ts' file. */,
// ...
"outDir": "./dist",
"rootDir": "./src"
// ...
},
"include": ["src"]
}
  • tsc --init 기본값으로 생성된 상태에서 위 옵션만 수정해주었다
  • declaration ; d.ts파일을 생성해서 자동완성에 도움을 준다
  • outDir ; tsc 명령의 결과로 생성되는 js 위치
  • rootDir, include ; root ts 파일 위치

.gitignore

.gitignore
1
2
dist
node_modules
  • 커밋에서 무시할 디렉터리, 파일을 나열한다

.npmignore

.npmignore
1
2
3
src
test
tsconfig.json
  • 패키지를 publish 할 때 무시할 디렉터리, 파일을 나열한다

.npmrc

  • 워크스페이스에 위치해도 되고,
  • 어느 워크스페이스든 상관없이 전역적으로 적용하려면 ~/.npmrc에 넣어주면 된다
.npmrc
1
//npm.pkg.github.com/:_authToken=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • 처음에 발급받은 토큰을 xxxx... 부분에 넣어준다
  • 자신의 토큰은 아무래도 전역으로 적용하는 게 좋아 보인다

package.json

package.json
1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "@chinsun9/hello-package",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"repository": "https://github.com/chinsun9/hello-package.git",
"author": "chinsun9 <chin_sung@naver.com>",
"license": "MIT",
"publishConfig": {
"registry": "https://npm.pkg.github.com/"
}
}
  • 몇 가지 수정사항이 있다
  • name, main, types, publishConfig를 적절하게 수정한다
  • name ; @chinsun9/처럼 골뱅이 자기 이름을 넣어준다
  • main ; 트랜스파일 결과로 메인 파일을 넣어준다
  • types ; 자동완성을 위해서 생성된 d.ts파일을 넣어준다
  • publishConfig ; registry를 깃허브로 하겠다는 설정이다

패키지 배포

  • npm publish
  • 저장소에 들어가서 패키지가 잘 배포되었는지 확인하다

배포한 패키지 인스톨해보기

  • github registry에 등록된 패키지는 퍼블릭 일지라도 PAT이 필요하다
  • 퍼블릭일 때 패키지 주인이 생성한 토큰이 아니다
  • 각자 자기 자신의 토큰으로 가능하다..!
  • 비공개 패키지라면 패키지 주인이 생성한 토큰이 있어야 한다
  • 패키지 주인은 read:packages 권한이 있는 토큰을 알려주면 다른 사람, 컴퓨터에서 패키지를 인스톨할 수 있다
  • 임시 디렉터리를 하나 만들고 npm init -y한다
  • .npmrc를 생성하고 내용을 추가한다
.npmrc
1
2
//npm.pkg.github.com/:_authToken=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@chinsun9:registry=https://npm.pkg.github.com/
  • 워크스페이스의 .npmrc 또는 유저 홈 디렉터리의 .npmrc 에 위 내용을 추가한다

  • @chinsun9:registry=https://npm.pkg.github.com/

  • @chinsun9으로 시작하는 패키지는 https://npm.pkg.github.com/ 에서 가져오라고 알려주자

헷갈린 점

  • 퍼블릭한 패키지도 PAT가 필요했다
  • 당연히 퍼블릭한 패키지에는 토큰이 필요 없을 거라 생각했다
  • 그래서 어쩔 수 없이 패키지 오너의 토큰이 필요할 거라 생각했다
  • 근데, 패키지 주인이 생성한 토큰이 아니더라도 패키지를 인스톨할 수 있었다
  • 즉, github 계정을 가지고 있고, read:packages 토큰을 생성하면 퍼블릭 패키지를 인스톨할 수 있다

참고

내 첫 패키지

GitHub 패키지 저장소 호스팅: GitHub Package Registry 시작하기

d.ts 만들기

*rc 뜻

Moment.js utc 사용하기

1
2
const date1 = moment().utc().format('YYYY-MM-DD HH:mm:ss');
console.log(date1);
  • utc() 메서드를 이용한다

활용한 곳

  • rds는 기본적으로 utc를 사용한다
  • 그래서 현재 지역 시간으로 포맷팅 된 값을 그대로 db에 넣으면 안 된다
  • rds의 시간대를 변경하거나, insert, update 할 때 잘 가공해서 쿼리를 해야 한다

참고

forEach await 안되는 문제

상황

  • 배열로 저장되어 있는 데이터를 forEach로 순회하면서 db에 INSERT하는 쿼리를 만들려고 했다
  • 근데 비동기적으로 동작했다
1
2
3
await data.forEach(async (element: ArticlePreview, idx: number) => {
// insert query
});

해결

1
2
3
4
5
6
7
8
9
for (const element of data) {
// ...
try {
const a = await databaseConnection.query(queryString, [
// ...
]);
}
// ...
}
  • for of에서는 await을 통해서 순차적으로 처리가 가능했다

시도해보지 않은 다른 방향

참고

SyntaxError: Unexpected end of input

  • vscode에서는 아무 에러, 경고없이 잘 실행되었는데,
  • SyntaxError-Unexpected-end-of-input 에러가 날 때가 있다
  • 나의 경우에는 api 서버가 host가 달라 cors mode로 리퀘스트를 보내야하는데
  • ‘no-cors’ mode로 보내서 생긴 에러이다
  • 그 외에도 api서버에서 연산이 잘못되어 응답을 반환하지 않을 때에도 똑같은 에러가 나왔다
  • 그냥 서버로부터 결과를 제대로 받지 않으면 생기는 오류 같다

윈도우에서 yarn 설치

  • nodejs로 이것저것 할 때 yarn을 피해 갈 수 없을 것이다

설치방법

  • 설치가 완료되면 cmd를 열고 yarn -v 를 쳐서 확인한다

yarn

  • 페이스북에서 만든 npm

참고

nodejs __dirname

index.js
1
2
log(`__dirname`, __dirname);
log(`process.cwd()`, process.cwd());

C:\git>node tmp\app-root\index.js
__dirname C:\git\tmp\app-root
process.cwd() C:\git

  • __dirname은 현재 실행하는 파일의 절대경로이다
  • process.cwd()는 node명령을 호출한 작업디렉터리의 절대경로이다

app-root-path

index.js
1
2
3
4
5
6
const log = console.log;
const app_root_path = require('app-root-path').path;

log(`__dirname`, __dirname);
log(`process.cwd()`, process.cwd());
log(`app_root_path`, app_root_path);
  • 프로젝트 루트를 찾아주는 패키지도 있다

참고