| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- IntelliJ
- Flux
- AWS CI/CD 구축하기
- docker
- SQL
- codedeploy error
- Airflow
- codedeploy
- VPN
- aws
- bootstrap
- Python
- PostgreSQL
- 도커
- redis
- openlens
- COALESCE
- JavaScript
- aws cicd
- Spring
- chartjs
- chart.js
- codebuild
- codepipeline
- Jenkins
- Kafka
- Spring Error
- java bigdecimal
- kubeflow
- node
- Today
- Total
Small Asteroid Blog
Claude Code 하네스 엔지니어링 본문
Claude Code를 쓰면서 느낀 불편함
Claude Code로 프로젝트 작업을 하다 보면 이런 상황이 반복된다.
- "DTO는 record로 만들어줘" (3번째 말하는 중)
- "@Autowired 말고 생성자 주입으로 해줘" (또...)
- "Controller에 @Transactional 붙이지 마" (이것도 또)
Claude Code는 세션이 바뀌면 기억이 초기화된다. 그래서 매번 같은 컨벤션을 반복해서 알려줘야 한다. 프로젝트가 커질수록 이 반복이 쌓인다.
이걸 해결하려고 하네스(Harness) 라는 개념을 적용해봤다.
하네스가 뭔데?
한 줄로 요약하면, Claude Code가 동작하는 환경을 세팅하는 것이다.
┌─────────────────────────────────────────┐
│ CLAUDE.md (프로젝트 설명서) │
│ Hooks (코드 수정 시 자동 체크) │
│ Memory (세션 간 기억) │
│ ┌─────────────────────────────────┐ │
│ │ Claude Model (LLM) │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
프롬프트 엔지니어링이 "뭘 물어볼까"의 문제라면, 하네스 엔지니어링은 "어떤 환경에서 일하게 할까"의 문제다. 신규 입사자에게 온보딩 문서 주고, 코드 리뷰 룰 알려주고, 팀 위키 접근권한 주는 것과 비슷하다.
핵심 구성 요소는 3가지다:
| 구성 요소 | 하는 일 |
| CLAUDE.md | 세션 시작 시 자동으로 읽히는 프로젝트 가이드 |
| Hooks | .java 파일 수정할 때마다 컨벤션 규칙을 자동 주입 |
| Memory | "DTO는 record로" 같은 피드백을 다음 세션에도 기억 |
Spring Boot 프로젝트에 적용해보기
1단계: 초기화
claude-harness 레포를 클론하고, 초기화 스크립트를 실행한다.
git clone https://github.com/minseoky/claude-harness.git
./claude-harness/scripts/init-harness.sh /path/to/my-project java
이러면 프로젝트의 .claude/ 폴더에 필요한 파일들이 자동 생성된다.
my-project/.claude/
├── settings.json # Hook 등록
├── convention-rules.txt # Java 컨벤션 규칙
├── compact-preserve.txt # 컨텍스트 압축 시 보존 규칙
└── hooks/
├── convention-check.sh # 코드 수정 시 컨벤션 리마인더
├── post-bash.sh # 빌드 명령 추적
└── pre-compact.sh # 압축 시 보존 규칙 주입
2단계: CLAUDE.md 작성
프로젝트 루트에 CLAUDE.md를 만든다. Claude Code가 세션 시작할 때 이 파일을 자동으로 읽는다.
# OrderService
Spring Boot 3.2 + Java 21 + JPA + PostgreSQL 기반 주문 관리 서비스.
## 디렉토리 구조
controller/ → service/ → repository/ → domain/ 계층 구조.
DTO는 dto/ 패키지에 Java record로 작성.
## 컨벤션
- DI: 생성자 주입만 사용 (@Autowired 필드 주입 금지)
- DTO: Java record 사용
- 트랜잭션: Service 레이어에서만, 읽기 전용은 readOnly=true
- Entity에 @Setter 금지
## 빌드
./gradlew build / ./gradlew test
길게 쓸 필요 없다. 이것만으로도 Claude는 "이 프로젝트에서 DTO는 record로, DI는 생성자 주입으로" 라는 걸 매 세션마다 인지한다.
3단계: 끝. 그냥 쓰면 된다
이제 Claude Code에서 "주문 생성 API 만들어줘"라고 하면, .java 파일을 수정하는 순간 Hook이 발동해서 컨벤션 규칙이 자동 주입된다.
[Convention Check] Java 코드 수정 중:
1. DB 쿼리: PreparedStatement 파라미터 바인딩 (SQL injection 방지)
2. API: @PreAuthorize / SecurityContext 인증·인가 체크 확인
3. 입력 검증: @Valid / @Validated + DTO 검증 어노테이션
4. 예외 처리: 적절한 커스텀 예외 + @ExceptionHandler 매핑
5. 패키지 구조: controller → service → repository 계층 준수
6. 불변성: DTO는 record 또는 final 필드 + Builder 패턴 권장
내가 매번 말하지 않아도 Claude가 알아서 체크한다.
적용 전후 비교
실제로 "주문 생성 API 만들어줘"를 요청했을 때 차이를 보면
Before (하네스 없이)
// DTO를 그냥 class로 만듦
public class CreateOrderRequest {
private Long productId;
private int quantity;
// getter, setter...
}
// @Autowired 필드 주입
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
}
After (하네스 적용)
// record로 생성 + 검증 어노테이션
public record CreateOrderRequest(
@NotNull Long productId,
@Min(1) int quantity
) {}
// 생성자 주입 + @Transactional
@Service
@RequiredArgsConstructor
public class OrderService {
private final OrderRepository orderRepository;
@Transactional
public Order createOrder(Long userId, Long productId, int quantity) {
// ...
}
}
같은 요청인데 결과물의 품질이 다르다. 하네스가 컨벤션을 자동으로 챙겨주기 때문이다.
팀에 맞게 커스터마이즈
생성된 파일들은 전부 텍스트 파일이라 수정이 쉽다.
convention-rules.txt에 팀 규칙 추가:
[Convention Check] Java 코드 수정 중:
1. DB 쿼리: PreparedStatement 파라미터 바인딩
2. QueryDSL: BooleanBuilder 대신 BooleanExpression 메서드 분리
3. 로깅: 비즈니스 로직 진입점에 log.info, 예외 시 log.error
...원하는 규칙 추가
post-bash.sh에서 Gradle 추적 활성화:
# 기본값이 npm/yarn이라 Java 프로젝트에 맞게 변경
CMD_PATTERN="^(\./gradlew|gradle|mvn) "
프리셋 종류
java 말고도 여러 프리셋이 있다.
./scripts/init-harness.sh /path/to/project java # Java 일반
./scripts/init-harness.sh /path/to/project spring # Spring 특화
./scripts/init-harness.sh /path/to/project kotlin # Kotlin
./scripts/init-harness.sh /path/to/project react-native # React Native
./scripts/init-harness.sh /path/to/project python # Python
Spring Boot 프로젝트라면 spring 프리셋도 괜찮다. java보다 @Transactional 범위 관리, 생성자 주입 강제, 테스트 슬라이싱 같은 Spring 특화 규칙이 추가된다.
마무리
하네스 엔지니어링의 핵심은 간단하다. AI에게 매번 같은 말을 반복하는 대신, 환경으로 만들어라.
CLAUDE.md로 프로젝트를 설명하고, Hook으로 컨벤션을 자동 체크하고, Memory로 피드백을 기억시킨다. 초기 세팅에 10~30분 정도 투자하면, 이후 모든 세션에서 일관된 품질의 코드를 받을 수 있다.
특히 팀 프로젝트에서 여러 사람이 Claude Code를 쓸 때, 하네스를 .claude/ 폴더째 커밋해두면 팀원 모두가 같은 환경에서 작업할 수 있다는 점이 좋았다.
'AI' 카테고리의 다른 글
| Datadog MCP 설치 및 운영 환경에서 사용하기 (1) | 2026.03.06 |
|---|---|
| Antigravity 개인적인 사용후기 (0) | 2025.11.27 |
| Serena MCP 사용해 토큰 절약하고 퀄리티 높이기 (0) | 2025.08.16 |
| Langfuse의 Span과 Generation의 관계 (0) | 2025.08.09 |
| 백엔드 개발자를 위한 Claude 꿀팁 (0) | 2025.07.20 |