들어가며

최근 여러가지 AI 툴 및 Agent 를 이용한 개발 생산성 향상 및 자동화 열풍이 뜨겁다.

어느 누군가는 이에 대해 낙관하고 또 누군가는 비관적으로 바라본다. 나는 일부는 낙관적으로 바라보고 일부는 비관적으로 바라본다.

내가 사용중인 AI 툴과 개발 방식을 소개하며 왜 그런지 이유를 작성하겠다.

일단 내가 선택한 AI 개발 툴은 Cursor 이다. 먼저 몇 가지 근거 자료를 보도록 하겠다.

첫번쨰로 많이 사용되는 AI 서비스들의 안정성 현황이다.(status page 기준)

AI 서비스 안정성 현황 (2025년 10월 31일 ~ 11월 6일 기준)

AI 툴을 선택할 때 중요한 요소 중 하나는 서비스의 안정성이다. 최근 일주일간 주요 AI 서비스들의 상태를 확인해보았다.

OpenAI 서비스 상태

OpenAI Status Page 기준으로 지난 일주일간의 가동률은 다음과 같다:

  • ChatGPT: 99.21% uptime (약 0.79% degraded)
  • APIs: 99.27% uptime (약 0.73% degraded)
  • Sora: 99.93% uptime (약 0.07% degraded)

현재 진행 중인 이슈로는 ChatGPT Memory 관련 문제가 있으며, 일부 사용자의 메모리가 부분적으로 복구된 상태이다.

Claude 서비스 상태

Claude Status Page 기준으로 지난 90일간의 가동률은 다음과 같으며, 최근 일주일간도 유사한 수준을 유지한 것으로 보인다:

  • claude.ai: 99.71% uptime (약 0.29% degraded)
  • platform.claude.com: 99.84% uptime (약 0.16% degraded)
  • Claude API: 99.81% uptime (약 0.19% degraded)
  • Claude Code: 99.79% uptime (약 0.21% degraded)

최근 일주일간 발생한 주요 인시던트:

  • 10월 27일: Claude 4.5 Sonnet 요청 오류 증가
  • 10월 28일: Claude 4.5 Haiku 요청 오류 증가, claude.ai 파일 업로드 오류
  • 10월 29일: claude.ai 지연 시간 증가
  • 10월 31일: claude.ai 오류 증가, Claude 4.1 Opus 및 Claude 4 Sonnet 요청 오류 증가
  • 11월 1일: Claude 4 Sonnet 요청 오류 증가
  • 11월 4-5일: Haiku 4.5 출력 품질 저하, claude.ai/code 오류 증가

Cursor 서비스 상태

Cursor Status Page 기준으로 지난 90일간의 가동률은 다음과 같으며, 최근 일주일간도 유사한 수준을 유지한 것으로 보인다:

주요 서비스:

  • Cursor App: 99.99% uptime (약 0.01% degraded)
  • Chat - Agent & Custom Modes: 99.98% uptime (약 0.02% degraded)
  • Tab: 99.99% uptime (약 0.01% degraded)
  • Codebase Indexing: 99.99% uptime (약 0.01% degraded)
  • Background Agent: 99.88% uptime (약 0.12% degraded)
  • Infrastructure: 99.88% uptime (약 0.12% degraded)

기타 서비스:

  • Extension Marketplace: 100.0% uptime
  • GitHub Integrations: 100.0% uptime
  • PR Indexing: 100.0% uptime
  • BugBot: 100.0% uptime
  • Website: 99.99% uptime (약 0.01% degraded)
  • User Dashboard: 99.99% uptime (약 0.01% degraded)

최근 일주일간 발생한 주요 인시던트:

  • 10월 27일: Significant Service Degradation - 로그인, AI 채팅, Cloud agents 등 핵심 기능에 심각한 서비스 중단 발생 (18:21 UTC ~ 22:32 UTC, 약 4시간 11분)
  • 10월 29일: Service Degradation - Composer 1 모델의 간헐적 서비스 저하 (19:45 UTC ~ 19:54 UTC, 약 9분)
  • 10월 29일: Service Degradation - 서비스 저하 발생 (01:50 UTC ~ 02:33 UTC, 약 43분)
  • 11월 6일: Service Degradation - 서비스 저하 발생 (06:24 UTC ~ 06:44 UTC, 약 20분)

분석 결과

