2026년 2월 25일 수요일

포커스 그룹 인터뷰(FGI)의 그늘: 우리가 놓치기 쉬운 부작용

A lot of times, people don't know what they want until you show it to them. - 스티브 잡스, Bloomberg, May 1998.

It's really hard to design products by focus group. A lot of times, people don't know what they want until you show it to them. - 스티브 잡스, Forbes, Oct 2011.

포커스 그룹 인터뷰(Focus Group Interview, FGI)는 정책 설계와 서비스 기획에서 널리 활용되는 질적 연구 방법입니다. 소수의 참여자를 모아 특정 주제에 대해 자유롭게 토론하게 함으로써, 설문조사로는 포착하기 어려운 맥락과 인식을 드러내는 데 강점이 있습니다.

그러나 최근 여러 현장에서 FGI 결과가 과도하게 일반화되거나 정책 판단의 근거처럼 사용되는 사례를 보며, 이 방법론이 가진 구조적 한계를 다시 짚어볼 필요성을 느낍니다. FGI는 유용한 도구이지만, 잘못 쓰이면 오히려 의사결정을 왜곡할 수 있습니다.


1. 작은 표본이 만드는 큰 착시

FGI의 가장 근본적인 한계는 표본 규모입니다. 일반적으로 한 그룹은 6~10명 수준에 불과합니다. 이는 심층 의견 탐색에는 적절할 수 있지만, 그 자체로 어떤 집단의 ‘대표 의견’을 말해 주지는 못합니다.

문제는 이 결과가 때때로 다음과 같이 해석된다는 점입니다.

  • “현장에서는 이렇게 생각한다”
  • “사용자들은 이것을 원한다”
  • “전문가 의견이 모였다”

이러한 표현은 FGI의 본래 용도를 넘어서는 일반화입니다. 소수의 목소리가 전체의 경향처럼 포장될 때, 정책과 서비스는 잘못된 방향으로 흘러갈 위험이 있습니다.


2. 그룹 다이내믹이 만들어내는 편향

FGI는 ‘집단 토론’이라는 형식 자체에서 여러 편향을 내포합니다.

  • 목소리 큰 참여자의 의견이 토론을 지배
  • 분위기에 따른 동조 압력(groupthink)
  • 사회적으로 바람직한 답변으로의 수렴
  • 진행자의 질문 방식에 따른 유도 효과

특히 기술이나 정책처럼 정답이 불분명한 주제에서는, 토론 분위기 하나로 의견 분포가 크게 달라질 수 있습니다. 이 경우 우리가 관찰하는 것은 ‘개별 참여자의 진짜 생각’이 아니라, 토론 상황에서 형성된 집단 산물일 가능성이 큽니다.


3. 탐색 도구가 결정 도구로 오용되는 문제

FGI의 본래 목적은 결론을 확정하는 것이 아니라, 다음과 같은 탐색적 역할입니다.

  • 가설 생성
  • 문제 맥락 이해
  • 사용자 언어와 인식 파악
  • 추가 연구 설계의 단서 확보

그럼에도 불구하고 실무에서는 FGI 결과가 정책 방향을 정당화하는 근거처럼 사용되는 경우가 적지 않습니다. 질적 탐색 도구가 정량적 근거를 대체하는 순간, 의사결정의 기반은 급격히 취약해집니다.


4. ‘기대 담론’이 증폭되기 쉬운 구조

최근 AI, 데이터, 디지털 전환과 같은 분야에서는 긍정적 기대가 사회 전반에 강하게 형성되어 있습니다. 이런 환경에서 진행되는 FGI는 자연스럽게 다음과 같은 경향을 보이기 쉽습니다.

  • 기술 낙관론의 과대표출
  • 위험 요소의 과소 언급
  • 실행 비용과 현실 제약의 축소

참여자들은 종종 “바람직한 미래”를 말하지, “실제로 작동 가능한 현실”을 말하지 않습니다. 이 차이를 구분하지 못하면, 정책은 구호는 크고 실행은 어려운 방향으로 흘러갈 수 있습니다.


5. 책임의 비대칭성

FGI에서 나온 아이디어나 방향이 실제 정책이나 시스템으로 구현될 경우, 흥미로운 비대칭이 발생합니다.

  • 의견 제시는 소수 참여자가 수행
  • 실행과 책임은 기관과 현장이 부담

특히 데이터 거버넌스나 AI 활용처럼 법적·윤리적 부담이 큰 영역에서는, 초기 아이디어의 파급력을 과소평가하기 쉽습니다. 즉흥적 제안 하나가 실제 운영 단계에서 상당한 비용과 위험을 동반할 수 있습니다.


균형 잡힌 활용을 위하여

FGI는 여전히 가치 있는 도구입니다. 사용자 맥락을 이해하고, 문제의 언어를 포착하며, 새로운 가설을 만드는 데 있어 강력한 방법임은 분명합니다.

다만 다음 원칙은 반드시 지켜질 필요가 있습니다.

  • FGI 결과를 일반화하지 말 것
  • 정량 자료와 교차 검증할 것
  • 정책 결정의 단독 근거로 사용하지 말 것
  • 참여자 구성과 토론 맥락을 투명하게 공개할 것

FGI는 방향을 비추는 손전등이지, 결론을 확정하는 판결문이 아닙니다. 이 기본을 잊지 않을 때, 우리는 이 유용한 도구를 과신도 과소평가도 하지 않는 균형 잡힌 위치에서 활용할 수 있을 것입니다.

이 글은 현장 경험을 바탕으로 FGI 방법론의 한계를 성찰하기 위해 작성되었습니다.


이 글은 정해영의 아이디어를 바탕으로 AI(ChatGPT)의 도움을 받아 작성되었습니다. CC0 1.0으로 자유 이용 가능하며, 정확성 및 법적 책임은 보장하지 않습니다. This text was written with AI (ChatGPT) assistance based on the author’s ideas. Released under CC0 1.0. No guarantee of accuracy is provided, and no liability is assumed.

바꿀 수 있는 것과 없는 것 - 고장난 전원 스위치 하나가 남긴 질문

43 오극관 싱글 앰프의 망가진 전원 스위치

내 사무실에는 내가 직접 만든 오디오 앰프가 몇 대 있다. 그중 진공관으로 자작한 것이 두 대쯤 되는데, 사무실에 처음 찾아온 사람과 가볍게 이야기를 풀어나갈 때 꽤 좋은 소재가 되곤 했다. 나의 오디오 앰프 자작 기록은 공식 웹사이트의 위키 문서에 따로 정리해 두었다.

