← 아티클 목록

시리즈AI를 보안 분석에 붙여 본 기록5편 · 공개 5편

AI Security

영상과 메일로 매체를 바꿔도 점수 한 칸에서 같은 문제가 나온다

OpenCV 전처리와 HOG·Haar 탐지 결과를 부분 탐지까지 포함해 읽고, CNN·YOLO의 출력과 평가 방식이 어디서 어긋나는지, LIME 같은 설명이 무엇을 증명하지 않는지, 딥페이크와 TF-IDF 피싱 탐지에서 점수 하나로 확정할 수 없는 이유를 정리한 개념 노트.

목차 9

2026-08-09 업데이트 — TF-IDF 예제의 Accuracy 0.83을 피싱 4건 중 3건으로 연결한 오류를 바로잡았다. Accuracy와 Recall의 분모를 구분하고, support와 혼동행렬 없이는 정수 건수를 확정하지 않도록 수정했다.

이미지는 배열이고 채널 순서가 결과를 뒤집는다

컴퓨터 비전에서 이미지는 높이, 너비, 채널로 이루어진 수치 배열이다. 컬러 이미지의 픽셀 하나는 여러 채널의 밝기 값을 갖고, 전처리는 이 배열을 탐지 목적에 맞게 바꿔 모델이 쓸 특징을 만드는 과정이다.

표현 배열 형태 예시 용도
컬러 (height, width, 3) 색상 정보를 포함한 분석과 시각화
그레이스케일 (height, width) 밝기 중심 특징 추출과 계산량 감소
이진 엣지 (height, width) 경계선 위치와 형태 분석

첫 줄에서 어긋나기 쉬운 것이 채널 순서다. OpenCV의 cv2.imread()는 컬러 이미지를 BGR 순서로 읽는다. RGB를 기대하는 Matplotlib에 그대로 넘기면 빨강과 파랑이 바뀐 그림이 나오므로 cv2.cvtColor(img, cv2.COLOR_BGR2RGB)로 바꿔야 한다. 반대로 cv2.imwrite()는 BGR 배열을 기대하니, RGB로 변환한 배열을 그대로 저장하면 색이 다시 뒤집힌다. 같은 파이프라인 안에서 두 번 변환하거나 한 번도 변환하지 않는 실수가 여기서 나온다.

전처리 흐름은 이미지를 읽고 None 여부를 확인하는 데서 시작해, 다음 도구가 기대하는 채널 순서를 맞추고, cv2.cvtColor(..., cv2.COLOR_BGR2GRAY)로 밝기 정보만 남긴 뒤, cv2.Canny(gray, low, high)로 경계선 후보를 뽑고, 입력 크기와 임계값과 생성 파일 경로를 결과와 함께 기록하는 순서다. Canny의 50, 150은 실습 이미지에 쓴 설정값이지 보편적인 최적값이 아니다. 조명과 노이즈, 카메라에 따라 달라지므로 정상 영상과 이상 영상을 함께 놓고 조정한다.

얼굴 상자 하나와 사람 상자 두 개를 어떻게 읽나

HOG는 지역별 경계선 방향 분포를 특징으로 쓰고 선형 SVM과 결합해 사람 형태 같은 학습 대상을 찾는다. detectMultiScale()이 돌려주는 foundWeights는 각 검출의 분류 점수이고 확률로 보정된 값이 아니라서, 다른 모델이나 다른 설정의 확률처럼 나란히 놓고 비교하지 않는다.

Haar Cascade는 여러 밝기 차이 특징을 단계적으로 적용해 정면 얼굴 후보를 빠르게 찾는다. 얼굴이 있는 영역을 찾는 탐지기이지 사람의 신원을 확인하는 얼굴 인식 모델이 아니다. scaleFactor, minNeighbors, minSize에 따라 미탐과 오탐이 갈린다.

제공된 결과 이미지 두 장을 열어 보니 읽는 방식이 갈리는 지점이 그대로 나왔다. 얼굴 결과에는 정면 얼굴 한 곳에 경계 상자가 있었다. 얼굴 위치를 찾았다는 것까지가 이 그림이 말하는 전부이고, 인물의 신원이나 실제 사람 여부, 출입 권한은 검증되지 않았다.