일주일 기준으로 보면:

  • OpenAI: 평균적으로 약 0.73~0.79% 정도의 서비스 저하 경험
  • Claude: 평균적으로 약 0.19~0.29% 정도의 서비스 저하 경험
  • Cursor: 평균적으로 약 0.01~0.12% 정도의 서비스 저하 경험 (주요 서비스 기준)

세 서비스 중 Cursor가 가장 높은 가동률을 보여주고 있으며, 대부분의 핵심 서비스가 99.99% 이상의 가동률을 유지하고 있다. 물론 Cursor의 경우 자체 모델의 경우는(Composer등) 다른 모델과 비슷한 경향을 보이나 주요 모델에 이슈 있을 때 바꿔 쓰기가 편하다. 다만 10월 27일 발생한 약 4시간 11분간의 Significant Service Degradation은 개발 작업에 상당한 영향을 줄 수 있는 수준이었다.

실제 개발 작업 중에는 이러한 짧은 다운타임이나 degraded 상태도 작업 흐름에 영향을 줄 수 있으므로, 여러 AI 툴을 병행 사용하거나 로컬에서 실행 가능한 대안을 고려하는 것이 좋다.

Cursor Rules 적용 및 설명

Cursor를 사용하면서 가장 유용한 기능 중 하나는 .cursor/rules 디렉토리 아래에 규칙 파일을 분리하여 관리하는 것이다. 각 규칙을 number-name-rules.mdc 형식으로 파일을 나누어 관리하면 규칙의 목적과 범위를 명확히 할 수 있고, 필요에 따라 특정 규칙만 활성화하거나 비활성화할 수 있다.

이 파일들을 통해 AI가 코드를 생성하거나 수정할 때 프로젝트의 컨벤션, 아키텍처 패턴, 코딩 스타일 등을 일관되게 유지할 수 있다.

실제 NestJS API 개발 프로젝트에서 적용한 6개의 Rule들과 그 이유를 설명하겠다.

Rule 1: Base Rules (00-base-rules.mdc)

가장 기본이 되는 규칙으로, 모든 파일에 항상 적용되는 규칙이다. 이 규칙의 핵심은 다음과 같다:

  • 기존 코드는 절대 삭제하지 않는다: AI가 코드를 생성하거나 수정할 때 기존 코드를 삭제하는 것은 위험하다. 기존 코드의 의도나 동작을 완전히 이해하지 못한 상태에서 삭제하면 예상치 못한 버그가 발생할 수 있다.
  • 모든 새로 생성되는 코드는 기존 코드와 분리하여 생성한다: 기존 코드를 수정하는 대신 새로운 파일이나 함수로 분리하여 생성하면, 기존 동작을 보장하면서 새로운 기능을 추가할 수 있다.
  • src 디렉토리 아래의 모든 코드는 NestJS 프레임워크를 염두에 두고 작성한다: NestJS의 컨벤션과 패턴을 따르도록 명시하여 일관된 코드베이스를 유지한다.

이 규칙을 적용한 이유는 AI가 코드를 생성할 때 실수로 기존 코드를 손상시키는 것을 방지하고, 코드 리뷰와 테스트를 용이하게 하기 위함이다.

Rule 2: Handler Directory Rules (01-handler-rules.mdc)

NestJS 프로젝트의 핵심 구조를 정의하는 규칙이다. 모든 NestJS 리소스(controllers, services, modules)를 src/handler/ 디렉토리 아래에 구현하도록 강제한다.

주요 특징:

  • 각 기능은 handler/ 아래에 자체 서브디렉토리를 가진다
  • 표준 NestJS 모듈 구조를 따르며, DTO, Entities, Types, Interfaces, Constants, Responses 등을 체계적으로 관리한다
  • Constants와 Responses 디렉토리는 세부적인 네이밍 규칙을 따르도록 정의되어 있다
  • kebab-case를 사용하여 일관된 파일명을 유지한다

이 규칙을 적용한 이유는 프로젝트의 구조를 명확하게 하고, 새로운 기능을 추가할 때 어디에 무엇을 작성해야 할지 AI가 자동으로 판단할 수 있도록 하기 위함이다. 또한 팀원들이 프로젝트 구조를 빠르게 이해할 수 있도록 도와준다.

Rule 3: Controller Rules (02-src-controllers.mdc)

Controller 개발 시 따라야 할 규칙을 정의한다. RESTful API 설계 원칙을 따르고, 적절한 HTTP 메서드 데코레이터를 사용하도록 강제한다.

