[Control Tower] Spring AI로 구현한 항공사 사원 가입 자동화 (명함 OCR & 프롬프트 엔지니어링)

2026. 3. 7. 16:14·Projects/Team Projects

🧐 배경: "입사 첫날의 번거로운 회원가입을 1초 만에"

항공사 HR SaaS인 'Control Tower' 프로젝트를 진행하며 가장 신경 쓴 부분 중 하나는 사용자 경험(UX)입니다. 기업용 서비스 특성상 이름, 부서, 직급 등 입력해야 할 정보가 많았고, 이는 신규 입사자에게 다소 피로한 첫인상이 될 수 있었습니다.

여기서 아이디어를 얻었습니다. "신규 직원이 이미 발급받은 명함을 찍기만 하면, 모든 정보가 자동으로 채워지면 어떨까?" 단순히 기능을 추가하는 것을 넘어, 서비스의 전문성을 높이는 '스마트 온보딩'을 기획하게 되었습니다.


🛠 기술적 선택: 왜 Tesseract 대신 'Spring AI'인가?

처음에는 전통적인 OCR 라이브러리(Tesseract 등)를 검토했지만, 두 가지 결정적인 한계가 있었습니다.

  1. 라벨링(Labeling)의 한계: 항공사마다 명함 양식이 다릅니다. 특정 좌표에서 텍스트를 읽어오는 방식으로는 대한항공, 아시아나, 제주항공 등 다양한 디자인에 대응할 수 없었습니다.
  2. 구조화의 어려움: 단순 OCR은 글자를 읽을 뿐, 이 글자가 '이름'인지 '부서'인지 구분하는 문맥 이해 능력이 부족했습니다.

저는 이 문제를 해결하기 위해 Spring AI와 **멀티모달 LLM(openAI)**을 도입했습니다. AI에게 이미지 전체의 문맥을 분석하게 하여, 라벨링 없이도 정교한 데이터 추출이 가능하도록 설계했습니다.


⚙️ 구현 핵심: 정밀한 프롬프트 엔지니어링

비정형 이미지에서 정형 데이터(JSON)를 완벽하게 뽑아내기 위해, VisionService에서 다음과 같은 프롬프트 전략을 사용했습니다.

1. 문맥 이해 및 구조적 추론

단순히 "읽어줘"가 아니라, 데이터의 성격을 명확히 규정했습니다.

  • 날짜: YYYY-MM-DD 형식 준수
  • 시간: HH:mm 형식 준수
  • 사유: 핵심 내용을 요약하여 추출

2. 구조화된 응답(Structured Output) 강제