사람 결과에는 초록 상자가 두 개 있었다. 상자가 둘이니 사람 두 명을 탐지했다고 적기 쉬운데, 두 번째 상자는 오른쪽 인물의 전신이 아니라 손과 의자 주변만 감싸고 있었다. 오른쪽 인물의 대부분은 상자 밖에 있다. 그래서 이 결과는 사람 두 명의 정확한 탐지가 아니라 부분 탐지, 위치 오류 또는 오탐 후보로 기록하고, 미탐 관점에서도 함께 본다. 탐지 건수를 세는 것과 탐지 결과를 읽는 것은 다른 작업이다.

분류와 탐지는 다른 출력을 내고 다른 지표로 잰다

이미지 분류는 입력 이미지 전체에 범주를 부여하고, 객체 탐지는 이미지 안에서 각 객체의 범주와 위치를 함께 찾는다. 보안 카메라에서 사람이 있는지를 판단하는 것과 사람마다 경계 상자를 만들어 추적 후보를 넘기는 것은 다른 문제라, 모델 출력과 평가 지표도 따로 둔다.

작업 주요 출력 대표 평가 보안 활용 예시
이미지 분류 클래스와 클래스 점수 Accuracy, Precision, Recall, F1 프레임의 위험 장면 분류
객체 탐지 클래스, 점수, 경계 상자 Precision, Recall, IoU, mAP 사람·차량 위치와 수량 확인

경계 상자와 함께 나오는 점수는 모델의 상대적 판정 강도이고 현실의 참·거짓 확률과 같지 않다. 운영 임계값은 미탐 비용, 오탐 처리량, 카메라 환경을 놓고 정한다.

CNN은 작은 합성곱 커널로 지역 패턴을 학습하고 활성화 함수와 풀링을 거쳐 점점 복합적인 특징을 만든다. 실습의 cnn_classify.py는 다음 구조로 scikit-learn 숫자 이미지를 분류한다.

1x8x8 입력
  -> Conv 8채널 + ReLU + MaxPool
  -> Conv 16채널 + ReLU + MaxPool
  -> 16x2x2 Flatten
  -> 10개 숫자 클래스

load_digits는 1,797개의 8×8 이미지와 10개 클래스로 이루어져 있고, 코드는 픽셀 값을 0~1로 정규화한 뒤 Adam과 Cross Entropy로 15 epoch 학습하도록 작성되어 있다.

YOLO는 단일 단계 객체 탐지 계열로, 한 번의 추론에서 여러 객체의 클래스와 경계 상자 후보를 계산한다. yolo_detect.py는 COCO로 사전학습된 yolov8n.pt를 쓰고, 이 모델은 80개 COCO 클래스를 다룬다. yolov8n의 n은 nano 규모라는 뜻이지 실시간이 보장된다는 뜻이 아니다. 처리 속도는 입력 해상도, 하드웨어, 전처리와 후처리, 배포 형식에 따라 달라진다.

Vision Transformer는 이미지를 패치 토큰으로 바꾸고 self-attention으로 패치 사이 관계를 학습한다. CNN과 ViT는 세대 교체라기보다 데이터와 계산 자원, 목적에 따라 고르거나 섞는 계열이다. 최신 모델이라는 이유만으로 특정 보안 데이터에서 더 강건하거나 더 설명 가능하다고 가정하지 않는다.

테스트 세트를 매 epoch 들여다보면 그것은 검증 세트다

CNN 실습 코드를 읽으면서 평가 쪽에 걸리는 곳이 세 군데 있었다.

  • 데이터를 순서대로 앞 80%와 뒤 20%로 나누고 셔플과 계층 분할을 하지 않는다.
  • 매 epoch마다 최종 테스트 세트의 정확도를 확인한다. 테스트 세트를 검증 세트처럼 반복해서 쓰는 것이다.
  • 별도의 검증 세트나 교차 검증이 없어서 마지막 수치를 일반화 성능으로 읽기 어렵다.

두 번째가 특히 조용히 지나가는 문제다. 학습을 멈출 시점이나 하이퍼파라미터를 테스트 정확도를 보고 고르면, 그 테스트 세트는 모델 선택에 이미 참여한 데이터다. 남는 숫자는 ’한 번도 안 본 데이터에서의 성능’이 아니라 ’여러 번 들여다본 데이터에서의 최고 기록’이 된다.