주요 특징:

  • Controller 클래스명은 Controller 접미사를 사용한다
  • 파일명은 kebab-case.controller.ts 형식을 따른다
  • DTO 클래스를 사용하여 요청 데이터를 검증한다
  • 일관된 응답 형식을 유지한다
  • 의존성 주입은 생성자를 통해 이루어진다

예시 코드에서는 plainToInstance를 사용하여 응답을 변환하는 패턴을 보여준다. 이는 엔티티의 모든 필드가 노출되는 것을 방지하고, 명시적으로 @Expose() 데코레이터가 있는 필드만 반환하도록 보장한다.

이 규칙을 적용한 이유는 API의 일관성을 유지하고, 보안상 민감한 정보가 실수로 노출되는 것을 방지하기 위함이다.

Rule 4: Source Code Rules (03-src-rules.mdc)

소스 코드 전반에 적용되는 코딩 컨벤션과 구조 규칙을 정의한다.

주요 특징:

  • 네이밍 컨벤션: PascalCase (클래스), camelCase (함수/변수), UPPER_SNAKE_CASE (상수)
  • 인터페이스는 I 접두사 없이 PascalCase를 사용한다
  • JSDoc 주석을 통한 문서화
  • async/await 패턴 사용
  • 명시적인 에러 처리
  • NestJS 특화 규칙 (데코레이터 사용, 의존성 주입 등)

이 규칙을 적용한 이유는 코드의 가독성을 높이고, 팀원 간의 코드 스타일을 통일하여 유지보수성을 향상시키기 위함이다. 특히 인터페이스에 I 접두사를 사용하지 않는 것은 TypeScript 커뮤니티의 모범 사례를 따르는 것이다.

Rule 5: DTO Rules (04-src-dto.mdc)

DTO(Data Transfer Object) 개발 규칙을 정의한다. 요청/응답 데이터의 구조와 검증을 일관되게 관리한다.

주요 특징:

  • DTO 클래스명은 목적에 따라 접미사를 사용한다 (Create, Update, Response 등)
  • Response DTO는 .response.ts 확장자를 사용하고 responses/ 디렉토리에 위치한다
  • class-validator 데코레이터를 사용한 검증
  • @Expose() 데코레이터를 사용한 직렬화 제어
  • @ApiProperty() 데코레이터를 사용한 Swagger 문서화

Response DTO의 경우 @Expose() 데코레이터를 필수로 사용하도록 하여, 엔티티의 모든 필드가 자동으로 노출되는 것을 방지한다. 또한 Swagger 문서화를 위한 @ApiProperty() 데코레이터도 필수로 사용하도록 하여 API 문서의 품질을 보장한다.

이 규칙을 적용한 이유는 API 응답의 일관성을 유지하고, 보안과 문서화를 동시에 해결하기 위함이다.

Rule 6: Service Rules (05-src-services.mdc)

Service 개발 규칙을 정의한다. Service는 비즈니스 로직 서비스와 엔티티 조작 서비스로 구분된다.

주요 특징:

  • 비즈니스 로직 서비스: 복잡한 비즈니스 로직과 오케스트레이션을 처리한다
  • 엔티티 조작 서비스: EntityServiceBase<T>를 확장하여 TypeORM 엔티티 작업을 표준화한다
  • 모든 의존성은 생성자를 통해 주입되며 private readonly로 선언한다
  • 비즈니스 로직 오류는 커스텀 예외를 던진다
  • async/await 패턴을 사용한다

엔티티 조작 서비스의 경우 EntityServiceBase를 확장하여 CRUD 작업을 표준화하고, 트랜잭션 지원을 포함한다. 또한 모든 새로운 엔티티 조작 서비스는 entityServicesProviders에 등록하도록 강제하여 일관된 의존성 관리를 보장한다.

이 규칙을 적용한 이유는 데이터베이스 작업의 일관성을 유지하고, 트랜잭션 처리를 용이하게 하며, 코드 재사용성을 높이기 위함이다.

트랜잭션 관리 방식

이 프로젝트에서는 TypeORM의 @Transactional() 데코레이터나 @InjectDataSource()를 통한 트랜잭션 라이브러리를 사용하지 않고, 직접 manager 래퍼 객체를 통해 트랜잭션을 관리했다.

NoSQL(MongoDB 등) 및 기타 저장소들과의 일관성을 맞추기 위해서이다. RDBMS만을 위한 트랜잭션 데코레이터를 사용하면, 다른 저장소를 사용하는 서비스와의 통합 시 일관된 트랜잭션 관리 패턴을 유지하기 어렵다.