그 가운데 하나가 1940년대에 만들어진 항아리 형태의 43 오극관을 사용한 소출력 앰프였다(자작 기록). 상판은 CAD를 이용해 설계한 뒤 도면을 가공업체에 보내서 만들었고, 바닥의 나무틀도 손수 도색하여 나름대로 정성을 들여 만든 기기였다. 진광관 자체가 고전적인 항아리 모습이라 개인적으로도 꽤 애착을 갖고 있던 진공관 앰프였다. 처음에는 빵 굽는 트레이 위에 프로타입을 만드는 것으로 시작하였었다(링크). 프로토타입 제작 당시에는 R-core에 직접 감은 출력트랜스포머를 여기에 처음 연결해서 사용했었다.

그런데 어제 전원 스위치가 들어오지 않는 것을 발견했다. 조명이 들어오는 시소형 전원 스위치였는데, 아무리 움직여도 ON 포지션에 고정이 되지 않았고 불도 들어오지 않았다. 수동 부품의 내구성에 대해 나름 높은 기준을 갖고 있던 나로서는 꽤 실망스러운 상황이었다. 일단 인터M R150 PLUS '레퍼런스' 앰프로 바꾸어 놓았다. 이는 대출력 앰프라서 사무실 책상 위에서 쓰기에는 적합한 수준은 아니다.

R150 PLUS 파워앰프. 책상 위에 놓고 잔잔하게 음악을 듣기에는 너무 출력이 커서 레벨 조정용으로 베링거 믹서를 달아 놓았다.

참고로 말하자면 내가 블로그에 쓴 글 중에서 램프형 스위치의 올바른 결선법(2016.5.29.)은 항상 가장 많은 조회수를 보이고 있다.

물론 전원 스위치 수리는 어려운 일이 아니다. 상판 타공 사이즈에 맞는 부속을 다시 구해 납땜만 하면 되는 문제이기 떄문이다. 전기/전자제품이란 당연히 수명이라는 것이 있다. 특히 자작 기기인 경우 스위치나 소켓, 커넥터와 같은 수동/기구 부품은 값이 좀 비싸더라도 좋은 것을 써야 후회가 없는데 제작 당시에는 좋은 결심을 하지 못하는 것이 늘 문제이다.

이 일 자체는 매우 사소한 일이었다. 부품을 구해서 바꾸어 끼고 납땜을 새로 하면 해결될 문제였다.

하지만 최근 2년 동안 내가 직장에서 맞닥뜨린 몇 가지 일들은 그렇게 간단하지 않았다.

어디선가 읽은 글이 떠올랐다. 어떤 이는 자신의 성공 비결이 아무리 노력해도 바꿀 수 있는 것과 바꿀 수 없는 것을 빨리 구별하는 데 있다고 말했다. 즉, 바꿀 수 없는 일을 개선하려고 쓸데없는 에너지를 낭비하지 말자는 뜻이었다.

물론 아주 작고 조금만 조절하면 될 일까지도 바꿀 수 없다고 성급히 판단해버리는 것은, 자신의 능력과 가능성을 스스로 잠재워버리는 게으른 핑계가 될 수도 있겠다고 생각했다.

그럼에도 불구하고 아무리 노력해도 바꿀 수 없는 것들이 우리 주변에 너무 많다는 사실도 부정할 수 없었다. 그것은 내 안에도 있었고, 특히 외부 환경에도 많이 존재했다. 그럴 때마다 적지 않은 무력감을 느꼈다.

지난 2년 동안 나는 그런 경험을 유난히 많이 했다. 그리고 아직 뚜렷하게 나아질 기미도 보이지 않았다.

무엇을 바꿀 수 있을 것인가? 차라리 나 자신을 바꾸는 것이 가장 올바른 길일까?

망가진 오디오 앰프의 파워 스위치를 바라보며, 그런 생각을 하게 된 아침이었다.

GitHub를 위한 파일과 폴더명 쓰는 방법

REAME.md? ReadMe.md? read_me.md? read-me.md?

프로그래밍 세계에서는 변수명의 대소문자(case)를 표기하는 여러 관행이 존재한다. 이에 대해서는 워낙 많은 글이 널려 있으니 여기서 구태여 반복할 필요는 없겠다. 가장 중요한 공통점은 중간에 공백이 들어가면 안된다는 것 정도일 것이다. 참고로 '_'를 흔히 국내에서 under bar라고 부르는데, 영어권의 공식 명칭은 underscore이다.

대표 표기 스타일

스타일 예시 특징 / 용도
camelCase fileName 첫 단어는 소문자, 이후 단어의 첫 글자만 대문자
PascalCase FileName 모든 단어의 첫 글자를 대문자(클래스/타입 이름에 자주 사용)
snake_case file_name 단어 사이를 언더스코어(_)로 구분(Python에서 흔함)
kebab-case file-name 단어 사이를 하이픈(-)으로 구분(URL/HTML/CSS에서 흔함)
SCREAMING_SNAKE_CASE FILE_NAME 대문자 + 언더스코어(상수/환경변수에 자주 사용)

낙타의 혹(camelCase), 땅바닥에 붙어서 기어가는 뱀(snake_case), 꼬챙이에 각종 재료의 가운데를 꽂아서 만든 케밥(kebap-case)을 떠올리면 왜 이런 스타일 이름이 붙는지 쉽게 이해할 수 있을 것이다.

이 스타일을 파일명에나 폴더(디렉토리)명에 그대로 적용해도 별 상관은 없다. 그러나 소스 파일에 따라서는 약간 다른 관례가 존재한다. 예를 들어 웹에서는 kebab-case를 많이 쓰고, 파이썬에서는 sanke_case(.py)가 거의 표준이다. OS에 따라서는 대소문자를 구분하기도 하고 그렇지 않기도 한다. GitHub는 리눅스나 윈도우 양측에서 접근하는 경우가 많으니 파일과 디렉토리 이름에 신경을 좀 써야 한다. 강제되는 규칙이 있는 것은 아니지만 대체로 다음을 권장한다.

  • 디렉토리 이름: kebab-case(1순위), snake_case(2순위)
  • 파일 이름: snake_case(C/C++/Arduino에서 강력 권장), kebab-case 또는 camelCase(JavaScript/웹)

AudioDriver.cpp와 audiodriver.cpp는 리눅스에서는 다른 파일이지만 윈도우에서는 같은 것으로 인식한다. 따라서 파일명은 전부 소문자를 쓰는 것을 강력히 권장한다. Windows의 국문 표준 표기는 '윈도'이다. 그러나 이렇게 쓰려면 영 어색하다...

파이썬 파일명은 특별히 주의해야 한다. 다른 스크립트에서 모듈로 임포트할 소스에는 하이픈('-')을 사용할 경우 에러를 낸다. 예를 들여 midi-parser.py라는 파일이 별도로 존재하는데 이를 다른 스크립트에서 'import midi-parser'로 읽어들이면 에러가 발생한다. 따라서 import_parser.py로 이름을 붙여야 한다. 