재현 가능한 평가로 바꾸려면 train_test_split(..., stratify=y, random_state=...)이나 계층 교차 검증으로 클래스 비율을 유지하고, 모델 선택에 쓰지 않은 테스트 세트를 마지막에 한 번만 연다.

스크립트 쪽에도 손볼 곳이 하나 있었다. HOG 탐지 수가 2로 하드코딩되어 있어서, 다른 입력이나 다른 설정으로 다시 돌리면 요약 문장과 실제 결과가 어긋난다. len(rects) 같은 실행 결과를 받아 비교하도록 바꿔야 한다.

설명 히트맵은 판정이 옳다는 증거가 아니다

설명 가능한 AI는 모델의 판정을 사람이 검토할 수 있는 특징, 영역, 규칙 형태로 보여 준다. 영상 보안에서 이 그림은 탐지기가 사람에 반응했는지 배경이나 도구에 반응했는지를 조사하는 단서가 되지만, 판정이 정확하다는 증명이나 원인에 대한 인과적 설명은 아니다.

방법 설명 대상 대표 출력 주의점
LIME 개별 예측 주변 슈퍼픽셀 또는 단어별 기여 샘플링과 난수에 따라 결과가 달라질 수 있음
SHAP 특징별 기여 기준값 대비 양·음의 기여 배경 데이터와 특징 의존성에 민감
Grad-CAM CNN의 특정 클래스 활성 영역 히트맵 낮은 해상도와 레이어 선택의 영향
Attention Map 토큰·패치 사이 가중치 집중 영역 또는 관계 attention 값만으로 모델의 전체 추론을 설명하지 못함

LIME은 설명할 입력 주변에 변형된 샘플을 만들고 원래 모델의 출력 변화를 관찰한 뒤, 그 지역을 근사하는 단순 대리 모델을 학습한다. 이미지에서는 슈퍼픽셀을 가리거나 드러내어 판정에 크게 영향을 준 영역을 찾는다.

원본 이미지
  -> 슈퍼픽셀 분할
  -> 일부 영역을 가린 변형 샘플 생성
  -> 블랙박스 모델의 예측 수집
  -> 주변을 근사하는 단순 모델 학습
  -> 지역별 기여 표시

여기서 나오는 그림은 원본 모델의 내부 규칙이 아니라 선택한 주변 샘플과 대리 모델이 만든 국소 근사다. 난수 시드, 슈퍼픽셀 알고리즘, 샘플 수, 거리 커널을 기록하고 같은 입력을 반복해서 설명했을 때 결과가 얼마나 흔들리는지 확인해야 한다.

영상 보안 모델을 평가할 때 보는 항목은 다섯 가지다. 독립된 테스트 데이터에서의 Precision·Recall·F1·mAP, 조명과 각도와 압축과 가림과 새 카메라에서의 강건성, 설명이 원래 모델의 국소 출력을 얼마나 잘 근사하는지, 같은 입력의 반복 설명과 작은 입력 변화에서의 안정성, 그리고 분석가가 원본 영상과 함께 판단하는 데 실제로 도움이 되는지다.

히트맵이나 중요 영역만으로 위험 인물, 범행 의도, 신원을 확정하지 않는다. 원본 파일의 무결성, 시간·카메라 메타데이터, 탐지 모델과 설명기의 버전, 임계값, 전체 프레임 맥락, 사람의 검토를 함께 남긴다. 설명 가능성은 조사를 돕지만 잘못된 모델을 올바른 모델로 만들지는 않는다.

딥페이크는 생성 기술보다 신뢰 경로의 문제다

딥페이크는 AI로 사람의 얼굴, 음성, 영상 내용을 생성하거나 합성·변형한 미디어다. 초기 얼굴 합성에서는 GAN과 오토인코더 계열이 큰 역할을 했지만 지금의 합성 미디어에는 diffusion, neural rendering, 음성 생성이 함께 들어가므로 딥페이크를 GAN 하나로 설명하지 않는다.

보안 쪽 문제는 생성 기술 자체보다 그 미디어가 신원, 지시, 증거로 받아들여질 때 생긴다.