직접 manager 래퍼 객체를 사용함으로써 모든 저장소 타입에 대해 동일한 트랜잭션 관리 인터페이스를 제공할 수 있으며, 향후 다른 저장소로의 마이그레이션이나 멀티 저장소 환경에서도 일관된 코드 구조를 유지할 수 있다.

Cursor Rules를 작성한 이유

위에서 설명한 6개의 Rule들을 작성하게 된 배경과 이유를 상세히 설명하겠다.

AI 코드 생성의 한계와 해결 방안

AI가 코드를 생성할 때 가장 큰 문제점은 프로젝트의 컨텍스트를 완전히 이해하지 못한다는 것이다. 특히 다음과 같은 상황에서 문제가 발생한다:

  • 기존 코드 삭제: AI가 새로운 기능을 추가하면서 기존 코드를 삭제하거나 수정하여 예상치 못한 버그를 발생시키는 경우
  • 일관성 없는 코드 스타일: 프로젝트의 코딩 컨벤션을 따르지 않고 자유롭게 코드를 생성하는 경우
  • 아키텍처 패턴 위반: 프로젝트의 구조와 패턴을 무시하고 다른 방식으로 코드를 작성하는 경우
  • 보안 취약점: 민감한 정보가 노출되거나 적절한 검증 없이 데이터를 처리하는 경우

이러한 문제들을 완화하기(삭제하지 말라는 것도 무시될 수 있다.) 위해 Cursor Rules를 작성했다. Rule을 통해 AI에게 프로젝트의 컨텍스트, 구조, 컨벤션을 명확하게 전달함으로써 일관되고 안전한 코드를 생성하도록 유도할 수 있다.

프로젝트 구조의 명확화

대규모 프로젝트에서는 코드의 위치와 구조가 매우 중요하다. 새로운 기능을 추가할 때마다 “어디에 무엇을 작성해야 하는가?”라는 질문에 답해야 한다. 이는 개발자의 인지 부하를 증가시키고, 코드 리뷰와 유지보수를 어렵게 만든다.

Handler Directory Rules를 통해 모든 NestJS 리소스를 src/handler/ 디렉토리 아래에 체계적으로 관리하도록 강제함으로써, AI가 자동으로 올바른 위치에 코드를 생성할 수 있게 했다. Rule을 통해 구조를 명확히 하고, AI가 올바른 위치에 코드를 생성할 수 있도록 하는 것이 현실적인 해결책이다.

코드 품질과 보안 보장

AI가 생성한 코드는 기능적으로는 동작할 수 있지만, 보안이나 품질 측면에서 문제가 있을 수 있다.

Controller Rules와 DTO Rules를 통해 API 응답의 일관성을 유지하고, @Expose() 데코레이터를 필수로 사용하도록 하여 엔티티의 모든 필드가 자동으로 노출되는 것을 방지했다. 또한 Swagger 문서화를 위한 @ApiProperty() 데코레이터를 필수로 사용하도록 하여 API 문서의 품질을 보장한다.

확장성과 유연성 고려

프로젝트는 시간이 지나면서 변경되고 확장된다. 새로운 저장소를 추가하거나, 다른 프레임워크로 마이그레이션하는 경우도 발생할 수 있다.

트랜잭션 관리 방식을 직접 manager 래퍼 객체로 구현한 것처럼, Rule을 통해 확장 가능하고 유연한 구조를 유지하도록 했다. NoSQL과 RDBMS를 모두 지원할 수 있는 구조를 만들고, 향후 다른 저장소로의 마이그레이션이나 멀티 저장소 환경에서도 일관된 코드 구조를 유지할 수 있도록 설계했다.

AI 도구 활용의 극대화

현재 AI의 한계

AI 도구가 많이 발전했지만 Context Window 사이즈의 한계가 존재한다. 이를 극복하기 위한 청킹(Chunking) 및 서머라이징(Summarizing) 기법이 있지만, 이것만으로는 한계가 있다고 생각한다.

지금의 AI는 분명히 한계가 있다. Context Window 사이즈의 제약이 존재하며, MoE(Mixture of Experts)와 같은 아키텍처적인 해결 방법만으로는 결국 사용자인 인간의 모호한 요구사항을 전부 담을 Context라는 건 존재하기 힘들다고 생각된다.

