AI로 프로젝트 보일러플레이트 만들기: 고정 템플릿과 생성 범위 나누기, 설치 전 의존성 점검

존재하지 않는 패키지, 오래된 패키지, peer 의존성 충돌을 npm install 전에 걸러내는 순서

AI 보일러플레이트와 의존성 점검 썸네일

핵심 요약

  1. 폴더 구조·설정·허용 패키지 목록은 고정하고, 도메인 코드만 AI에 생성시킨다.
  2. 코드 생성 LLM은 존재하지 않는 패키지 이름을 만들 수 있으므로 의존성은 설치 전에 레지스트리에서 확인한다.
  3. 실제로 있는 패키지도 오래 배포가 없으면 peer 의존성이 맞지 않을 수 있다.
  4. --legacy-peer-deps로 충돌을 덮지 말고, min-release-age로 너무 새 버전 설치를 막는 방법을 검토한다.

새 프로젝트의 폴더 구조, 설정 파일, 기본 라우트를 AI 코딩 도구로 만들면 몇 분 만에 초안이 나온다. 이때 가장 조심할 부분은 코드보다 package.json이다. AI가 그럴듯한 이름의 패키지를 지어내거나, 오래전에 관리가 멈춘 패키지를 고르거나, 서로 맞지 않는 버전을 섞는 일이 있다. 이 글은 고정할 부분과 생성시킬 부분을 나누는 기준을 정리하고, 생성된 의존성을 설치 전에 점검하는 방법을 실제 실행 결과로 보여 준다.

고정 템플릿과 AI 생성의 경계

고정(템플릿·규칙 파일)AI에 생성시킬 것
폴더 구조, 실행·테스트 스크립트엔드포인트, 도메인 모델, 검증 스키마
린트·포맷·타입 설정샘플 데이터, 초기 테스트 케이스
허용 패키지 목록과 버전 범위목록 안에서의 패키지 조합
.env.example의 키 이름키를 읽는 설정 코드

핵심은 허용 패키지 목록을 고정 쪽에 두는 것이다. 요청할 때 "아래 목록 밖의 패키지는 추가하지 말고, 필요하면 이유와 함께 제안만 하라"고 적고, 규칙 파일에도 같은 내용을 둔다. 규칙 파일 작성은 Cursor Rules 작성법을 참고한다.

왜 설치 전에 의존성을 확인해야 하나

코드 생성 LLM이 존재하지 않는 패키지 이름을 만들어 내는 현상을 분석한 연구는 16개 모델로 만든 코드 샘플 57만 6천 개를 조사해, 상용 모델은 평균 5.2% 이상, 오픈소스 모델은 평균 21.7%의 패키지 환각 비율을 보였고 서로 다른 환각 패키지 이름이 20만 5천여 개였다고 보고했다. 환각된 이름을 누군가 먼저 등록해 악성 코드를 올리면, npm install이 그 코드를 그대로 받아 설치 스크립트까지 실행할 수 있다. 그래서 확인은 설치 전에 해야 한다.

설치 전 점검 스크립트

아래 스크립트는 패키지를 설치하지 않고 npm 레지스트리 메타데이터만 조회한다. 레지스트리에 없는 패키지, 생성된 지 90일이 안 된 패키지, 주간 다운로드가 1,000회 미만인 패키지, 마지막 배포가 2년을 넘은 패키지를 확인 대상으로 표시한다. 다운로드 수는 npm의 다운로드 수 API를 쓴다.

// 사용법: node check-deps.mjs package.json
// AI가 만든 package.json의 의존성이 npm 레지스트리에 실제로 있는지, 너무 최근에 만들어졌거나
// 다운로드가 거의 없는 패키지는 아닌지 설치 전에 확인한다(설치하지 않고 메타데이터만 조회).
import { readFileSync } from 'node:fs';

const pkg = JSON.parse(readFileSync(process.argv[2], 'utf8'));
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
const DAY = 864e5;