시나리오 공격자가 노리는 신뢰 주요 방어
음성·영상 사칭 상사·가족·기관의 신원 별도 채널 재확인, 거래 승인 분리
얼굴 인증 우회 카메라 영상이 실제 사용자라는 가정 liveness, 기기 신뢰, 다요소 인증
허위 정보 유포 영상은 사실이라는 사회적 신뢰 출처·서명·원본 검증과 맥락 확인
합성 협박물 피해자의 평판과 심리 증거 보존, 신고, 유통 차단 절차

탐지 신호 쪽은 세 갈래로 배웠다. Eye Aspect Ratio는 얼굴 랜드마크에서 눈의 세로 거리와 가로 거리 비율을 계산해 깜빡임 후보를 찾는다. 강의에 나온 0.25~0.35와 0.20 미만은 예제 범위이고 얼굴 각도, 사람, 카메라, 랜드마크 모델에 따라 달라지는 값이라 보편 임계값으로 쓸 수 없다. 자연스러운 깜빡임도 합성할 수 있으니 EAR 하나로 확정하지 않는다. 얼굴과 배경 경계의 밝기 차이, 텍스처 불연속, 색상 공간과 주파수 흔적은 합성 후보를 찾는 단서지만, SNS 재압축과 리사이징이 이 흔적을 지우거나 정상 영상에도 비슷한 패턴을 만든다. CNN·Transformer 탐지기는 대규모 데이터에서 공간·시간 특징을 학습할 수 있어도 학습하지 않은 생성 방식과 다른 압축 조건에서 성능이 떨어진다. FaceForensics++의 XceptionNet 결과는 특정 벤치마크의 기준 모델로 읽고 현재 모든 환경의 최고 탐지기로 옮겨 적지 않는다.

구조적으로 남는 한계가 있다. 생성기와 탐지기는 서로의 개선에 적응하는 관계라 한쪽의 우위가 오래가지 않고, 같은 데이터셋에서 얻은 높은 성능이 다른 생성기와 실제 유통 영상으로 넘어가지 않을 수 있다. 프레임 단위 점수는 음성, 입 모양, 시간적 일관성, 출처 정보를 놓친다. 그래서 미디어 분석 전에 파일 해시와 원본 출처, 전송 이력을 보존하고, 여러 탐지기의 결과가 엇갈리면 그 불일치를 숨기지 않고 기록하며, 고위험 거래와 권한 변경은 등록된 별도 채널과 다중 승인으로 다시 확인한다. 탐지 실패를 전제로 한 승인 절차가 마지막 층이다.

TF-IDF의 Accuracy와 Recall은 분모가 다르다

TF-IDF 기반 피싱 탐지는 이메일 본문 단어의 빈도와 문서 집합에서의 희소성을 수치 특징으로 바꾸고 분류 모델로 판단한다. TF는 한 문서 안에서 단어가 얼마나 자주 나오는지를, IDF는 여러 문서에 흔한 단어의 영향을 낮추고 드문 단어의 영향을 높이는 값이다.

이메일 원문
  -> 토큰화와 정규화
  -> TF-IDF 특징 벡터
  -> 로지스틱 회귀 학습
  -> 피싱 확률 또는 클래스
  -> 임계값과 대응 정책

강의 예제는 피싱 10건과 정상 10건, 최대 50개 특징을 쓴다. 화면에 나온 출력은 Accuracy 0.83, 피싱 Precision 1.00, Recall 0.75다. Recall은 실제 피싱 중 찾아낸 비율이므로, Recall 0.75는 테스트 세트의 실제 피싱 가운데 75%를 찾았다는 뜻이다. 그러나 저장소에 남은 화면 수치만으로는 피싱 support를 확인할 수 없다. 0.75는 3/4뿐 아니라 6/8처럼도 나올 수 있으므로 찾아낸 건수와 놓친 건수를 임의로 정하지 않는다.

Accuracy 0.83은 피싱만이 아니라 정상 메일까지 포함한 전체 테스트 표본 중 맞힌 비율이다. 제공된 화면에는 전체 테스트 표본 수와 혼동행렬이 없어 이 값의 분자와 분모를 복원할 수 없다. 따라서 0.83을 4건 중 3건으로 바꾸어 읽지 않고, 원 코드와 분할을 확보하기 전에는 반올림 방식도 추정하지 않는다. 두 지표 모두 같은 작은 분할에서 나온 값이라 운영 성능으로 옮겨 적지 않는다.

