(최종 프로젝트 진행중)
오늘 한/마친 일:
- 프로젝트 전체 폴더, 파일, 클래스 및 임포트 경로를 단수형(’user’)에서 복수형(’users’)로 바꿨다.
⇒ 프로젝트 폴더와 파일명을 바꾸는 작업은 생각보다 복잡한 작업이며, 팀원 아무도 코드를 작성하지 않은 초창기 시점이나 팀 프로젝트의 모든 코드가 작성된 마무리 시점에 바꾸는 것이 좋다는 배움을 얻었다…
파일명과 폴더명, 클래스명과 임포트되는 경로에 들어가는 모듈명 전부를 단수형(user)에서 복수형(users.controller.ts)로 바꾸느라 삽질하며 배운 것:
- 노가다로 반복 숙달된 단축키 커맨드와 윈도우 명령어 ren
- Nest.js (암묵적인) 네이밍 컨벤션이 모듈, 컨트롤러, 서비스 파일명 및 클래스명은 복수형(UsersModule)을 취하고, 엔티티와 DTO 파일 및 클래스명은 단수형(CreateUserDto)을 취한다는 사실.
- 다른 팀원의 코드와 ‘잘’ 합치는 게 아주 어렵다는 점. 일단 VS Code는 병합이 일어날 때 user라는 폴더와 users라는 폴더를 ‘이름이 바뀌었다’고 하지 않고 다른 폴더로 만들어버린다. 이 문제 때문에 rebase나 merge 자체도 하나하나 뜯어보며 해줘야 하는데, 그걸 또 main에 올려서 다른 팀원이 pull을 받는다고 생각하면 아득하다. 그쪽 코드는 여전히 단수형 폴더명들일 테니까…
- git rebase는 괜히 어렵기만 하다는 사실. 상기한 것처럼 user와 users 폴더 내에 각각 달라진 점을 충돌로 표시하지 않아서 소리소문 없이 코드가 이상하게 바뀌어 있는 경우가 많았다. git push 및 merge로 작업할 땐 최소한 모든 사항을 빠짐없이 체크할 수 있었는데… rebase가 그냥 처음인데 특수 상황(user를 users로 바꾼 상황)까지 겹처 그랬던 걸수도 있다. 그러나 유용한 점에 비해 위험과 시간 손실이 너무 크다.
⇒ 일단 바꿔 놓은 게 있으니 이걸 main 브랜치에 일단 반영하되, 각자 작업 중인 코드가 유실되지 않도록 pull 받을 땐 수신 쪽(들어오는 쪽)을 마음껏 무시해도 되도록 공지하였다.
- ‘품앗이’ 신청 CRUD 마무리
- Linear와 깃헙을 연동하여 처음 issue를 ‘done’으로 만들어 봄.
- YAML 파일 에러를 해결하여 GitHub Actions를 활성화시키는 데 성공.
※ 이하는 스스로 공부하며 적어둔 노트이며 불확실한 내용이 있을 수 있습니다. 학습용으로 적합하지 않음을 유념해주세요. ※
Github Actions와 Round Robin
Github Actions와 Round Robin
결과: 다음과 같은 yml 파일을 만들어 깃헙의 메인 브랜치에 올려두었다.
// .github/workflows/my-action.yml
name: MAIN branch PUSH, PULL_REQUEST test
run-name: PUSH or PULL_REQUEST events triggered on branch MAIN
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 15.x, 18.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- run: npm run build --if-present
# TODO: - run: npm test
처음에 name: [main] branch … 라고 대괄호를 써서 문법에 어긋나버렸고,
다음에는 들여쓰기가 말썽이었다. 깃허브 에디터에 뜨는 에러 도움말을 보고 간신히 수정하여 올렸다. 들여쓰기가 중요하다고 했는데, 내 파일은 탭(Tab)이 아니라 띄어쓰기로 들여쓰기 간격을 맞추고 있더라… 그걸 모르고 탭으로 맞추니 아무리 해도 어긋나지…
어쨌든 결과적으로는 main 브랜치에 Pull request 발생 시 GitHub actions 테스트가 잘 작동한다.
(이하는 첫 조사부터의 노트 테이킹과 생각 과정을 두서없이 적어둔 것이다. 보관용으로 올려둔다.)
GitHub Actions 마켓 플레이스!
GitHub Actions 관련 질문
name: learn-github-actions
on:
push:
branches: [master, dev]
pull_request:
branches: [master]
paths:
- '**.js'
paths-ignore:
- 'doc/**'
jobs:
build:
strategy:
matrix:
node-version: [10.x, 12.x]
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v3
- name: My First Step
run: npm install
npm test
npm build
이렇게 생긴 yaml 파일을 만들려고 하는데,
- actions/checkout@v3 가 정확히 뭐 하는 애인지 설명을 봐도 모르겠다.
⇒ 자세히 보다보니…. “This is an action that checks out your repository onto the runner, “ 여기서 runner는 ubuntu 운영체제(서버)를 가리키고, check out 한다는 건 (깃헙이 런칭한) 가상의 서버컴에 내 레파지토리 코드를 clone한다는 말 같다..!
- 같은 맥락에서 actions/setup-node@v3 도 필수 옵션이다. node.js를 설치하고, node와 npm을 가상 서버컴에 PATH 등록해주는 거라고.
name: learn-github-actions
run-name: ${{ github.actor }} is learning GitHub Actions
on: [push]
jobs:
check-bats-version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '14'
- run: npm install -g bats
- run: bats -v
- 꼭 runs-on: ubuntu로 해야 하는가? 아! AWS EC2에서 ubuntu로 배포할 거면 이걸로 테스트하는 게 맞겠구나..!
Understanding the workflow file
To help you understand how YAML syntax is used to create a workflow file, this section explains each line of the introduction's example:
name: learn-github-actions | Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. |
run-name: ${{ github.actor }} is learning GitHub Actions | Optional - The name for workflow runs generated from the workflow, which will appear in the list of workflow runs on your repository's "Actions" tab. This example uses an expression with the github context to display the username of the actor that triggered the workflow run. For more information, see "Workflow syntax for GitHub Actions." |
on: [push] | Specifies the trigger for this workflow. This example uses the push event, so a workflow run is triggered every time someone pushes a change to the repository or merges a pull request. This is triggered by a push to every branch; for examples of syntax that runs only on pushes to specific branches, paths, or tags, see "Workflow syntax for GitHub Actions." |
jobs: | Groups together all the jobs that run in the learn-github-actions workflow. |
check-bats-version: | Defines a job named check-bats-version . The child keys will define properties of the job. |
runs-on: ubuntu-latest | Configures the job to run on the latest version of an Ubuntu Linux runner. This means that the job will execute on a fresh virtual machine hosted by GitHub. For syntax examples using other runners, see "Workflow syntax for GitHub Actions." |
steps: | Groups together all the steps that run in the check-bats-version job. Each item nested under this section is a separate action or shell script. |
- uses: actions/checkout@v3 | The uses keyword specifies that this step will run v3 of the actions/checkout action. This is an action that checks out your repository onto the runner, allowing you to run scripts or other actions against your code (such as build and test tools). You should use the checkout action any time your workflow will run against the repository's code. |
- uses: actions/setup-node@v3
with:
node-version: '14' | This step uses the actions/setup-node@v3 action to install the specified version of the Node.js (this example uses v14). This puts both the node and npm commands in your PATH . |
- run: npm install -g bats | The run keyword tells the job to execute a command on the runner. In this case, you are using npm to install the bats software testing package. |
- run: bats -v | Finally, you'll run the bats command with a parameter that outputs the software version. |
이건 어떤지?
name: Node.js CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x, 14.x, 15.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- run: npm run build --if-present
- run: npm test
- run: npm ci
Using
npm ci
installs the versions in the package-lock.json or npm-shrinkwrap.json file and prevents updates to the lock file. Usingnpm ci
is generally faster than runningnpm install
.
- cache: ‘npm’ →
You can cache and restore the dependencies using the
setup-node
action.
- run build? build가 뭐지?
build와 test를 진행하는 동안 log files, test results 등을 저장해둘 수도 있다고 한다: "Storing workflow data as artifacts."
build와 test를 거치는 CI 작업이 끝났다면 진행할 스텝: package registry (npm install 할 때 가져오는 그 npm 마켓 말하는 것 같다)에 배포하기. "Publishing Node.js packages." ⇒ 우리 프로젝트는 패키지로 만들어 배포할 필요는 없으므로 여기까지는 생각하지 않아도 될 것 같다.
위의 세미 최종 yaml 파일을 뼈대만 빼오면 이렇다:
name: Node.js CI
on:
jobs:
build:
runs-on: ubuntu-latest
strategy:
steps:
⇒ [push, pull-request] 등의 깃허브 이벤트마다 새로 가상 서버를 만들고 테스트를 진행한다는 것임. (하나의 가상 서버를 먼저 세팅하고서 push 때, pull-request 때 각 각 테스트를 나눌 수 있는 것이 아니다.)
- 이게 맞나? 왜인지 후자가 더 합리적이어 보이는데…
- build를 안 하면 어떻게 되나? ⇒ 일단 저기서의 build란 “job name”을 뜻한다.
- npm run build 후 npm test? 아니면 테스트를 먼저 하고 빌드?
그래서…
- 결국 초기 테스트 코드는 필요하다 이 말인데…
- 커스텀 테스트 코드 없이 깃헙 액션즈를 세팅해놓는 방법도 있을까?
⇒ 그냥 run: npm test 부분을 빼고 npm run build 부분까지만 해도 시작으론 괜찮음.
- 기초 커스텀 코드를 빠르게 작성할 수 있는 방법이 있을까? 어떤 식으로 테스트 코드를 작성해야 하는지 감이 잘 안와서…
- 커스텀 테스트 코드 없이 깃헙 액션즈를 세팅해놓는 방법도 있을까?
- 이 .github/workflows 는 어느 브랜치에 작성해놔야 하는가? 아무래도 main이겠지..? ⇒ 그렇다.
- on: push 라면, 어느 브랜치에 push가 일어나든 전부 다 잡고, on: pull-request라면 어느 브랜ㅊ에서 어느 브랜치로 PR이 일어나든 전부 다 잡는건가? ⇒ on: push: branches 항목이 있다!
최종 질문 정리
이렇게 생긴 yaml 파일을 등록하려고 하는데:
// .github/workflows/my-action.yml
name: [main] branch [PUSH, PULL_REQUEST] test
run-name: PUSH or PULL_REQUEST events triggered on branch MAIN
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x, 15.x, 18.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- run: npm run build --if-present
- run: npm test
test-by-feature:
runs-on: ...
strategy:
steps:
- 일단 이 정도면 충분한가요
- npm test에 사용할 초기 테스트 코드를 … 간편하게 설정하고 들어가는 방법
- 이 파일을 로컬에서 push를 이용해 원격 깃헙으로 보내는 것인지, 아니면 .gitingnore에 등록해 놓고 깃헙 페이지에서 직접 관리하는 것인지
- main 브랜치에만 .github/workflows 폴더를 만들고 거기다 yaml 파일들을 몽땅 넣으면 되는지
- ‘build’ 외에 저렇게 또 하나의 Job을 계속 지정해주는 방식이 좋은가, 따로 떼어주는 게 좋을까
- 작은 단위로 테스트하는 방법 - 이 때도 actions/chekcout 부터 run: ci까지는 전부 수행해야 하는가. 아니면 작은 단위의 테스트가 아예 필요 없을까? 트렁크 기반 개발이라서? 항상 main 브랜치가 테스트 대상이 될 테니까..?
- github actions를 활성화해둔다고 하면 리뷰어를 어떻게 정하는지 - 무작위 두 명? 팀 내 임명된 리뷰어 한 명?
- PR과 리뷰는 아무 때나? 아니면 매 회의 시간에만?
(튜터님게 DM 보낸) 간추린 질문 리스트:
- 만약 이렇게 Github Actions를 활용하게 된다면, 결국 모두가 자기 코드에 대한 테스트 코드도 동시에 만들어 PR 해야 -run: npm test가 의미있어질 수 있는 걸까요
- 테스트할 때 더 작은 단위로 테스트하려면 위의 yaml 파일을 어떻게 수정해야 할까요. 아니면 아예 (트렁크 기반 개발이므로) main 브랜치 전체에 대한 테스트 외에 더 작은 테스트가 필요 없을까요?
- .github/workflows 폴더는 어디에 (main 브랜치? 로컬 브랜치에서 푸시?) 만들어야 할까요
- 리뷰어를 팀 내 특정한 한 사람으로 지정해두는 게 좋을지 궁금합니다!
⇒ 답:
- 이건 같이 얘기해봐요
- 전체에 대한 테스트만 하시면 돼요
- 메인에 커밋하시면 됩니다
- round robin으로 랜덤하게 select되게 하는게 좋습니다
+ 리뷰어를 어떻게 지정하는지에 대해서도 질문하였더니…
- Q. “리뷰어를 팀 내 특정한 한 사람으로 지정해두는 게 좋을지 궁금합니다”
- A. “round robin으로 랜덤하게 select되게 하는게 좋습니다.”
⇒ 깃허브 Round Robin 방식: 풀 리퀘가 생긴 경우 팀 내 n명을 리뷰어로 랜덤 배정하는 방식.
라운드 로빈 설정 방법 참고 링크
- Q. “리뷰는 수시로 이루어지는지, 매일 회의 때마다 대대적으로 하는지”
- A. “24시간 내로 리뷰를 해주는 룰이 있기는 합니다. 또 ‘review first’라고 본인이 하던 일이 있어도 리뷰 리퀘스트가 오면 그걸 먼저 해결하도록 하는 팀 문화도 있어서, 어쨌든 리뷰가 빨리 되어야 프로젝트가 굴러가게 됩니다”
참고함:
(참고: https://velog.io/@ggong/Github-Action에-대한-소개와-사용법)
(참고: YAML이란 - https://velog.io/@jnine/YAML이란)
(참고: 공식 문서 - https://docs.github.com/ko/actions/learn-github-actions/understanding-github-actions)
나중에 더 읽어보고 싶은:
(참고: 카카오웹툰은 GitHub Actions를 어떻게 사용하고 있을까 - https://fe-developers.kakaoent.com/2022/220106-github-actions/)
(참고: YAML 문법 총정리 - https://inpa.tistory.com/entry/YAML-📚-yaml-개념-문법-이해하기-💯-총정리#들여쓰기indent)
윈도우 명령 프롬포트로 파일명 일괄 변경하기
윈도우 명령 프롬포트로 파일명 일괄 변경하기
프로젝트 폴더와 파일들의 이름을 전부 단수형에서 복수형으로 바꿔야 할 일이 생겨서 사용한 윈도우 명령어:
C:\Users\USER\Desktop\Sparta\05_project_무인냥품>cd src/user
C:\Users\USER\Desktop\Sparta\05_project_무인냥품\src\user>ren *.ts users.*.ts
C:\Users\USER\Desktop\Sparta\05_project_무인냥품\src\user>cd ../
C:\Users\USER\Desktop\Sparta\05_project_무인냥품\src>cd user-like
C:\Users\USER\Desktop\Sparta\05_project_무인냥품\src\user-like>ren *.ts user-likes.*.ts
...(반복)
(참고: https://forbes.tistory.com/452)
Nest.js 네이밍 컨벤션
Nest.js 네이밍 컨벤션
- user와 cat 같은 모듈, 컨트롤러, 서비스 파일명 및 클래스명은 복수형을 기본으로 한다. (엔티티가 되는 user와 cat이 여럿일 것이므로)
ex) users/users.module.ts, users/users.controller.ts, users/users.service.ts
ex) export class UserLikes
- 엔티티와 DTO 파일 및 클래스명은 그대로 단수형으로 쓴다. (엔티티 하나의 일반 케이스를 나타내기 때문)
ex) users/user.entity.ts
ex) export class User { }
ex) users/dto/create-user.dto.ts
ex) export class CreateUserDto { }
Error: EPERM: operation not permitted, rename… (진행중)(해결 실패)
Error: EPERM: operation not permitted, rename… (진행중)(해결 실패)
발생 상황: VS Code에서 Nest.js 프로젝트 src 폴더 안의 폴더명을 cat에서 cats로 바꾸려고 함. 로딩이 오래 걸리더니 1분쯤 지나 저렇게 뜸.
타입: 바보 이슈 …인 줄 알았으나 해결할 수 없었던.
에러 메세지 전문:
Error: EPERM: operation not permitted, rename 'c:\Users\USER\Desktop\Sparta\05_project_무인냥품\src\cat' -> 'c:\Users\USER\Desktop\Sparta\05_project_무인냥품\src\cats'
시도: 앱 실행을 중지하고 폴더명 바꾸기를 재시도. ⇒ 그래도 안됨?!
시도2: VS Code를 닫고 다시 열어서 실행 ⇒ 다른 폴더 이름 변경 때 또 그러한 문제 발생
시도 3: Antivirus의 문제일 수 있다고 하여 제안대로 node_modules/graceful_fs/polyfills.js 파일을 수정하여 봄 ⇒ 안됨.
// node_modules/graceful_fs/polyfills.js
if (platform === "win32") {
fs.rename = typeof fs.rename !== 'function' ? fs.rename
: (function (fs$rename) {
function rename (from, to, cb) {
var start = Date.now()
var backoff = 0;
fs$rename(from, to, function CB (er) {
if (er
&& (er.code === "EACCES" || er.code === "EPERM")
// && Date.now() - start < 60000
) {
// setTimeout(function() {
// fs.stat(to, function (stater, st) {
// if (stater && stater.code === "ENOENT")
// fs$rename(from, to, CB);
// else
// cb(er)
// })
// }, backoff)
if (backoff < 100)
backoff += 10;
return;
}
if (cb) cb(er)
})
하지만 위 파일에 작성된 주석에서 힌트를 얻었다.
“on Windows, A/V software can lock the directory, causing thisto fail with an EACCES or EPERM if the directory contains newly created files. Try again on failure, for up to 60 seconds.”
⇒ slackoverflow의 다른 답변들은 ‘바꾸려는 파일명이 이미 존재하는 파일명일 때 그럴 수 있다”, “그냥 vs code를 닫고서 npm install을 실행하라”, “실행 중인 앱을 중지하라” 이런 얘기가 태반이었는데.
시도 4: ‘새로 작성된 파일’은 없어도 오류가 있는 파일은 바꾸려는 폴더 안애 있어서 그걸 전부 수정하니 폴더명이 바뀌었다.
원인:
원인 1. VS Code instance가 실행중이었어서 그랬다. 즉, 이 Nest.js 프로젝트 앱을 실행중이었어서 그랬다. 어쩐지 그 전까진 잘만 이름을 바꿀 수 있더만 갑자기 안 된다 했다. 중간에 앱을 실행시켜놓아서 그랬다. 생각해보면 앱 실행 중에는 파일명을 바꿀 수 없는 게 당연하겠다.
원인 2. 왜 안되지… 의심가는 바는,
(참고: https://stackoverflow.com/questions/67965961/error-error-eperm-operation-not-permitted-rename-path)
(참고: https://stackoverflow.com/questions/39293636/npm-err-error-eperm-operation-not-permitted-rename )
(참고: 위의 방법과 비슷? https://plming.tistory.com/211)
폴더 및 파일명 및 참조 코드 바꾸기 진행중…. 답이 안 나온다.
- 왜 F2로 폴더명을 수정할 때, 어떤 폴더는 자 ㄹ되고 어떤 애는 안 되는 걸까?
- 어떨 때는 해당하는 code 변화까지 모두 추적해서 바꿔주고, 어떨 때는 안 그렇지?
해결: 미해결 (생각보다 답이 안 나온다.) → 어쩔 수 없이 노가다로 수정하였다.
에러 TypeError: Cannot read properties of undefined ✔️
발생 상황: Nest.js의 한 Service에서 다른 Service를 주입해 사용하려고 하는데, 생성자도 잘 만들어 줬는데 this.xxxxService.메소드()를 호출하니 저런 에러가 뜸. this.xxxxService를 undefined라고 인식하고 있는 게 분명한데, 분명 Module에서도 import와 provider 설정을 잘 해줬다.
해결: 알고 보니 해당 (this.xxxxService를 호출하고 있는) Service에 @Injectable() 데코레이터를 달아주지 않아서 그랬다.
알게 된 것:
Service 계층에서 @Injectable() 데코레이터를 제대로 달아주지 않으면 내부에서 this.anotherService 를 사용할 때 ‘cannot read properties of undefined TypeError’가 뜬다는 것.
Uploaded by N2T