본문으로 건너뛰기

품질 관리 가이드

1. 코드 품질 관리

1.1 ESLint 설정

.eslintrc.json 파일 구성:

{
"extends": [
"plugin:@nx/typescript",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"rules": {
"@typescript-eslint/explicit-function-return-type": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": "error",
"max-len": ["error", { "code": 120 }],
"no-console": "warn"
}
}

1.2 Prettier 설정

.prettierrc 파일 구성:

{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 120,
"tabWidth": 2,
"semi": true,
"bracketSpacing": true,
"arrowParens": "avoid"
}

1.3 코드 스타일 검사

# 전체 프로젝트 린트 검사
nx run-many -t lint

# 특정 프로젝트 린트 검사
nx lint dta-wide-api

# 자동 수정 가능한 문제 해결
nx lint dta-wide-api --fix

2. 테스트 관리

2.1 단위 테스트

// 테스트 파일 명명 규칙: *.spec.ts
describe('UserService', () => {
let service: UserService;
let repository: MockType<UserRepository>;

beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
UserService,
{
provide: UserRepository,
useFactory: repositoryMockFactory,
},
],
}).compile();

service = module.get(UserService);
repository = module.get(UserRepository);
});

it('should be defined', () => {
expect(service).toBeDefined();
});

// 각 메서드별 테스트 케이스 작성
});

2.2 통합 테스트

// 테스트 파일 명명 규칙: *.e2e-spec.ts
describe('UserController (e2e)', () => {
let app: INestApplication;

beforeAll(async () => {
const moduleFixture = await Test.createTestingModule({
imports: [AppModule],
}).compile();

app = moduleFixture.createNestApplication();
await app.init();
});

afterAll(async () => {
await app.close();
});

it('/users (GET)', () => {
return request(app.getHttpServer())
.get('/users')
.expect(200)
.expect('Content-Type', /json/);
});
});

2.3 테스트 실행

# 전체 테스트 실행
nx run-many -t test

# 특정 프로젝트 테스트
nx test dta-wide-api

# 특정 파일만 테스트
nx test dta-wide-api --test-file=apps/dta-wide-api/src/app/user/user.service.spec.ts

# 테스트 커버리지 확인
nx test dta-wide-api --coverage

3. 성능 모니터링

3.1 API 응답 시간 모니터링

// libs/core/common/src/lib/interceptors/performance.interceptor.ts
@Injectable()
export class PerformanceInterceptor implements NestInterceptor {
constructor(private readonly logger: LoggerService) {}

intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const start = Date.now();
const request = context.switchToHttp().getRequest();

return next.handle().pipe(
tap(() => {
const duration = Date.now() - start;
this.logger.log(
`${request.method} ${request.url} took ${duration}ms`,
);
}),
);
}
}

3.2 데이터베이스 쿼리 모니터링

// libs/core/database/src/lib/core-database.module.ts
TypeOrmModule.forRootAsync({
useFactory: (configService: ConfigService) => ({
logging: ['query', 'error'],
maxQueryExecutionTime: 1000, // 1초 이상 걸리는 쿼리 로깅
}),
})

4. 보안 검사

4.1 의존성 취약점 검사

# npm audit 실행
npm audit

# yarn audit 실행
yarn audit

# 자동 수정 가능한 취약점 해결
yarn audit fix

4.2 보안 헤더 설정

// apps/dta-wide-api/src/main.ts
import helmet from 'helmet';

async function bootstrap() {
const app = await NestFactory.create(AppModule);

// 보안 헤더 설정
app.use(helmet());

// CORS 설정
app.enableCors({
origin: configService.get('CORS_ORIGINS'),
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
credentials: true,
});

await app.listen(3000);
}

5. 로깅 및 모니터링

5.1 로깅 설정

// libs/core/common/src/lib/services/logger.service.ts
@Injectable()
export class LoggerService implements LoggerService {
private logger: winston.Logger;

constructor(private configService: ConfigService) {
this.logger = winston.createLogger({
level: configService.get('LOG_LEVEL', 'info'),
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json(),
),
transports: [
new winston.transports.Console(),
new winston.transports.File({
filename: 'logs/error.log',
level: 'error',
}),
new winston.transports.File({
filename: 'logs/combined.log',
}),
],
});
}
}

5.2 에러 추적

// libs/core/common/src/lib/filters/all-exceptions.filter.ts
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
constructor(private readonly logger: LoggerService) {}

catch(exception: unknown, host: ArgumentsHost): void {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;

this.logger.error(
`Error processing request: ${request.method} ${request.url}`,
exception instanceof Error ? exception.stack : '',
);

response.status(status).json({
statusCode: status,
timestamp: Date.now(),
path: request.url,
message: exception instanceof Error ? exception.message : 'Internal server error',
});
}
}

6. 코드 리뷰

코드 리뷰 프로세스와 가이드라인에 대한 자세한 내용은 코드 리뷰 가이드라인을 참조하세요.

7. 지속적 통합 (CI)

7.1 CI 파이프라인 구성

# .github/workflows/ci.yml
name: CI

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '18'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Lint
run: nx run-many -t lint

- name: Test
run: nx run-many -t test --coverage

- name: Build
run: nx run-many -t build

변경 이력

버전날짜작성자변경 내용
0.1.02025-03-24bok@weltcorp.com최초 작성