시간 처리를 자동화했는데, 작성자 추적이 부산물로 따라왔습니다
"시간 자동화가 목표였는데 lineage가 따라왔습니다"
PM 도구의 Service 레이어에서 ZonedDateTime.now() 호출이 79곳에 산재해 있었습니다. 노드 저장·수정마다 setUpdatedAt(now())를 수동으로 박는 코드들이었어요.
이걸 SDN(Spring Data Neo4j)의 auditing으로 자동화하기로 했습니다. 목표는 단순했어요. 시간 처리를 중앙화해서 누락 위험을 없애는 것. 79곳을 한 곳에서 관리하면 새 코드 추가 시 메타 필드를 빠뜨릴 위험이 사라집니다.
도입 후 효과를 보니 예상한 가치가 잡혔어요. 25/29 노드의 createdAt/updatedAt이 save 시점에 자동 채움. Service는 시간 처리를 의식하지 않게 됐습니다.
그런데 더 큰 가치가 부산물로 따라왔습니다. 작성자 추적이 자동으로 잡혔어요.
처음 목표는 시간이었는데, 운영해보니 시간보다 lineage(누가 노드를 만들었는지)가 훨씬 더 가치 있었습니다. 이번 글은 그 발견과 일반화 가능한 통찰을 정리한 회고입니다.
SDN auditing — 어노테이션 4종이 데려온 부산물
SDN의 auditing은 어노테이션 4종이 한 묶음으로 동작합니다.
@CreatedDate // 생성 시간
@LastModifiedDate // 수정 시간
@CreatedBy // 생성자
@LastModifiedBy // 수정자처음에는 위 두 개(@CreatedDate, @LastModifiedDate)만 관심이 있었어요. 시간 처리 중앙화가 목표였으니까요.
그런데 아래 두 개(@CreatedBy, @LastModifiedBy)가 함께 따라옵니다. 이 두 어노테이션을 활성화하려면 AuditorAware<String> bean 하나만 추가하면 됐어요.
@Bean
public AuditorAware<String> auditorAware() {
return () -> {
// 요청 컨텍스트에서 accountId 추출
String accountId = getAccountIdFromRequest();
return Optional.of(accountId != null ? accountId : "system");
};
}JwtInterceptor가 요청마다 박아두는 accountId를 참조해서 자동으로 작성자를 채웁니다. 요청 컨텍스트가 없으면(스케줄러·시스템 작업 등) "system"으로 fallback.
여기까지는 그저 "시간 자동화하면서 작성자도 같이 채우는 김에 넣은 것"이었어요. 운영해보고 나서야 이 부산물의 진짜 가치가 보였습니다.
(짧은 트러블슈팅 메모: Spring 기본 DateTimeProvider는 LocalDateTime을 반환해서, 우리 노드의 ZonedDateTime 필드와 변환 mismatch가 났어요. DateTimeProvider 빈을 ZonedDateTime UTC로 명시 등록해서 해결. 프레임워크 기본값이 우리 시스템과 안 맞을 수 있다는 게 한 가지 교훈이었습니다.)
노드를 보면 누가 만들었는지 알 수 있다
자동화 도입 후 노드를 조회하면 이렇게 보입니다.
createdBy = "user-12345" → JWT 인증 사용자가 직접 생성
createdBy = "api-key" → API Key로 외부 시스템이 생성
createdBy = "system" → 스케줄러·내부 작업이 생성호출자 유형이 그대로 메타 필드에 기록되는 거예요. 세 가지 호출 경로가 자동으로 분기됩니다.
이게 처음에는 작은 부산물처럼 보였는데, 운영 중 마주친 상황들에서 그 가치가 드러났습니다.
상황 1: "이 노드 왜 생겼지?"
운영 중에 예상치 못한 노드가 발견되는 경우가 있어요. 이전에는 누가·언제·왜 만들었는지 추적이 어려웠습니다. 로그를 거꾸로 뒤지거나 코드 호출 경로를 추정해야 했어요.
이제는 createdBy 하나만 봐도 답이 나옵니다. "api-key"면 외부 시스템 호출, "system"이면 스케줄러, 특정 user ID면 그 사용자가 직접 만든 것. 30분 걸리던 디버깅이 30초로 줄어들었어요.
상황 2: "이 작업 누가 했어?"
다중 사용자 환경에서 데이터 변경 추적이 필요한 순간이 있습니다. 잘못된 데이터가 들어왔을 때, 누가 마지막으로 수정했는지가 중요해요. updatedBy로 즉시 확인 가능합니다. 별도 감사 로그를 만들 필요 없이 노드 자체가 자기 이력을 들고 있어요.
상황 3: "외부 시스템 트래픽이 어디서 오지?"
createdBy = "api-key"만 카운트해도 외부 시스템이 생성한 노드 비율이 나옵니다. API Key 기반 자동화가 시스템에서 얼마나 차지하는지 측정 가능해졌어요. 이건 운영 가시성 측면에서 중요한 정보였습니다.
부산물의 가치가 본 목표보다 큰 경우
이번 사건이 흥미로웠던 이유는 부산물이 본 목표를 능가했다는 점이에요.
처음 본 목표: 시간 처리 누락 위험 제거
실제로 큰 가치: 호출자 유형 자동 추적 → 디버깅·감사·운영 가시성
두 가치를 정직하게 비교하면 lineage 쪽이 운영에 미치는 영향이 더 컸어요. 시간 누락은 1년에 한두 번 발견되는 위험이지만, "누가 만들었지?"는 운영 중 자주 마주치는 질문입니다.
비슷한 패턴이 다른 인프라 자동화 결정에서도 보였어요.
본 목표 | 부산물 가치 |
|---|---|
시간 처리 자동화 | 작성자 추적 (lineage) |
로그 수집 자동화 | 외부 시스템 가시성 |
캐시 도입 | 호출 패턴 측정 |
인증 미들웨어 | 요청 컨텍스트 자동 전파 |
인프라 자동화는 본 목표 외에 부산물 가치를 함께 가져옵니다. 그리고 운영 중에는 부산물이 본 목표보다 더 자주 활용되는 경우가 있어요. 도입 시점에는 부산물의 가치가 잘 안 보이지만, 운영하면서 드러납니다.