작은 데이터에서는 계층 분할과 교차 검증, 반복 실행으로 편차를 확인하고 최종 테스트 세트는 모델 선택 이후 한 번만 연다. Accuracy 옆에 피싱 Recall, Precision, PR-AUC와 미탐 피해, 오탐 처리 비용을 같이 놓는다.

키워드 중심 탐지가 새는 자리도 예제 규모와 무관하게 그대로 남는다. 지금, 즉시, 클릭 같은 단어가 없으면 긴급한 사기 문맥을 놓치고, 확인이나 안녕하세요처럼 정상 메일에 흔한 단어는 피싱에도 자연스럽게 들어간다. 수신자 이름과 조직 문체를 흉내 낸 개인화 피싱은 일반 키워드 규칙을 지나간다. URL 단축과 QR 코드, 이미지 속 문자와 첨부 파일은 본문 TF-IDF로 분석되지 않는다. 생성형 AI가 자연스러운 문장과 다국어 변형을 빠르게 만들 수 있으니 이 빈틈은 시간이 갈수록 넓어진다.

그래서 본문 하나로 판단하지 않고 신호를 여러 줄로 놓는다.

신호 확인 항목
본문 TF-IDF, 문장 임베딩, 요청 의도와 언어 이상
발신 인증 SPF, DKIM, DMARC 결과와 표시 이름 불일치
URL 최종 도메인, 리디렉션, 등록 시점과 평판
첨부 파일 파일 형식, 매크로, 샌드박스와 정적 분석
행동 신규 발신자, 대량 발송, 로그인·메일 규칙 변경
업무 맥락 결제·권한 변경의 별도 채널 승인

매체가 바뀌어도 같은 자리에서 갈렸다

로그에서 영상으로, 영상에서 메일 본문으로 매체가 바뀌었는데 걸리는 자리는 같았다. 상자 두 개가 사람 두 명을 뜻하지 않았고, 히트맵이 판정의 근거를 증명하지 않았고, EAR 하나가 합성을 확정하지 않았고, 피싱 Recall 0.75도 support 없이 정수 건수로 바꿀 수 없었다. 모델이 내놓는 값은 조사 후보이지 결론이 아니라는 조건이 매체를 따라 옮겨 다닌다.

달라지는 것은 그 조건을 어디서 보완하느냐다. 로그에서는 규칙과 다른 시간 창과 원본 이벤트가 그 자리에 왔고, 영상에서는 원본 파일의 무결성과 메타데이터와 전체 프레임 맥락이, 메일에서는 발신 인증과 URL과 업무 승인 절차가 왔다. 기술이 아니라 그 옆에 무엇을 세워 두었는지가 판정의 신뢰도를 정한다.

이번 편에서 직접 실행해 확인한 것은 없다. 제공된 cv_image_basics.py와 cv_detection.py, cnn_classify.py는 구문 검사까지만 통과했다. cv_detection.py가 참조하는 data/face_sample.jpg와 data/people_sample.png가 배포 폴더에 없고 실행 환경에 OpenCV가 설치되어 있지 않아 원본 입력부터 다시 돌리지 못했으므로, HOG와 Haar 결과에 대한 관찰은 제공된 출력 이미지와 코드의 정적 검토에 근거한다. YOLO는 참조 이미지와 yolov8n.pt가 없고 Ultralytics도 설치되어 있지 않아 모델을 내려받으면서까지 돌리지는 않았다. TF-IDF 피싱 실습은 오후 자료에 화면이 있지만 phishing_detector.py 원본이 제공 파일 목록에 없어서, 위 수치는 강의자료를 옮겨 적은 것이지 실행 결과가 아니다. Accuracy와 Recall의 정정도 원 실험을 재실행한 결과가 아니라, 화면의 지표 이름과 공식 계산 정의를 대조한 문서 검토다. LIME과 SHAP, Grad-CAM은 표에 적은 설명 대상과 주의점을 정리했을 뿐 어느 것도 실제 모델에 붙여 보지 않았다.

참고 자료