LLM이 마크다운 블록(```json) 없이 순수 JSON만 반환하도록 요청하고, 백엔드에서 ObjectMapper를 통해 바로 Java 객체(`ProtestDto.OcrResponse`)로 변환했습니다.

[핵심 소스 코드: VisionService.java]

@Service
@RequiredArgsConstructor
public class VisionService {
    private final ChatClient.Builder chatClientBuilder;
    private final ObjectMapper objectMapper;

    public ProtestDto.OcrResponse extractText(MultipartFile file) {
        // 프롬프트 엔지니어링: 항공사별 다른 양식에 대응하기 위한 명확한 지침 설계
        String promptText = """
            이 이미지에서 다음 정보를 추출해서 순수 JSON 형식으로만 반환해.
            - targetDate: 문서에 적힌 날짜 (YYYY-MM-DD 형식)
            - updateTime: 문서에 적힌 시간 (HH:mm 형식)
            - reason: 문서의 핵심 내용 요약
            """;

        ChatClient chatClient = chatClientBuilder.build();
        String response = chatClient.prompt()
                .user(userSpec -> userSpec
                        .text(promptText)
                        .media(MimeTypeUtils.parseMimeType(file.getContentType()), resource))
                .call()
                .content();

        // LLM 응답을 바로 객체로 파싱하여 구조화된 데이터 반환
        return objectMapper.readValue(removeMarkdownCodeBlocks(response), ProtestDto.OcrResponse.class);
    }
}

🔥 'Control Tower' 프로젝트에서의 트러블슈팅

1. 항공사 도메인 지식의 부재

초기에는 AI가 항공사 로고를 사원 이름으로 착각하는 경우가 있었습니다. 이를 해결하기 위해 "텍스트의 크기와 문맥상 항공사명은 회사 필드로, 사람은 이름 필드로 분류하라"는 도메인 특화 지침을 프롬프트에 추가하여 정확도를 대폭 높였습니다.

2. 가입 프로세스와의 유연한 연동

회원가입 컨트롤러(EmpController)와 OCR 컨트롤러(ProtestApplyController)를 분리하여, 사용자가 사진을 올리는 즉시 API가 동작하고 결과를 프론트엔드 입력 폼에 Auto-fill(자동 채우기) 하도록 구현했습니다.


✨ 성과 및 배운 점

  • 유지보수성 향상: 새로운 항공사가 추가되어도 코드를 수정하거나 다시 라벨링할 필요가 없습니다. 오직 프롬프트 하나로 대응 가능한 확장성을 얻었습니다.
  • 사용자 경험(UX) 극대화: 복잡한 가입 절차를 사진 한 장으로 해결하여 '스마트한 HR 서비스'라는 프로젝트 정체성을 확립했습니다.
  • 백엔드 개발자의 역할 재정의: 단순히 데이터를 저장하는 것을 넘어, AI를 활용해 비정형 데이터를 가치 있는 비즈니스 데이터로 변환하는 브릿지 역할의 중요성을 체감했습니다.

'Projects > Team Projects' 카테고리의 다른 글

[Control Tower]Spring Boot + AWS RDS + Nginx 배포기: 삽질하며 배운 인프라의 중요성  (0) 2026.03.07
[Control Tower] AWS S3 + CloudFront로 React 앱 정적 배포하기 (보안과 성능 최적화)  (0) 2026.03.07
[Control Tower] Spring AI(Gemini)로 근태 증빙서류 자동 완성(OCR) 구현하기 🚀 (Zero-Click UX 적용기)  (0) 2026.02.12
[Control Tower] 2차 개발 구현 계획(Spring Ai & OCR)  (0) 2026.02.11
[Control Tower] 1차 개발 회고: 협업의 가치와 성장을 기록하다  (0) 2026.02.10
'Projects/Team Projects' 카테고리의 다른 글
  • [Control Tower]Spring Boot + AWS RDS + Nginx 배포기: 삽질하며 배운 인프라의 중요성
  • [Control Tower] AWS S3 + CloudFront로 React 앱 정적 배포하기 (보안과 성능 최적화)
  • [Control Tower] Spring AI(Gemini)로 근태 증빙서류 자동 완성(OCR) 구현하기 🚀 (Zero-Click UX 적용기)
  • [Control Tower] 2차 개발 구현 계획(Spring Ai & OCR)
tlsgkstj
tlsgkstj
짱구의 성장 일기
  • tlsgkstj
    코딩하는 짱구
    tlsgkstj
  • 전체
    오늘
    어제
    • 분류 전체보기 (159)
      • About (1)
      • Projects (35)
        • Personal Projects (21)
        • Team Projects (14)
      • Engineering (20)
        • CS & Tools (0)
        • Backend Core (15)
        • Frontend (1)
        • Infra & Cloud (2)
        • AI & Tools (1)
      • Trouble Shooting & Issues (0)
      • Growth & Career (38)
        • Interview Prep (0)
        • Retrospectives (38)
      • Archive (65)
        • TIL (8)
        • Daily Dev Q&A (56)
  • 블로그 메뉴

    • 홈
    • About
    • Projects
    • Tech Stack
    • Dev Log
    • GitHub
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    til
    프로덕트개발자
    java
    Project_Review
    backend
    클로드코드
    데브페스트
    Spring비교
    커리어리셋
    aws_s3
    network
    devlog
    프로젝트회고
    OrphanRemova
    jpa
    REACT
    DevFestIncheon2025
    spring
    SpringBoot
    경기기후바이브코딩
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
tlsgkstj
[Control Tower] Spring AI로 구현한 항공사 사원 가입 자동화 (명함 OCR & 프롬프트 엔지니어링)
상단으로

티스토리툴바