☰ 분류

Angular 디렉티브 생성 프롬프트

디렉티브 설명, 유형, 셀렉터, 입력값, 호스트 요소 동작을 넣으면 Angular 17+ standalone 디렉티브 코드와 사용 예시를 생성합니다.

분류개발 › 코딩
태그초안작성개발자코드템플릿
프롬프트 (영어 본문 · 답은 한국어로 옵니다)
You are an expert Angular developer. Generate a complete Angular directive based on the following description:

Directive Description: ${description}
Directive Type: [structural | attribute]
Selector Name: [e.g. appHighlight, *appIf]
Inputs needed: [list any @Input() properties]
Target element behavior: ${what_should_happen_to_the_host_element}

Generate:
1. The full directive TypeScript class with proper decorators
2. Any required imports
3. Host bindings or listeners if needed
4. A usage example in a template
5. A brief explanation of how it works

Use Angular 17+ standalone directive syntax. Follow Angular style guide conventions.

어떤 프롬프트인가

Angular 디렉티브 초안을 빠르게 만들 때 쓰기 좋다. TypeScript 클래스, import, host binding/listener, 템플릿 예시, 간단한 작동 설명을 요구한다.

모델 비교

Claude는 접근성과 구성 면에서 가장 균형적이고, Gemini는 충실하지만 장황하다. ChatGPT는 간결하나 배경 복원과 생명주기 처리가 약하다.

Claude종합 1위
43/ 50

+ 키보드·스크린리더 접근성까지 잘 보완했다.

- 위치 강제 변경과 SSR 안전성 설명이 부정확하다.

ChatGPT
41/ 50

+ 필수 구현을 간결하고 쉽게 제시했다.

- 기존 배경을 잃고 파괴 시 타이머 정리가 없다.

Gemini
41/ 50

+ 요구 기능과 사용법을 빠짐없이 구현했다.

- 반복 클릭 시 툴팁 문구까지 복사될 수 있다.

기준ChatGPTClaudeGemini앞선 모델
지시 준수91010동점
정확성677동점
구체성999동점
구성·가독성899동점
분량 적정성986ChatGPT +13%

gpt-5.6-sol가 모델 이름을 가린 채 1~10점으로 채점했습니다 (2026-09-24). 측정값이 아니라 AI 심사 결과입니다.

답 전문 보기

같은 입력을 세 모델에 넣어 받은 답을 그대로 옮겼습니다. 각 CLI(에이전트 하네스)에서 실행했습니다. ChatGPT·Claude 앱이나 웹에서는 답이 다를 수 있습니다.

넣은 입력
[붙여 넣은 자료]
Directive Description: 요소에 마우스를 올리면 배경색이 부드럽게 하이라이트되고, 클릭하면 해당 요소의 내용을 클립보드에 복사하는 디렉티브
Directive Type: attribute
Selector Name: appCopyHighlight
Inputs needed: highlightColor (string, 기본값 '#fef08a'), copyText (복사할 텍스트, 없으면 innerText 사용)
Target element behavior: hover 시 배경색 트랜지션 적용, click 시 텍스트 복사 후 잠깐 '복사됨!' 툴팁 표시
gpt-5.6-luna (codex CLI · 에이전트 하네스) · 실행일 2026-09-24
import {
  Directive,
  ElementRef,
  HostListener,
  Input,
  Renderer2,
  inject,
} from '@angular/core';

@Directive({
  selector: '[appCopyHighlight]',
  standalone: true,
})
export class CopyHighlightDirective {
  @Input() highlightColor = '#fef08a';
  @Input() copyText?: string;

  private readonly elementRef = inject(ElementRef<HTMLElement>);
  private readonly renderer = inject(Renderer2);

  private tooltip?: HTMLElement;
  private tooltipTimer?: ReturnType<typeof setTimeout>;

