43/ 50
+ 키보드·스크린리더 접근성까지 잘 보완했다.
- 위치 강제 변경과 SSR 안전성 설명이 부정확하다.
디렉티브 설명, 유형, 셀렉터, 입력값, 호스트 요소 동작을 넣으면 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는 간결하나 배경 복원과 생명주기 처리가 약하다.
+ 키보드·스크린리더 접근성까지 잘 보완했다.
- 위치 강제 변경과 SSR 안전성 설명이 부정확하다.
+ 필수 구현을 간결하고 쉽게 제시했다.
- 기존 배경을 잃고 파괴 시 타이머 정리가 없다.
+ 요구 기능과 사용법을 빠짐없이 구현했다.
- 반복 클릭 시 툴팁 문구까지 복사될 수 있다.
| 기준 | ChatGPT | Claude | Gemini | 앞선 모델 |
|---|---|---|---|---|
| 지시 준수 | 9 | 10 | 10 | 동점 |
| 정확성 | 6 | 7 | 7 | 동점 |
| 구체성 | 9 | 9 | 9 | 동점 |
| 구성·가독성 | 8 | 9 | 9 | 동점 |
| 분량 적정성 | 9 | 8 | 6 | ChatGPT +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 시 텍스트 복사 후 잠깐 '복사됨!' 툴팁 표시
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 게임 개발 프롬프트 |