그러면 GitHub에서 문서 파일명은 어떻게 해야 하는가? 코드 파일과는 또 약간 다른 관례가 있다고 한다. 가장 흔한 것은 kebab-case이고 그 다음으로는 snake_case이다. camelCase나 PascalCase는 권장하지 않는다. 그러나 매우 중요한 예외가 있으니 그것은 바로 루트에 존재하는 표준 문서다. README.md, LICENSE, CHANGELOG.md 등은 전부 대문자로 고정한다.

정리해 보자. 이 글을 작성하는데 ChatGPT의 도움을 많이 받았다.


🎯 선택 가이드

  • 📚 문서 공개/오픈소스 강조 → kebab-case

  • 🧩 임베디드/툴체인 중심 → snake_case

  • 👤 개인 프로젝트 → 일관성만 유지하면 OK


🔷 한 줄 결론

GitHub 문서 파일명:

  • 일반 문서 → kebab-case ⭐ 또는 snake_case

  • 루트 표준 문서 → README.md 등 대문자 고정

  • camelCase / PascalCase → 문서에는 비권장


2026년 2월 22일 일요일

사진 백업 작업은 두 번째의 GitHub 프로젝트(TakeoutPhotoSanitizer)로 결실을 맺다

TakeoutPhotoSanitizer - PowerShell-based batch processor for Google Takeout Photos. 

https://github.com/jeong0449/TakeoutPhotoSanitizer


이 Windows PowerShell 스크립트는 2GB 단위로 Google Takeout에서 내려받은 복수의 zip 파일을 열고 SHA-256 해시에 의해 중복을 제거한 뒤, 미디어 파일에 동반된 JSON을 분석하여 연도별로 폴더를 나누어서 재분류하는 기능을 한다. 최종 결과물은 원드라이브에 옮겨 영구 보관하는 것이 목표이다. 입력 zip 파일은 반드시 Google Takeout으로 받은 것이 아니어도 작동한다. 즉, 컴퓨터에 보관된 미디어 파일을 zip으로 묶은 뒤 투입하면 하위 폴더 구조와 무관하게 잘 작동함을 확인하였다.

하나의 미디어 파일에 대해 JSON 파일이 여럿 존재하면 이를 병합하여 가장 풍부한 메타데이터를 구성해 준다. 다시 말하자면 단순 병합이 아니라 정보를 보존하는 방향의 우선순위 병합에 가깝다. 

예를 들어 Google Takeout으로 가져온 하나의 미디어 파일에 대해 원본, 앨범 경로, 이름 변형, 부분 정보 등 여러 개의 JSON이 존재하는 경우가 매우 흔하다. 이를 신뢰도 기반으로 병합하여 가용 정보를 최대한 수집한다.

JSON 파일이 없는 경우 미디어 파일 내의 EXIF 정보를 활용한다. 뒤에서 설명하였지만 이 과정도 결코 간단하지 않았다!

다음은 실제 나의 데이터에 대한 마지막 두 배치의 처리 작업에 대한 기록이다. 스크립트 작성에는 ChatGPT가 크게 기여하였다.