  constructor() {
    const element = this.elementRef.nativeElement;

    this.renderer.setStyle(element, 'transition', 'background-color 180ms ease');

    if (getComputedStyle(element).position === 'static') {
      this.renderer.setStyle(element, 'position', 'relative');
    }

    this.renderer.setStyle(element, 'cursor', 'pointer');
  }

  @HostListener('mouseenter')
  onMouseEnter(): void {
    this.renderer.setStyle(
      this.elementRef.nativeElement,
      'background-color',
      this.highlightColor,
    );
  }

  @HostListener('mouseleave')
  onMouseLeave(): void {
    this.renderer.removeStyle(
      this.elementRef.nativeElement,
      'background-color',
    );
  }

  @HostListener('click')
  async onClick(): Promise<void> {
    const text = this.copyText?.trim() || this.elementRef.nativeElement.innerText;

    if (!text.trim()) {
      return;
    }

    try {
      await navigator.clipboard.writeText(text);
      this.showTooltip('복사됨!');
    } catch {
      this.showTooltip('복사 실패');
    }
  }

  private showTooltip(message: string): void {
    this.removeTooltip();

    const tooltip = this.renderer.createElement('span') as HTMLElement;
    this.tooltip = tooltip;

    this.renderer.setProperty(tooltip, 'textContent', message);
    this.renderer.setAttribute(tooltip, 'role', 'status');
    this.renderer.setAttribute(tooltip, 'aria-live', 'polite');

    this.renderer.setStyle(tooltip, 'position', 'absolute');
    this.renderer.setStyle(tooltip, 'top', '100%');
    this.renderer.setStyle(tooltip, 'left', '50%');
    this.renderer.setStyle(tooltip, 'transform', 'translateX(-50%)');
    this.renderer.setStyle(tooltip, 'margin-top', '6px');
    this.renderer.setStyle(tooltip, 'padding', '4px 8px');
    this.renderer.setStyle(tooltip, 'border-radius', '4px');
    this.renderer.setStyle(tooltip, 'background-color', '#1f2937');
    this.renderer.setStyle(tooltip, 'color', '#fff');
    this.renderer.setStyle(tooltip, 'font-size', '12px');
    this.renderer.setStyle(tooltip, 'white-space', 'nowrap');
    this.renderer.setStyle(tooltip, 'z-index', '1000');
    this.renderer.setStyle(tooltip, 'pointer-events', 'none');

    this.renderer.appendChild(this.elementRef.nativeElement, tooltip);

    this.tooltipTimer = setTimeout(() => {
      this.removeTooltip();
    }, 1500);
  }

  private removeTooltip(): void {
    if (this.tooltip) {
      this.renderer.removeChild(
        this.elementRef.nativeElement,
        this.tooltip,
      );
      this.tooltip = undefined;
    }

    if (this.tooltipTimer) {
      clearTimeout(this.tooltipTimer);
      this.tooltipTimer = undefined;
    }
  }
}

사용 예시:

import { Component } from '@angular/core';
import { CopyHighlightDirective } from './copy-highlight.directive';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [CopyHighlightDirective],
  template: `
    <p
      appCopyHighlight
      highlightColor="#bfdbfe"
    >
      이 문장을 클릭하면 복사됩니다.
    </p>

    <button
      appCopyHighlight
      [copyText]="'버튼 클릭으로 복사되는 별도 텍스트'"
      highlightColor="#bbf7d0"
    >
      텍스트 복사
    </button>
  `,
})
export class ExampleComponent {}

마우스를 올리면 background-color가 부드럽게 변경되고, 클릭하면 copyText 값을 클립보드에 복사합니다. copyText가 없으면 호스트 요소의 innerText를 사용하며, 복사 후 1.5초 동안 복사됨! 툴팁을 표시합니다.

같은 분류의 프롬프트

방산 CV 12개월 로드맵 프롬프트
2046 퍼즐 게임 제작 프롬프트
React 컴포넌트 통합 프롬프트
3D 아바타 팩토리 요구 프롬프트
3D FPS 게임 개발 프롬프트