let problems = 0;
for (const name of Object.keys(deps)) {
  const res = await fetch(`https://registry.npmjs.org/${name.replace('/', '%2F')}`, { signal: AbortSignal.timeout(10000) });
  if (res.status === 404) { problems++; console.log(`없음   ${name} — 레지스트리에 존재하지 않음 (환각 의심)`); continue; }
  const meta = await res.json();
  const ageDays = Math.floor((Date.now() - new Date(meta.time.created)) / DAY);
  const dl = await fetch(`https://api.npmjs.org/downloads/point/last-week/${name}`).then((r) => r.json()).catch(() => ({}));
  const weekly = dl.downloads ?? 0;
  const latest = meta['dist-tags']?.latest;
  const staleDays = Math.floor((Date.now() - new Date(meta.time[latest])) / DAY);
  // 새로 만들어졌거나(이름 선점 의심), 거의 안 쓰이거나, 2년 넘게 배포가 없는 패키지는 확인 대상으로 둔다.
  const warn = ageDays < 90 || weekly < 1000 || staleDays > 730;
  if (warn) problems++;
  console.log(`${warn ? '확인' : 'OK  '}   ${name}@${latest} — 생성 ${ageDays}일 전, 마지막 배포 ${staleDays}일 전, 주간 다운로드 ${weekly.toLocaleString()}`);
}
console.log(problems ? `\n확인 필요 ${problems}건 — 설치 전에 공식 문서·저장소를 확인하세요.` : '\n모든 의존성 확인');
process.exitCode = problems ? 1 : 0;

점검 대상은 AI가 만들어 낸 것처럼 꾸민 예시 package.json이다. express-zod-api-validator-middleware는 그럴듯하게 지은 이름이고, 나머지는 실제 패키지다.

{
  "name": "orders-api",
  "private": true,
  "type": "module",
  "dependencies": {
    "express": "^5.1.0",
    "zod": "^4.0.0",
    "zod-express-middleware": "^1.4.0",
    "express-zod-api-validator-middleware": "^2.0.0"
  },
  "devDependencies": {
    "vitest": "^3.0.0"
  }
}
$ node check-deps.mjs package.json
OK     [email protected] — 생성 5760일 전, 마지막 배포 309일 전, 주간 다운로드 169,483,150
OK     [email protected] — 생성 2404일 전, 마지막 배포 23일 전, 주간 다운로드 387,371,526
확인   [email protected] — 생성 1941일 전, 마지막 배포 1903일 전, 주간 다운로드 48,734
없음   express-zod-api-validator-middleware — 레지스트리에 존재하지 않음 (환각 의심)
OK     [email protected] — 생성 1769일 전, 마지막 배포 7일 전, 주간 다운로드 142,142,023

확인 필요 2건 — 설치 전에 공식 문서·저장소를 확인하세요.

"확인"으로 표시된 패키지를 열어 보면

zod-express-middleware는 실제로 있고 주간 다운로드도 4만 8천 회가 넘지만, 마지막 배포가 약 5년 전이다. 레지스트리에서 1.4.0의 peerDependencies를 확인하면 zod: ^3.2.0, express: ^4.17.1이다. 이 프로젝트는 zod 4와 express 5를 쓰므로 맞지 않는다. 환각 패키지를 뺀 뒤 스크립트를 실행하지 않는 --ignore-scripts로 설치를 시험하면 npm이 충돌을 알려 준다.

$ npm install --dry-run --ignore-scripts --no-audit --no-fund
npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error Found: [email protected]
npm error Could not resolve dependency:
npm error peer express@"^4.17.1" from [email protected]
npm error Fix the upstream dependency conflict, or retry this command with --force or --legacy-peer-deps to accept an incorrect (and potentially broken) dependency resolution.