미래의 AI는 현재의 컨텍스트 사이즈 문제 등이 없는 AI가 될 수도 있겠지만(물론 그때는 더 많은 추상화 레이어에 따른 더 큰 사이즈가 필요한 문제들이 발생하겠지만), 개인적으로는 지금의 프론티어 모델들이 인터넷 연결 없이 개인의 휴대용 랩탑에 들어갈 수 있을 정도가 되면 현재 문제라고 생각한 부분들 중 많은 부분이 해결될 수 있다고 생각한다. 하지만 현재는 아니다.

Rule을 통한 극대화 전략

최소한의 그리고 최대한의 구조화된 Context인 예시 코드로 구조 자체에 대해서는 제공하고, 그 외의 시스템 설계 등의 부분은 개발자 본인이 책임지는 형태로 Rule을 설계했다.

Rule을 통해 AI에게 프로젝트의 코드 구조와 패턴을 명확하게 전달함으로써, AI가 구조적인 부분은 올바르게 생성할 수 있도록 했다. 반면 시스템 설계나 비즈니스 로직과 같은 고차원적인 의사결정은 개발자가 직접 담당하도록 하여, AI의 한계를 인정하면서도 효율적으로 활용할 수 있는 균형을 찾았다.

마치며

기본적으로 AI를 활용한 코드 생성은 꽤나 생산성 향상에 도움이 되는 부분이 있다. 단 경험상으로는 백엔드 기준으로 다음과 같은 방식일 때의 이야기다.

  • 일관된 구조: 프로젝트 전체에 걸쳐 일관된 구조와 패턴이 유지되어야 한다.
  • 너무 많은 자율성보다는 패턴 매칭에 가까운 지시: AI에게 너무 많은 자율성을 주기보다는, 기존 패턴에 맞춰 코드를 생성하도록 명확하게 지시하는 것이 효과적이다.

효과적인 AI 활용 순서

  1. 가장 작은 단위의 Entity에 대한 설계가 마무리되었고 상세 스펙 및 문서를 전달한다.

  2. 해당 Entity들의 관계에 대한 서술

  3. 해당 Entity를 조작하는 Repository들에 대한 접근 서비스로 타입한정

  4. 해당 Entity들에 대한 기본적인 생성 DTO 및 조회용 프로젝션 옵션들 및 Response용(모델을 나타내는 문서화된 내용이면 VO 던 DTO 던 상관없음) 객체의 문서화

  5. 3과 4를 이용한 비즈니스 로직 서비스 메서드 작성 요청

  6. 접근제한 관련 Guard 등에 대한 작성

  7. 5와 6을 이용한 Controller API 작성 요청

단계별 활용 효과

3, 4, 5가 되었다면 6 정도는 자연어로 대충 때려 넣어도 예를 들어서 “일반 유저만 접근 가능한 본인 프로필 조회 API 작성해줘”로 문서까지 어느정도 잘 뽑혀 나온다(확인 및 트랜잭션 처리, 캐싱 등은 개발자 판단하에 수정).

그리고 3, 4, 5, 6까지가 잘 이뤄져 있다면 이후 추가하는 1, 2, 3 또한 자연어로 작성해도 얼추 잘 나올 것이다.(DDD 에서 일부 차용해서 Ubiquitous Language 같은게 잘 정의 되어서 일관된 내용으로 사용되고 그 양이 많지 않다면 컨텍스트에 들어가도 좋다고 생각한다.(많으면 개발자가 쪼개서 작업 지시 프롬프트로 넣는게 좋을 듯))

Rule 설계의 균형

Rule이 빈약해 보이지만 너무 상세한 Rule을 작성하다보면 Rule끼리 논리적 모순이 발생한다던가 Rule만으로 컨텍스트가 너무 많이 소비된다던가 그리고 생성형 AI의 창의적(나는 우발적이라고 생각) 코드 작성을 막을 수 있어서 프로젝트 내에서의 뼈대가 되는 기본 규칙들만 추가하는 것이 좀 더 올바른 사용 방식이라고 생각하며 현재는 이렇게 잘 사용하고 있다.

Agent를 활용한 자동화

특히 속성 수정시 문서 수정은 모든 백엔드 개발자라면 극혐할 극한 노동인데 이런 부분은 8개 Agent로 파일별로 나눠서 지시해놓으면 하나 리뷰하면 나머지 작업들이 완료되어 있어서 리뷰만 하면 되서 좋다.

테스트 수정 및 추가도 여러 Agent로 처리하기 좋은 작업이다. 코드 변경에 따라 테스트 케이스를 수정하거나 새로운 테스트를 추가해야 할 때, 여러 Agent로 파일별로 나눠서 작업하면 효율적으로 처리할 수 있다.