호출자 유형 자동 분기가 만드는 운영 가치
부산물의 가치를 더 깊게 들여다보면 호출자 유형 자동 분기가 핵심이었어요.
세 가지 호출 경로(JWT / API Key / system)를 노드 메타에 자동 기록하는 게 무엇을 가능하게 했을까요.
디버깅에서
예상치 못한 데이터 패턴이 발견됐을 때, createdBy 분포로 원인을 좁힐 수 있습니다.
특정 시점 이후 api-key 비율 급증 → 외부 시스템 변경 의심
system 노드만 이상 → 스케줄러 로직 검토
특정 user ID에서만 패턴 → 그 사용자 행동 점검
별도 모니터링 시스템 없이 노드 자체에 분포 정보가 들어 있는 셈이에요.
감사·신뢰에서
특히 민감한 데이터(개인 정보·결제·인증 등)는 누가 만들었고 누가 마지막으로 수정했는지가 신뢰의 기반입니다. lineage가 없으면 감사 요구가 들어왔을 때 "잘 모르겠다"가 됩니다. 있으면 즉시 답이 나와요.
시스템 진화에서
기능 확장 시 "이 데이터는 누가 쓰고 있나?"가 항상 질문입니다. createdBy / updatedBy 분포를 보면 사용자가 직접 쓰는 데이터인지, 외부 시스템 연동에 활용되는 데이터인지, 스케줄러가 자동 생성하는 데이터인지 즉시 파악 가능해요. 폐기 결정·기능 확장·마이그레이션 의사결정에 직접 도움이 됩니다.

의사결정자가 점검할 4가지
인프라 자동화·메타 필드 관리·운영 가시성을 검토하실 때 점검할 일반 체크리스트입니다.
1. 본 목표 외 부산물 가치를 함께 봅니다
자동화·미들웨어·프레임워크 도입 시 본 목표 하나만 보지 않습니다. "이 도입으로 추가로 무엇이 가능해지는가?"를 함께 점검합니다. 시간 자동화 → 작성자 추적, 인증 미들웨어 → 요청 컨텍스트 전파, 캐시 도입 → 호출 패턴 측정. 부산물이 본 목표보다 운영 가치가 클 때가 있습니다.
2. 호출자 유형 자동 분기를 만듭니다
서비스를 JWT 인증 사용자만 쓰는 게 아닙니다. API Key·스케줄러·외부 시스템·내부 작업이 같은 코드를 호출해요. 메타 필드에 호출자 유형을 자동 기록하면 디버깅·감사·운영 가시성이 동시에 잡힙니다.
3. lineage 부재의 비용을 측정합니다
"이 데이터 누가 만들었지?" 질문이 운영 중 몇 번이나 나오는지 측정해보면 lineage의 가치가 보입니다. 별도 감사 로그를 만들지 않아도 노드 자체가 자기 이력을 들고 있으면 운영 부담이 크게 줄어요.
4. 자동화의 한계를 명확히 합니다
auditing은 라이프사이클 시간(createdAt, updatedAt)과 작성자(createdBy, updatedBy)에만 적용됩니다. 비즈니스 시간(completedAt, answeredAt 등)은 별도 처리예요. 직접 Cypher 실행이나 자동화 어노테이션이 안 걸린 노드는 별도 점검이 필요합니다. 자동화의 적용 경계를 분명히 알아야 안전합니다.
비슷한 발상이 다른 인프라 결정에서도 흐릅니다. 본 목표 외 부산물 가치를 함께 보는 것, 호출자 유형이 운영 가시성에 미치는 영향을 인정하는 것, 자동화의 적용 경계를 명확히 하는 것. 인프라 자동화의 핵심 기준입니다.
마무리
PM 도구의 시간 처리 자동화가 목표였습니다. SDN의 auditing을 도입해서 79곳 산재 ZonedDateTime.now() 호출을 save 시점 자동 채움으로 전환했어요. 그런데 운영해보니 본 목표(시간 자동화)보다 부산물(lineage 자동 확보)이 더 큰 운영 가치를 만들었습니다.
인프라 자동화는 본 목표 외 부산물 가치를 함께 가져온다 — 시간 자동화 → 작성자 추적이 그 예
호출자 유형 자동 분기가 디버깅·감사·운영 가시성을 동시에 만든다 — JWT / API Key / system이 메타에 자동 기록
부산물의 가치는 운영 중에 드러난다 — 도입 시점에는 잘 안 보이지만 운영 시 본 목표를 능가하는 경우가 있음
인프라 자동화·메타 필드 관리·운영 가시성을 검토하신다면, 이번 글의 4가지 체크리스트(부산물 가치 점검 / 호출자 유형 분기 / lineage 부재 비용 측정 / 자동화 한계 명확히)를 한 번 살펴보시길 추천합니다. 자동화 도입 결정에서 본 목표만 보면 진짜 가치를 놓치는 경우가 있었습니다.