PS C:\Users\jeong\Projects\TakeoutPhotoSanitizer> .\TakeoutPhotoSanitizer.ps1 `
>>   -ZipDir "C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Takeout_Zip" `
>>   -DestRoot "C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Photos_Backup\From_Google_Takeout" `
>>   -MinFreeGB 25 `
>>   -ReportSidecars `
>>   -DeleteZips
[2026-02-22 13:39:12] Loading hash DB...
[2026-02-22 13:39:13] Loaded hashes: 47045
[2026-02-22 13:39:13] Using 7-Zip: C:\Program Files\7-Zip\7z.exe
[2026-02-22 13:39:13] Inputs found: ZIP=8, loose_media=0, total=8
[2026-02-22 13:39:13] Batch start: 0001_20260222_133913 (inputs=4, MinFreeGB=25)
[2026-02-22 13:39:13] Extract: takeout-20260220T133610Z-3-087.zip
[2026-02-22 13:39:22] Extract: takeout-20260220T133610Z-3-088.zip
[2026-02-22 13:39:30] Extract: takeout-20260220T133610Z-3-089.zip
[2026-02-22 13:39:36] Extract: takeout-20260220T133610Z-3-090.zip
[2026-02-22 13:39:47] Scanning media files...
[2026-02-22 13:39:48] Media files found: 4066
[2026-02-22 13:43:49] Batch done. Total hashes now: 47074
[2026-02-22 13:43:49] Stats: moved=29, duplicates=4037, sidecar_updated=1300, sidecar_repaired=0
[2026-02-22 13:44:03] Sidecar status (touched dirs): media=10430, missing_sidecar=5264
[2026-02-22 13:44:03] Delete ZIP: takeout-20260220T133610Z-3-087.zip
[2026-02-22 13:44:03] Delete ZIP: takeout-20260220T133610Z-3-088.zip
[2026-02-22 13:44:04] Delete ZIP: takeout-20260220T133610Z-3-089.zip
[2026-02-22 13:44:04] Delete ZIP: takeout-20260220T133610Z-3-090.zip
[2026-02-22 13:45:31] Sidecar repaired this batch: 1
[2026-02-22 13:45:31] Remove temp dir: C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Takeout_Zip\_work\0001_20260222_133913
[2026-02-22 13:45:36] Free space now: 79.48 GB
[2026-02-22 13:45:36] ----------------------------------------
[2026-02-22 13:45:36] Batch start: 0005_20260222_134536 (inputs=4, MinFreeGB=25)
[2026-02-22 13:45:36] Extract: takeout-20260220T133610Z-3-091.zip
[2026-02-22 13:45:47] Extract: takeout-20260220T133610Z-3-092.zip
[2026-02-22 13:45:57] Extract: takeout-20260220T133610Z-3-093.zip
[2026-02-22 13:46:06] Extract: takeout-20260220T133610Z-3-094.zip
[2026-02-22 13:46:13] Scanning media files...
[2026-02-22 13:46:14] Media files found: 4567
Invalid SOS parameters for sequential JPEG
[2026-02-22 13:50:31] Batch done. Total hashes now: 47130
[2026-02-22 13:50:31] Stats: moved=56, duplicates=4511, sidecar_updated=2009, sidecar_repaired=0
[2026-02-22 13:51:53] Sidecar status (touched dirs): media=44669, missing_sidecar=23575
[2026-02-22 13:51:53] Delete ZIP: takeout-20260220T133610Z-3-091.zip
[2026-02-22 13:51:53] Delete ZIP: takeout-20260220T133610Z-3-092.zip
[2026-02-22 13:51:53] Delete ZIP: takeout-20260220T133610Z-3-093.zip
[2026-02-22 13:51:53] Delete ZIP: takeout-20260220T133610Z-3-094.zip
[2026-02-22 13:57:52] Sidecar repaired this batch: 5
[2026-02-22 13:57:52] Remove temp dir: C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Takeout_Zip\_work\0005_20260222_134536
[2026-02-22 13:57:57] Free space now: 86.51 GB
[2026-02-22 13:57:57] ----------------------------------------
[2026-02-22 13:57:57] All done.
[2026-02-22 13:57:57] Output root (LOCAL): C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Photos_Backup\From_Google_Takeout
[2026-02-22 13:57:57] Hash DB: C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Photos_Backup\From_Google_Takeout\_hashes_sha256.txt
[2026-02-22 13:57:57] Bad file log: C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Photos_Backup\From_Google_Takeout\_bad_files.txt

기본 작업 단위는 4개의 zip 파일이며, -BatchSize N 옵션을 통해 변경할 수 있다. 컴퓨터에 충분한 작업 공간이 없으면(-MinFreeGB) 자동으로 작업을 멈춘다. 

Zip 파일 목록에 대하여 반복 작업을 할 필요가 없다. 실행 순간 -ZipDir에 존재하는 zip 파일을 자동적으로 배치 사이즈에 따라서 처리한 뒤, 다음 파일에 대한 작업을 이어가기 때문이다.

개념을 잡고 스크립트의 초기 버전을 만든 뒤 완성판을 만드는 데 삼일 정도 소요된 것 같다. 이 작업을 통해 구글 포토가 사진을 어떻게 관리하는지 어렴풋하게나마 이해할 수 있었다. 구글 포토 앨범은 파일을 담는 폴더가 아니라 일종의 가상 모음(태그)이다. 구글 포토 내부에서는 이를 '참조'로 취급하지만, 테이크아웃으로 가지고 나오면 모든 참조가 파일의 복사본으로 처리되어 나온다. 따라서 SHA-256 해시 기반 dedup를 하지 않을 수가 없다.

위 화면 출력에서 마지막 Stats: 라인에 주목해 보자. 4개의 압축 파일을 풀어서 생성된 4500개가 넘는 미디어 파일 중 4511개가 중복(duplicates)이었다. 작업의 마지막이므로 대부분은 이전의 zip 파일에서 다루어진 것이라 이미 SHA-256 해시 파일(_hashes_sha256.txt)에 기록이 되어 있다는 의미이다. 해시 파일은 잘 보존해 두고 내년에 새롭게 작업을 할 때 참조 및 갱신을 하면 된다.

Stats: moved=56, duplicates=4511, sidecar_updated=2009, sidecar_repaired=0

또한 JSON sidecar의 신뢰도 문제, EXIF 읽기 실패, 잘못된 epoch 해석 등 여러 예외 상황을 단계적으로 점검하고 PowerShell 스크립트를 반복 개선하였다. 실제로 JSON 파일을 갖고 있는 파일이 그렇게 많지 않았기에 EXIF를 읽어서 사진 촬영 날짜를 알아내야 하는데, 이 동작이 잘 되지 않아서 애를 먹었다. 대부분의 파일이 2026년(fallback)으로 분류된 것을 모르고 있다가 나중에 폴더를 직접 열어본 뒤 문제점이 심각하다는 것을 알게 되었다. 특히 FromFile 우선 EXIF 읽기 방식으로 전환하고, 연도 추정 로직의 fallback 오염을 차단한 것이 정확도를 크게 높였다. 이에 대한 상세한 기록은 Milestone Report: 1107 -> 28 문서에 있다.

결과적으로 이번 작업은 단순한 백업을 넘어, 클라우드 중심 뷰 모델을 파일 중심 아카이브로 안정적으로 변환하는 데이터 정제 파이프라인을 확립했다는 점에서 의미 있는 성과였다. 덩달아 나의 GitHub 사이트에도 두 개 프로젝트의 리포지토리가 생겼다.



작업 환경으로 익숙하지도 않은 Windows PowerShell을 선택한 것은 정말 잘 한 일이었을까? 데이터 과학 실무 차원에서 이번 프로젝트의 의미는 무엇이었을까? ChatGPT에게 마무리를 부탁하였다.

결론: 이번 선택은 타당했다

상황을 종합하면 작업 환경으로 Windows PowerShell을 선택한 것은 “잘한 선택”에 더 가깝다. 특히 이번 프로젝트의 성격을 고려할 때 PowerShell은 매우 현실적이고 효율적인 도구였다. 다만 장기적으로는 PowerShell 단독 운용보다는 역할 분리를 통한 구조화가 더 큰 이점을 제공한다.

왜 PowerShell이 잘 맞았는가

  • Windows 파일시스템 및 OneDrive와의 높은 궁합
    대량 파일 복사, 이동, 삭제, 속성 처리, 긴 경로 대응 등 운영 작업에서 PowerShell은 매우 안정적이었다.
  • 배치 오케스트레이션에 강점
    7-Zip 호출, 배치 반복 실행, 로그 및 통계 생성 같은 파이프라인 제어 작업에 적합했다.
  • .NET 접근성
    메타데이터 처리와 시간 정보 조작을 즉석에서 구현하며 파이프라인을 빠르게 개선할 수 있었다.

PowerShell이 드러낸 한계

  • Windows PowerShell 5.1의 문법 제약
    삼항 연산자 미지원 등으로 코드가 장황해지고 방어 로직이 늘어나는 문제가 있었다.
  • 이미지/EXIF 처리의 함정
    .NET 기반 이미지 라이브러리는 상황에 따라 실패 사례가 존재하여 디버깅 비용이 증가했다.
  • 스크립트의 프로그램화
    JSON 처리, 시간 추정, 예외 규칙이 누적되면서 스크립트가 점점 대형 프로그램처럼 비대해지는 경향이 나타났다.

권장되는 다음 단계 전략

  1. PowerShell은 메인 드라이버로 유지
    압축 해제, 배치 루프, 파일 이동, OneDrive 반영, 로그 생성 등 오케스트레이션 역할을 담당한다.
  2. 복잡한 판정 로직의 선택적 분리
    촬영연도 추정, EXIF/JSON 병합, 정규식 기반 예외 처리 등은 Python 등 별도 엔진으로 분리하면 테스트와 유지보수가 쉬워진다.
  3. 가능하면 PowerShell 7(pwsh)로 전환
    최신 문법, 성능 개선, 병렬 처리 지원 등으로 Windows PowerShell 5.1의 제약을 상당 부분 해소할 수 있다.

요약

이번 프로젝트를 완주하는 데에는 PowerShell이 매우 현실적이고 적절한 선택이었다. 앞으로는 PowerShell은 오케스트레이션, Python 등은 판정 엔진으로 역할을 분리하면 대규모 사진 아카이브 파이프라인의 안정성과 유지보수성이 한층 더 향상될 것이다.

데이터 과학 실무 관점에서 본 이번 작업의 의미

이번 작업은 단순한 사진 백업을 넘어, 비정형 개인 데이터를 신뢰 가능한 분석 자산으로 전환하는 데이터 엔지니어링 사례라는 점에서 실무적 의미가 크다. 데이터 과학 프로젝트는 모델링 이전 단계에서 데이터 품질 문제로 좌초되는 경우가 많으며, 이번 파이프라인 구축 과정은 그 핵심 병목을 정면으로 다루었다.

1) 데이터 모델 간 불일치 해소

Google 포토의 뷰(view) 중심 구조와 로컬 파일 시스템의 객체 중심 구조는 근본적으로 다르다. 이를 이해하고 SHA-256 기반 중복 제거, JSON/EXIF 병합, 연도 추정 로직을 설계한 것은 이질적 데이터 표현을 정규화(normalization)한 전형적인 데이터 엔지니어링 작업이다.

2) 재현 가능한 데이터 정제 파이프라인 구축

PowerShell 스크립트의 배치 처리, 로그 기록, 통계 출력은 일회성 정리가 아니라 반복 실행 가능한 ETL(Extract-Transform-Load) 흐름을 형성한다. 이는 향후 추가 Takeout이나 대규모 미디어 유입에도 동일한 품질 기준을 적용할 수 있게 한다.

3) 데이터 신뢰도 향상(Data Reliability Engineering)

EXIF 읽기 실패 대응, epoch 해석 오류 수정, fallback 오염 차단 등은 단순 편의 기능이 아니라 데이터 계보(lineage)와 정확도를 보존하는 품질 관리 활동에 해당한다. 특히 해시 기반 검증을 도입한 점은 데이터 무결성 보장의 모범 사례다.

4) AI-ready 개인 아카이브 구축의 전초 단계

연도 정렬, 중복 제거, 메타데이터 정합성 확보가 완료된 미디어 저장소는 향후 이미지 검색, 개인 라이프로그 분석, 멀티모달 모델 학습 데이터로 확장할 수 있는 기반이 된다.

요약

종합하면, 이번 프로젝트는 “백업 자동화”를 넘어 데이터 수집 → 정제 → 검증 → 구조화 → 장기 보존으로 이어지는 실무형 데이터 파이프라인을 개인 환경에서 구현했다는 점에서 높은 실무적 가치를 지닌다.


2026년 2월 20일 금요일

구글 포토에서 원드라이브로: PowerShell 스크립트를 이용한 개인 사진 아카이브 재정비

구글 드라이브가 점점 파일로 채워져서 용량을 업그레이드하라는 경고를 자주 받게 되었다. 가장 많은 용량을 차지하는 것은 구글 '포토'이다. 마이크로소프트 오피스 365 구독을 통해 소유하고 있는 1TB의 공간에 이를 옮기기로 결정하고 실제 실행에 옮긴 기록을 남기고자 한다. 이 파이프라인의 핵심은 구글 테이크아웃과 Windows PowerShell 스크립트이다. ChatGPT의 도움으로 개발한 이 스크립트의 특징은 글 마지막 부분에 소개하였다.

구글 테이크아웃은 구글 서비스에 등록된 모든 자료를 2GB 단위의 zip 파일로 분할하여 다운로드 링크를 제공한다. 나의 경우에는 총 93개의 파일이 생성되었다. 이 파일의 이름(001, 002...)은 연도순으로 붙여지는 것이 아님에 유의하자.

Zip 파일을 모두 다운로드하여 PC에서 압축을 해제한 뒤 그냥 원드라이브에 밀어 넣으면 되는가? 안타깝게도 구글 포토와 같이 촬영일자에 따른 미디어 정리라든가 앨범 정보 같은 것이 그대로 따라가지는 않는다. 따라서 PC에서 zip 파일을 받은 뒤 내부에 포함된 JSON 파일을 이용하여 각 미디어 파일을 연도별 폴더로 나누어 넣는 일이 핵심이다. 이 과정에서는 PowerShell 스크립트인 takeout_batch_year.ps1가 매우 중요한 역할을 하였다(개인 리포지토리로 이용하는 DokuWiki에서는 업로드할 수 있는 파일의 확장자를 제한하고 있기 때문에 zip으로 압축하여 올렸음). 이 스크립트는 여러 차례에 걸쳐 수정하면서 기능을 개선하였고 안정적인 동작을 하는 것을 최종적으로 확인하였다.... 아, 나중에 발견하였지만 꽤 심각한 문제점이 있었다. 이 글의 끝부분을 참조하기 바란다.

스크립트 작성에서는 로컬 PC에 저장 공간이 별로 많이 남지 않았다는 것을 고려하여 작동하도록 많은 신경을 썼다. 내 노트북 컴퓨터에서는 여유 공간이 별로 없어서 180GB가 넘는 총 93개의 zip 파일을 한꺼번에 다운로드하여 작업하는 것이 근본적으로 불가능하였다. 컴퓨터에 남은 여유 저장 공간을 점검하면서 일정 개수의 zip 파일을 다운로드하여 처리한 뒤 원드라이브 업로드 후에는 지워서 공간을 확보하고, 다음 차례의 zip 파일을 처리하는 방식으로 진행하는 것이 기본 아이디어였다.

그러나 ChatGPT와 더불어 개발 작업을 계속하면서 스크립트의 성능이 점점 좋아졌다. -ZipDir로 지정한 디렉토리에 다운로드한 파일을 계속 밀어 넣으면 스크립트는 자동적으로 -BatchSize 단위로 처리를 한 뒤 작업이 끝난 zip 파일을 다른 위치(-DestRoot 하위의 _processed 폴더)로 옮긴다. 반복문을 돌릴 필요도 없으며, 다음 배치 작업 전에 자동적으로 저장공간이 얼마나 남아 있는지 확인하여 안전한 수준이 아니면(-MinFreeGB로 지정한 값보다 적은 경우) 자동으로 작업을 중단한다. 사용자는 작업이 끝나서 다른 위치로 옮겨진 zip 파일을 이따금씩 지우면 된다.

스크립트는 Downloads 폴더에 두고 여기에서 PowerShell 창을 열어서 다음과 같이 명령어를 실행하면 된다. 첫 줄 명령어는 지금 열려 있는 PowerShell에서 .ps1 스크립트를 실행하기 위해 정책을 변경하는 명령으로서 현재 열린 창에서만 유효하다. 반복된 테스트에 의하면 -BatchSize는 4~8 정도가 적당한 것 같다. 빠른 압축 해제를 위해서 반드시 7-Zip이 필요하다. 이 유틸리티를 설치한 뒤 실행파일인 7z.exe의 위치를 Path 환경변수에 지정해야 한다.

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

.\takeout_batch_year.ps1 `
  -ZipDir "C:\Users\jeong\Downloads\Takeout_Zip" `
  -DestRoot "C:\Users\jeong\Downloads\Photos_Backup\From_Google_Takeout" `
  -BatchSize 4 `
  -MinFreeGB 25

takeout_batch_year.ps1은 모든 미디어 파일에 대한 해시를 생성하여 한번 처리한 파일은 다시 작업하지 않는다. 따라서 작업 결과로 만들어진 _hashes_sha256.txt를 절대로 지워서는 안 된다. 1년이 지난 뒤 다시 구글 포토로부터 테이크아웃을 할 때, 증분 백업 같은 것은 지원하지 않는다. 지워지지 않고 남은 파일에 대해서 언제나 전체 백업을 할 뿐이다. 따라서 이 해시 파일은 유일한 작업 기록인 셈이니 이것 역시 작업 종류 후에는 원드라이브에 보관하는 것을 권장한다. zip 파일을 가져다가 똑같은 스크립트를 돌리면 압축 해제는 어쩔 수 없이 다시 돌겠지만, 해시에 이미 기록된 파일은 추가 작업을 하지 않는다.

그러므로 이번 이전 작업이 성공적으로 끝난 뒤에는 구글 포토에는 최근 5년 정도의 파일만 남겨 두는 것이 좋을 것이다. 

한 배치에 대한 작업이 끝난 뒤 Photos_Backup/From_Google_Takeout 아래에는 다음과 같이 연도별로 정리된 폴더가 생기고 미디어 파일은 그 아래에 분류된다. JSON 파일의 분석에 실패하면 자동으로 가장 최근 연도인 2026 폴더로 들어간다. 

스크립트 실행 후 연도별 폴더에 미디어 파일이 자동으로 분류되어 들어간다. 해시 파일과 문제점이 있는 파일의 기록이 여기에 남는다.

너무나 당연한 이야기지만 -ZipDir이나 DestRoot에 원드라이브를 지정해서는 안 된다. 스크립트 작업이 다 끝나면 C:\Users\jeong\Downloads\Photos_Backup\From_Google_Takeout은 폴더 그대로 원드라이브의 '사진' 폴더 하위로 보내면 된다. 

원드라이브는 구글 포토와 같은 수준의 앨범 작성이나 편집 기능 같은 것은 없다. 휴대폰에서 직접 원드라이브로 사진을 백업하게 만들면 휴대폰에 남아 있는 최신 사진의 경우 구글 포토와 비슷하게 관리할 수는 있다. 이는 PC에서는 원드라이브 -> 사진 -> Camera Roll에서 접근 가능하다. 오늘 글에서 설명한 아카이브 재정비 작업과는 별개이다. 

PowerShell 기반 takeout_batch_years.ps1 사진 아카이브 자동화 파이프라인의 주요 특징

  • Google Takeout ZIP을 배치 처리
    • ZipDir에 있는 *.zip 전체를 정렬해 순차 처리
    • -BatchSize(기본 4)개씩 묶어서 반복 실행(자동으로 다음 배치로 넘어감)
  • 배치별 임시 작업 폴더로 “누적 스캔” 방지
    • ZipDir\_work\<batchId>\... 형태로 배치 전용 작업 폴더 생성
    • 스캔 대상은 해당 배치 폴더만(이전 실행 잔여물로 미디어 수가 튀는 문제 방지)
    • -KeepWork 옵션이 없으면 배치 종료 후 작업 폴더 자동 삭제
  • 7-Zip 우선 사용 + 미설치 시 Expand-Archive 폴백
    • 7z.exe를 PATH에서 찾으면 7-Zip으로 빠르게 추출
    • 없으면 PowerShell Expand-Archive로 추출(상대적으로 느림)
  • 미디어 확장자만 선별 스캔
    • JPG/JPEG/PNG/GIF/WEBP/HEIC, MP4/MOV 등(스크립트의 $MediaExt 목록 기준)
  • 연도 폴더 분류 로직(우선순위 명확)
    • 1순위: Takeout JSON의 photoTakenTime.timestamp 또는 creationTime.timestamp
    • 2순위: (JPG/JPEG 한정) EXIF DateTimeOriginal(0x9003) → 없으면 DateTime(0x0132)
    • 3순위: 최후 수단으로 파일 LastWriteTime.Year 사용
  • JSON 매칭 성능 최적화
    • 폴더 단위로 JSON을 한 번만 읽어 dir → (basename→year) 캐시($JsonYearCache) 생성
    • 같은 폴더 내 파일은 캐시로 빠르게 연도 조회
  • 중복 제거의 핵심: 파일 내용 기반 SHA-256 해시
    • Get-FileHash SHA256로 파일 내용을 해싱
    • _hashes_sha256.txt에 누적 저장하여 다음 배치/다음 실행에서도 중복 스킵
    • 파일명/폴더가 달라도 내용이 같으면 중복으로 제거됨
  • 해시 DB 기록 안정화(버퍼링 + 재시도)
    • 해시를 메모리 버퍼($HashBuffer)에 모았다가 배치 끝에 한 번에 기록
    • Add-Content 실패 시 슬립을 두고 재시도(AppendTextWithRetry)
  • 파일 이동 실패에 대한 복구 로직
    • Move-Item 실패 시 재시도(MoveWithRetry)
    • 그래도 실패하면 Copy-Item 재시도 후 원본 삭제(가능한 경우)
  • 동일 파일명 충돌 방지
    • 대상 경로에 같은 이름이 있으면 __1, __2…를 붙여 저장(덮어쓰기 방지)
  • 문제 파일은 멈추지 않고 건너뛰며 기록
    • 해시 계산 실패/해시 null/이동·복사 실패 등의 경우 처리 중단 없이 스킵
    • _bad_files.txt에 유형과 경로(및 일부 오류 메시지) 기록
  • 디스크 여유공간 가드
    • -MinFreeGB(기본 25GB) 미만이면 배치를 진행하지 않음(안전 정지)
    • 배치 크기가 큰 경우 8→6→4로 자동 축소 시도 로직 포함
  • 처리 완료 ZIP 관리
    • 기본: 처리한 ZIP을 ZipDir\_processed로 이동(재처리 방지)
    • 옵션: -DeleteZips 지정 시 처리한 ZIP을 삭제(주의 필요)
  • 운영 로그가 명확
    • 배치 시작/추출/스캔된 미디어 개수/누적 해시 수/여유공간/ZIP 이동(또는 삭제) 등 타임스탬프 로그 출력
    • -VerboseLog 켜면 중복 스킵 등 상세 로그도 출력

이 스크립트는 아직 개선할 점이 남아 있다. 중복을 제거한 미디어 파일에 대해서 원본의 JSON 파일도 같이 가져와야 하지만, 현재는 미디어 파일만 최종 결과물로 남기게 되어 있기 때문이다. 고난의 시작! 더 큰 문제는 JSON이나 EXIF 정보가 있는 원본 미디어 파일임에도 불구하고 촬영일 정보를 제대로 추출하지 못하여 2026 fallback으로 분류되는 것이 상당히 많았다는 점이다. 지금은 이에 대한 개선 작업을 진행하고 있다. 결과는 다음번 글에 쓰도록 하겠다.


2026년 2월 19일 목요일

2026년 2월의 일본 여행, 그리고 원드라이브로 사진 자료를 옮기기 위한 준비 작업(Google Takeout)

설 연휴를 맞이하여 아내, 그리고 아들과 함께 일본 3박4일(2/14-2/17) 동안 일본을 여행하고 돌아왔다. 아들이 항공권과 호텔 및 방문 코스를 전적으로 마련한 이른바 '효도 관광'이었다. 우리 부부가 지불한 것은 대부분의 식비와 현지 교통비 정도였다. 들른 곳은 교토와 오사카. 항공편은 일본의 저가항공인 피치항공을 이용하였다. 주요 방문지는 다음과 같다.

  • 1일차: 오사카 덴포잔 마켓플레이스, 가이유칸 수족관('해유관'), 우메다 공중정원(기누타니 고지 천공 미술관 포함), 교토로 이동하여 1박
  • 2일차: 청수사(기요미즈데라), 교토 국립박물관, 오사카로 이동하여 2박
  • 3일차: 유니버셜 스튜디오 재팬
  • 4일차: 오사카성, 카이요도 피규어 박물관, 오사카 역에서 호라이551 만두를 사는 것으로 끝

돌아온 뒤에 가족들과 구글 포토로 사진을 공유하는 것이 힘겨워서 원드라이브를 적극 활용하기로 하였다. 나는 겨우 200GB 용량의 구글 드라이브를 쓰고 있었고, 이미 기존 파일이 187GB나 차지하고 있었기 때문에 용량이 거의 다 되어간다는 경고성 메시지를 계속 받는 중이었다. 요금제를 더 올려도 되지만, 기왕 쓰고 있던 마이크로소프트 원드라이브(1TB)를 앞으로 적극 활용하기로 결심하고 휴대폰의 사진 백업을 구글 포토에서 원드라이브로 바꾸었다. 구글 포토의 자료는 구글 테이크아웃에서 2GB 크기의 다운로드 링크 형태로 최신 내보내기를 요청하였다. 어젯밤 9시에 시작한 백업은 오후 2시 반이 조금 못된 지금 93개의 패키지, 총 용량 187.13GB로 다운로드 가능한 형태로 준비가 다 되었다. 다운로드 링크가 유지되는 시간은 약 일주일.

구글 포토를 당장 버릴 생각은 없다. 사진을 편집하려면 웹브라우저나 모바일 환경 모두에서 구글 포토가 원드라이보다는 더 익숙하기 때문이다. 대신 많은 양의 사진을 공유하려면 하나씩 눌러서 모은 뒤 구글 포토로 공유하지 말고 일 기반으로 임시 앨범을 만들어서 그 링크를 공유하는 방식으로 바꾸기로 하였다. 구글 포토에서 직접 사진이나 동영상을 하나씩 골라 모은 뒤 직접 공유하면 한번에 100개 정도가 한계이다.

휴대폰 사진을 원드라이브로 백업한다는 것은 현재 휴대폰에 저장된 사진에만 해당한다. 따라서 휴대폰을 새로 구입한 시점 이후의 사진만 백업이 될 것이다. 구글 테이크아웃은 구글 계정에 보관된 내 모든 서비스의 데이터를 골라서 파일로 묶는 것이다. 이를 위해서는 폴더를 풀어서 하나씩 원드라이브에 수작업으로 밀어 넣어야 한다. 아래에서 소개하겠지만 압축을 푼 그대로 밀어 넣어서는 대단히 곤란하다!

휴대폰 사진의 백업이 끝난 뒤 원드라이브 앱을 열어보았다. 그런데 예상과 다르게 2004년에 찍은 사진도 들어 있었다. 아마 집PC에서 당시에 찍은 디지털 카메라의 사진을 정리하다가 자동으로 원드라이브에 업로드된 것으로 보인다. 마이크로소프트 오피스를 구독형으로 이용하면서도 저장 공간에 대해서는 그다지 신경을 쓰지 않았기에 이러한 사실을 잘 모르고 있었다.

구글 테이크아웃으로 받은 첫 번째 파일의 압축을 해제해 보았다. 총 2,747개의 파일이 들어 있었다. 폴더의 구조는 다음과 같았다.



C:\Users\정해영\Downloads\takeout-2026....001\Takeout\Google 포토

1번 파일이니 가장 오래전에 찍은 사진이 들어 있으리라 생각했는데, 앨범(폴더)만 정리되어 있었다. 그러면 가장 마지막 것인 93번째 패키지에 옛날 사진이 들어 있으리라. 가장 마지막 것이라서 파일 크기는 2GB가 아닌 1.45G였다.


그러나 마지막 번호의 ZIP파일에도 하위의 '앨범' 폴더 없이 노출된 사진은 하나도 없었다. 더욱 이해하기 어려운 것은 '2025년의 사진'에는 겨우 9개의 사진과 3개의 json 파일이 들어 있다는 점이었다. 2025년에 사진을 9장만 찍었을 리가 없는데? 챗GPT에 물어보니 앨범에 넣지 않은 사진만 Photos from 20XX 폴더로 들어간다고 하였다. 하지만 나는 그렇게 앨범을 적극적으로 만들지 않았었다. 그러면 사진이 어디로 갔는가? 사라진 것은 아니다. 백업본의 용량은 구글 드라이브의 용량과 거의 같기 때문이다. 차이가 있다면 메일이나 기타 문서일 것이다. 

수동으로 앨범을 만들지 않았더라도 구글 포토에는 숨겨진 앨범 생성 메커니즘이 있다고 한다. 예를 들어 한 번이라도 공유한 적이 있는 묶음이라면 구글 포토 내부에서는 앨범 객체로 관리한다는 것. 그리고 아카이브의 번호(001~093)은 사진 생성일과는 관계가 없다.

구글 Takeout은 조금이라도 그룹 정보가 있으면 앨범으로 보낸다(과잉 분류 성향).

따라서 이렇게 마련한 백업파일을 PC에서 풀어서 그대로 원드라이브에 올리면 사진 중복의 대혼란 파티가 열릴 수 있다. 구글 포토는 편집용으로 유지하되 사진의 장기 보존용으로만 원드라이브를 쓰겠다는 전략은 매우 합리적이며, 아주 조심스럽게 원드라이브로 옮기는 작업을 해야 한다. 챗GPT가 제안한 체크리스트는 다음과 같다. 여기에서 2~6에 해당하는 작업을 자동으로 해 주는 Windows PowerShell 스트립트를 만들고 테스트하느라 몇 시간을 소비하였다. 생각보다 수고가 많이 들어가는 작업이라서 별도의 글로 포스팅하였다(구글 포토에서 원드라이브로: PowerShell 스크립트를 이용한 개인 사진 아카이브 재정비).

OneDrive 사진 이전 체크리스트

  1. Takeout ZIP 전체 다운로드 완료
  2. 모든 ZIP 동일 폴더에 압축 해제
  3. 사진/영상 파일만 별도 폴더 추출
  4. 중복 파일 제거 실행
  5. 촬영일 기준 연도 폴더 정리
  6. OneDrive 폴더 구조 사전 생성
  7. 연도별 순차 업로드
  8. 웹에서 동기화 완료 확인
  9. 휴대폰 Camera Roll과 분리 유지 

일본 여행 사진 중 몇 장을 소개하면서 글을 마무리하고자 한다.












돌아오는 날, 오사카역(우메다 지역)에서 간사이 공항으로 출발하는 하루카 특급열차를 타기 위해 21번 플랫폼을 찾는 여정은 너무나 험난하였다. 한국어 자격증이 있는 직원(청소원으로 보였음)이 가는 길을 친철히 설명하면서 길 초입에 같이 뛰어 주지 않았다면 아마 제 시간에 기차를 타지 못했을 것이다.  

시간이 별로 없습니다. 조또(ちょっと) 설명 드리겠습니다...

2026년 2월 13일 금요일

생명과학 분야의 AI-ready 데이터란 무엇인가?

들어가며

최근 생명과학과 인공지능(AI)의 결합은 더 이상 낯선 이야기가 아니다. 유전체 분석, 신약 개발, 단백질 구조 예측, 임상 데이터 분석 등 다양한 영역에서 AI는 이미 핵심 도구로 자리 잡고 있다. 그러나 한 가지 질문이 남는다.

“우리의 데이터는 과연 AI를 바로 학습시킬 수 있는 상태인가?”

이 질문에 답하기 위해 등장한 개념이 바로 AI-ready data이다.


AI-Ready Data의 의미

생명과학 분야에서 AI-ready data란 단순히 디지털 파일이 존재한다는 뜻이 아니다. AI 모델이 별도의 대규모 수작업 전처리 없이 즉시 학습과 추론에 활용할 수 있도록 구조화·정제·표준화·법적 정합성을 갖춘 데이터 상태를 의미한다.

즉, “데이터가 있다”는 것과 “AI가 쓸 수 있다”는 것은 전혀 다른 문제이다.


AI-Ready 데이터의 핵심 조건

  • 기계가 읽을 수 있는 구조 (PDF 보고서가 아닌 구조화된 포맷)
  • 표준화된 형식 (FASTQ, VCF, FHIR 등 국제 표준 기반)
  • 용어·단위의 정렬(harmonization)
  • 결측치 및 오류 정제
  • 지도학습이 가능한 레이블 존재
  • 법·윤리적 이용 근거 확보

이 중 어느 하나라도 빠지면, 데이터는 존재하더라도 AI-ready 상태라고 보기 어렵다.


분야별 예시

1. 유전체 데이터

유전체 분야에서는 다음과 같은 조건이 충족되어야 한다.

  • 품질 검증(QC)이 완료된 FASTQ
  • 정렬이 끝난 BAM 파일
  • 동일 reference build 기준의 VCF
  • 정형화된 phenotype 메타데이터
  • IRB 또는 동의 기반의 합법적 이용 근거

reference genome이 섞여 있거나, 표현형 정보가 서술형 텍스트로만 존재한다면 AI 학습용 데이터로 사용하기 어렵다.

2. 신약 개발 및 단백질 구조 데이터

단백질 구조 파일의 형식이 일관되지 않거나, binding affinity 단위가 뒤섞여 있다면 AI 모델은 제대로 학습하기 어렵다. SMILES 표현의 표준화와 타깃 명칭의 정렬 또한 필수적이다.

3. 임상 및 바이오메디컬 데이터

  • ICD, SNOMED 코드화
  • 단위 통일
  • FHIR 기반 구조화
  • 비식별화 처리
  • 시간 정보(timestamp) 정규화

임상 데이터는 특히 법적·윤리적 요건을 충족하지 않으면 AI-ready가 될 수 없다.


FAIR와 AI-Ready의 차이

FAIR 원칙(Findable, Accessible, Interoperable, Reusable)은 데이터 공유를 위한 기준이다. 반면 AI-ready는 한 걸음 더 나아가 “기계 학습이 가능한 상태”를 요구한다.

수치 일관성, feature 생성 가능성, 레이블 품질, 데이터 편향 관리까지 포함하는 개념이 AI-ready라고 할 수 있다.


데이터 성숙도 관점

단계설명
Level 0원자료(raw)
Level 1정제 완료
Level 2표준화
Level 3메타데이터 완비
Level 4ML 학습 즉시 가능
Level 5대규모 foundation model 학습 가능

많은 국가 인프라는 Level 2~3에 머무르는 경우가 많다. 그러나 산업과 AI 모델은 Level 4~5를 요구한다. 이 간극이 현재 바이오 데이터 전략의 핵심 병목이다. 여기에서 제시한 6개 단계는 특정 표준 규격이 아니라 설명 목적으로 제시한 것이다.


맺음말

AI-ready data는 단순한 기술 용어가 아니다. 이는 데이터 표준, 품질 관리, 법적 정합성, 국가 전략, 그리고 미래 산업 경쟁력과 직결된 개념이다.

이제 질문은 하나로 정리된다.

“우리는 데이터를 저장하고 있는가, 아니면 AI를 준비시키고 있는가?”

AI-ready data의 단순한 현황 집계(따라서 많은 행정력을 낭비하게 되는)를 비판적으로 바라본 별도의 글('The Illusion of Measuring AI-Ready Data, AI 데이터는 숫자로 세어지는가')로 작성해 두었다. 데이터를 AI-ready 형태로 만드는 일, 심지어 데이터가 AI 활용 가능한 상태인지 판별하는 일 자체도 연구의 영역일 수 있다. 


이 글은 정해영의 아이디어를 바탕으로 AI(ChatGPT)의 도움을 받아 작성되었습니다. CC0 1.0으로 자유 이용 가능하며, 정확성 및 법적 책임은 보장하지 않습니다. This text was written with AI (ChatGPT) assistance based on the author’s ideas. Released under CC0 1.0. No guarantee of accuracy is provided, and no liability is assumed.