안녕하세요 초원입니다. 👩🏻💻
회사에서는 반응형이 괴롭히고, 항해플러스에서는 낯선 CI/CD가 괴롭혀요 ..
도망가고 싶지만 그건 또 멋이 없으니까 ㅋㅋ
일단 해보겠습니다 얍 ✌🏻 (으앙 ... 💦)
6주차 과제
[목표]
다양한 workflow job을 만들어보고 실행하여 적용해봅니다.
모든 CI가 정상적으로 실행되어야 합니다.
[요구사항1 - yaml 파일 작성]
1. workflow는 PR이 올라오거나 혹은 PR에 commit이 push될 때 실행 된다.
name: CI Assignment 6
on:
pull_request:
types:
- synchronize
- opened
- reopened
paths:
- 'packages/assignment-6/**'
# 이렇게도 표현이 가능해요 👇🏻
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'packages/assignment-6/**'
• on: pull_request: 이 설정은 PR 관련 이벤트가 발생할 때 워크플로우를 트리거합니다.
• types
• synchronize: PR에 새로운 커밋이 푸시될 때 트리거됩니다.
• opened: 새로운 PR이 열릴 때 트리거됩니다.
• reopened: 닫힌 PR이 다시 열릴 때 트리거됩니다.
• paths: ‘packages/assignment-6/’ 경로에 있는 파일들이 변경되었을 때만 워크플로우가 트리거되도록 제한합니다.
2. job1: tsc, build 를 실행한다. 오류가 발생하면 코멘트를 남긴다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: latest
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: run build
run: |
pnpm install
pnpm -F assignment-6 tsc
pnpm -F assignment-6 build
continue-on-error: true
- uses: actions/github-script@v6
if: failure()
with:
github-token: ${{secrets.TOKEN_FOR_CI}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '빌드에 실패했습니다. 로그를 확인해주세요.'
})
요구사항 구현:
• pnpm install 명령어를 통해 프로젝트의 의존성을 설치하고, pnpm -F assignment-6 tsc로 TypeScript 코드를 컴파일합니다.
• pnpm -F assignment-6 build로 프로젝트를 빌드하며, 빌드가 실패할 경우 GitHub 이슈에 코멘트를 남깁니다.
3. job2: eslint를 실행한 다음에, eslint에서 오류가 발생할 경우 report를 코멘트에 남긴다.
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: latest
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: run lint
run: |
pnpm install
pnpm -F assignment-6 lint:report
continue-on-error: true
- name: Comment ESLint results
uses: actions/github-script@v6
with:
github-token: ${{secrets.TOKEN_FOR_CI}}
script: |
const fs = require('fs')
const eslintResultsFile = './packages/assignment-6/eslint-report'
if (fs.existsSync(eslintResultsFile)) {
const eslintResults = fs.readFileSync(eslintResultsFile, 'utf-8')
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## ESLint Results\n\n${eslintResults}`
})
}
요구사항 구현:
• pnpm install 명령어로 의존성을 설치하고, pnpm -F assignment-6 lint:report로 ESLint를 실행하여 리포트를 생성합니다.
• ESLint 리포트가 존재할 경우, 이를 읽어 GitHub 이슈에 코멘트로 남깁니다.
4. job3: 테스트를 실행하고, 커버리지를 측정하여 코멘트에 남긴다.
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: latest
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: run test
id: run-tests
continue-on-error: true
run: |
pnpm install
pnpm -F assignment-6 test:coverage
- name: Report test success with coverage
if: steps.run-tests.outcome == 'success'
uses: actions/github-script@v6
with:
github-token: ${{secrets.TOKEN_FOR_CI}}
script: |
const fs = require('fs')
const coverageReport = fs.readFileSync('./packages/assignment-6/.coverage/coverage-summary.json', 'utf8')
const coverage = JSON.parse(coverageReport)
const totalCoverage = coverage.total.lines.pct
const branchCoverage = coverage.total.branches.pct
const functionCoverage = coverage.total.functions.pct
const statementCoverage = coverage.total.statements.pct
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 테스트 성공 ✅
### 커버리지 결과
- 라인 커버리지: ${totalCoverage}%
- 브랜치 커버리지: ${branchCoverage}%
- 함수 커버리지: ${functionCoverage}%
- 구문 커버리지: ${statementCoverage}%`
})
- name: Report test failure
if: steps.run-tests.outcome == 'failure'
uses: actions/github-script@v6
with:
github-token: ${{secrets.TOKEN_FOR_CI}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 테스트 실패 ❌
테스트가 실패하여 커버리지 정보를 생성할 수 없습니다.
자세한 오류 내용은 CI 로그를 확인해주세요.`
})
- name: Exit with test result
if: steps.run-tests.outcome == 'failure'
run: exit 1
요구사항 구현:
- pnpm install 명령어로 의존성을 설치하고, pnpm -F assignment-6 test:coverage로 테스트를 실행하여 커버리지를 측정합니다.
- 테스트 성공 시 커버리지 결과를 GitHub 이슈에 코멘트로 남기고, 실패 시 실패 메시지를 코멘트로 남깁니다.
5. job4: lighthouse ci 를 실행하고, 실행 결과를 코멘트에 남긴다.
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: latest
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: run lhci
continue-on-error: true
run: |
pnpm install
pnpm -F assignment-6 build
pnpm -F assignment-6 lhci
- uses: actions/github-script@v6
with:
github-token: ${{secrets.TOKEN_FOR_CI}}
script: |
const fs = require('fs');
const path = require('path');
const lhciDir = './packages/assignment-6/.lighthouseci';
const jsonReports = fs.readdirSync(lhciDir).filter(f => f.endsWith('.json'));
const latestReport = jsonReports.sort().reverse()[0];
const reportPath = path.join(lhciDir, latestReport);
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
const scores = {
performance: report.categories.performance.score * 100,
accessibility: report.categories.accessibility.score * 100,
'best-practices': report.categories['best-practices'].score * 100,
seo: report.categories.seo.score * 100
};
const formatScore = (score) => `${score.toFixed(0)}%`;
const body = `## Lighthouse 성능 측정 결과
| 카테고리 | 점수 |
|----------|------|
| Performance | ${formatScore(scores.performance)} |
| Accessibility | ${formatScore(scores.accessibility)} |
| Best Practices | ${formatScore(scores['best-practices'])} |
| SEO | ${formatScore(scores.seo)} |`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
요구사항 구현:
• pnpm install 명령어로 의존성을 설치하고, pnpm -F assignment-6 build로 프로젝트를 빌드합니다.
• pnpm -F assignment-6 lhci로 Lighthouse CI를 실행하고, 결과를 GitHub 이슈에 코멘트로 남깁니다.
6. job5: PR이 open될 때만 실행되고, 팀원 중 한 명을 랜덤으로 선정하여 리뷰어를 지정한 다음에 코멘트에 멘션하여 올린다. 실제로 PR에 리뷰어로 지정도 되어야한다.
assign_reviewer:
runs-on: ubuntu-latest
if: github.event.action == 'opened'
steps:
- name: Assign reviewer
uses: actions/github-script@v6
with:
github-token: ${{secrets.TOKEN_FOR_CI}}
script: |
const reviewers = ['junilhwang']
const selectedReviewer = reviewers.sort(() => 0.5 - Math.random()).pop();
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `@${selectedReviewer} 님, 리뷰를 부탁드립니다.`
})
요구사항 구현:
• PR이 열릴 때 실행되며, 팀원 중 한 명을 랜덤으로 선정하여 리뷰어로 지정합니다.
• 선정된 리뷰어에게 멘션하는 코멘트를 GitHub 이슈에 남기고, 실제로 PR의 리뷰어로 지정합니다.
[요구사항2 - package.json 작성]
// package.json
{
"name": "assignment-6",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"start": "vite",
"test": "vitest run",
"test:coverage": "vitest run --coverage",
"test:ui": "vitest --ui",
"tsc": "tsc --noEmit",
"build": "tsc -b && vite build",
"preview": "vite preview --port 4173",
"lhci": "lhci autorun",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:report": "eslint . --ext ts,tsx -o eslint-report"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.4.5",
"@testing-library/react": "^15.0.7",
"@testing-library/user-event": "^14.5.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^7.13.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"@vitest/coverage-v8": "^2.0.3",
"@vitest/ui": "^1.6.0",
"@lhci/cli": "^0.14.0",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"typescript": "^5.2.2",
"vite": "^5.3.1",
"vitest": "^2.0.2"
}
}
// vite.config.js
import { defineConfig as defineTestConfig, mergeConfig } from 'vitest/config';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
export default mergeConfig(
defineConfig({
plugins: [react()],
}),
defineTestConfig({
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/setupTests.ts',
coverage: {
reportsDirectory: "./.coverage",
reporter: ['lcov', 'json', 'json-summary']
},
},
})
)
6주차 후기
솔직히 말하자면 ... 어렵다기보다는 시간이 없어서 도망가고 포기하고 싶었습니다. 😹
모든 걸 잘 해내고 싶은데, 어느 것 하나 중간 이상을 못한다는 생각이 들다 보니 자신에게 화가 많이 났던 것 같아요.
마음이 조급하니까 제대로 공부하지 않고 스크립트를 작성했고, build는 안되지, 코멘트도 안 달리는 이런 상황에서
시간만 허비하고 있다는 생각이 들 때쯤,
pr을 여러 번 열고 닫으며 시도한 끝에 안 돌아가던 ci도 결국 돌아가고, 그 과정에서 코멘트도 101개까지 늘어났어요 (ㅋㅋ)
추가로 main과 싱크 맞추다 1주차 과제의 빌드 에러 난 것도 수정했습니다. 도전하다보니 GitHub Action에 대해 점점 파악이 됐어요! (과제 제출 마지막 날 자신감 급 상승!)
[두고 두고 기억에 남을 기특한 나에 대한 기억]
멘탈 잘 잡고 각성한 후, 회사에선 반응형 리팩토링 마무리하고 11시 퇴근. 집에서는 새벽 4시 반까지 과제 모두 끝내고 제출한 다음 날 아침 9시 출근. 그 다음 날도 기능 마저 붙이며 남은 할 일까지 마무리하고 집에 간 일.
왜, 어린 시절 수학 점수보다는 시험공부하며 밤을 새웠던 기억, 열심히 하며 느껴본 성취감이 더 중요하다고 하잖아요. 이번 주가 성과와 상관없이 저에게 뭐든 할 수 있다는 자신감을 채워준 주차였어요. 어떠한 상황에 마주해도 나는 할 수 있다 !!!
6주차 회고
두 달 지났는데 아직도 제가 어려운 일은 맡을 수 없다는 안일한 생각을 가졌던 것 같습니다.
이제는 저의 일도 쉬운 수준에 머무를 수 없겠죠!
지금 프로젝트는 고민의 여지가 아주 많아서 정신 똑바로 차리고 일정을 더 빠듯하게 잡아야겠습니다.
피그마를 보고 개발 명세를 작성한 뒤 개발하되, 이 과정은 시간을 정해두고 너무 오랜 시간 할애하지 않도록 하려고 합니다.
이틀 동안 코드를 짜고 갈아엎어보니 전혀 .. 아까운 시간이 아니었어요.
또 티켓을 크게 받았어도 스스로 잘 쪼개서 처리해야 한다는 생각이 절실히 들었습니다.
할당받은 티켓이 작업 순서에 맞는지 검증하는 것까지도 저의 일이라는 것을요!
CSS 속성은 어느 정도 자주 쓰는 건 다 외운 것 같은데, 라이브러리 (Ant Design) useForm이 어떻게 동작하는지 잘 알지 못해서 디버깅이 좀 걸리는 것 같아요. 그동안 너무 길어진다 싶으면 사수님한테 물어보는 방법을 선택했지만, 이번 주말에 이 부분을 깊게 공부해서 폼 관련 디버깅 시간을 크게 단축해보겠습니다-
폼 보다도 퍼블리싱이 진짜 큰 문제인데, 특히 반응형 레이아웃 .. 새로운 페이지를 만들 때 작업순서가 뒤죽박죽이라 나중에 덜어내는 시간이 이젠 아깝더라고요. 많은 구현이 작업 시간을 단축시키긴 하겠지만 더 좋은 방법은 없을지 요즘 고민이 듭니다. 일단 퍼블리싱은 거의 다 끝냈으니 백오피스 들어가기 전 주말에 점검해보기로 하고! 일단 하나씩 해결을 해보죠 .. 👊🏻👊🏻
이렇게 정리해보니, 이번 주는 저에게 많은 도전과 성장이 있었던 한 주였네요!
앞으로도 자신감 가지고 파이팅 해보겠습니다 ~~
'항해플러스 프론트엔드 과정' 카테고리의 다른 글
[항해플러스 프론트엔드 2기] 과제만 매주 제출하자고 다짐했던 사람의 10주 회고_정말 힘들었나요_네 (2) | 2024.08.31 |
---|---|
[항해플러스 프론트엔드 2기] 7,8주차 후기 - 테스트코드,TDD (0) | 2024.08.09 |
[항해플러스 프론트엔드 2기] 중간점검, 솔직 후기! 과연 정말 실력이 늘었는지? (0) | 2024.07.22 |
[항해플러스 프론트엔드 2기] 5주차 후기 - 디자인 패턴 (0) | 2024.07.22 |
[항해플러스 프론트엔드 2기] 4주차 후기 - 클린코드 (0) | 2024.07.16 |