오류 메시지가 --legacy-peer-deps를 대안으로 보여 주지만, npm 문서는 이 옵션이 peerDependencies 계약을 강제하지 않으므로 권장하지 않는다고 적는다. AI 도구가 설치 오류를 고치려고 이 옵션을 붙이는 제안을 하면 그대로 받지 말고, 패키지 자체를 바꾸거나 직접 구현할지 판단한다. 이 경우 Express 미들웨어 몇 줄로 Zod 검증을 직접 붙이는 편이 의존성 하나를 줄인다.

npm의 min-release-age로 너무 새 버전 막기

npm 문서에 따르면 min-release-age를 설정하면 지정한 일수보다 오래전에 공개된 버전만으로 의존성 트리를 만들고, 맞는 버전이 없으면 오류로 멈춘다. 방금 등록된 악성 패키지나 탈취된 계정이 올린 새 버전을 설치하는 위험을 줄이는 설정이다. 이 글을 쓰는 시점에 7일 전 배포된 vitest 5.0.3을 30일 기준으로 요청하면 설치를 거부한다.

$ npm install --dry-run --ignore-scripts --min-release-age=30   # vitest@^5.0.3
npm error code ETARGET
npm error notarget No matching version found for vitest@^5.0.3 with a date before 2026. 9. 7. PM 11:34:44.

팀 저장소의 .npmrc에 min-release-age=7처럼 두면 모든 설치에 적용된다. 보안 패치처럼 새 버전이 급히 필요할 때 막히는 부작용이 있으므로, 문서의 예외 설정(min-release-age-exclude)과 함께 정한다.

생성부터 첫 커밋까지 순서

  1. 고정 템플릿과 허용 패키지 목록을 요청에 함께 준다.
  2. 생성된 파일 목록과 각 파일의 역할을 먼저 요약하게 한다.
  3. 설치 전에 의존성 점검 스크립트를 실행하고, 없음·확인 항목을 해결한다.
  4. --ignore-scripts로 설치를 시험한 뒤 정상 설치한다.
  5. 린트·타입 검사·테스트가 모두 통과한 상태로 첫 커밋을 만든다. 커밋 전 자동 검사는 ESLint·Prettier·tsc 자동화에서 다룬다.

초보자가 자주 실수하는 포인트

  • AI가 만든 package.json을 확인 없이 바로 npm install 한다.
  • 설치 오류를 --legacy-peer-deps나 --force로 넘긴다.
  • 다운로드 수만 보고 마지막 배포 시점과 peer 의존성을 확인하지 않는다.
  • 허용 패키지 목록 없이 생성을 요청해 매번 다른 라이브러리가 들어온다.

체크리스트

  • 요청에 고정 템플릿과 허용 패키지 목록을 넣었다.
  • 의존성 점검 스크립트에서 없음·확인 항목이 없다.
  • peer 의존성 충돌 없이 --ignore-scripts 설치가 된다.
  • .npmrc의 min-release-age 사용 여부를 정했다.
  • 린트·타입·테스트 통과 후 첫 커밋을 만들었다.

자주 묻는 질문

패키지가 레지스트리에 있으면 안전한가요?

존재는 첫 단계일 뿐입니다. 이 글의 예처럼 존재하더라도 관리가 멈춰 현재 버전과 맞지 않을 수 있고, 최근에 등록된 이름 선점 패키지일 수도 있습니다. 생성 시점, 마지막 배포, 다운로드 수, 저장소 링크를 함께 확인합니다.

npm install --dry-run은 패키지를 실행하나요?

--dry-run은 실제로 설치하지 않고 의존성 트리만 계산합니다. 이 글에서는 혹시 모를 설치 스크립트 실행을 막기 위해 --ignore-scripts도 함께 붙였습니다.

참고 자료 · 검증 기준

위 자료와 내용을 대조한 날짜: . 도구·서비스 정책은 이후 바뀔 수 있으므로 적용 전 공식 문서를 다시 확인하세요.

이 글은 실제 실무 환경 테스트 및 검증된 기술 자료를 바탕으로 작성되었으며, 환경 변화에 따라 지속적으로 갱신됩니다.