Deep Learning + AI
Generator?
내인생왜이래
2026. 3. 12. 16:34
반응형
1. 제너레이터(Generator)의 쉬운 정의: "실시간 데이터 공장"
보통 우리가 리스트(list)를 사용하면 모든 데이터를 메모리에 한꺼번에 쌓아두고 사용하지만, 제너레이터는 데이터가 필요할 때마다 그 자리에서 하나씩 생성해서 배출하는 방식을 취합니다.
- 비유: 모든 요리를 미리 만들어 쌓아두는 '뷔페'가 아닌, 손님이 주문할 때마다 즉석에서 하나씩 요리해 내놓는 '오마카세 식당'
- 장점: 수십 페이지의 PDF 이미지를 한 번에 메모리에 올리면 컴퓨터가 멈출 수 있는데, 제너레이터를 쓰면 지금 처리할 조각만 메모리에 올리므로 대형 사고(메모리 부족)를 방지할 수 있습니다.
2. 데이터 저장 및 활용 흐름
이렇게 제너레이터가 실시간으로 뱉어낸 조각들은 다음과 같은 과정을 거쳐 저장되고 최종 JSON으로 변환됩니다.
단계 동작 방식 예시
| 수집 | list(generator) 명령으로 흩어진 조각들을 바구니에 모음 | all_pieces 리스트에 튜플 형태로 저장 |
| 분석 | asyncio.gather를 통해 여러 조각을 Gemini API에 병렬로 전송 | 헤더 분석, 치식 분석이 동시에 실행됨 |
| 조립 | inferred 내용(예: '묶는다'는 문구)을 보고 데이터 형식을 결정 | notation: single 또는 range로 확정 |
| 저장 | 생성된 result 폴더 안에 원본 파일명과 시각을 붙여 JSON 저장 | 갈수아님_result_143005.json |
all_pieces 리스트 내부 구조 예시
all_pieces = [
# 0번 인덱스: 헤더 (Prescription Header)
(0, "header", <header_img_ndarray>),
# 1번 영역 (Area 1): 치식 조각과 상세 정보 조각
(1, "target", <area1_target_img_ndarray>), # 십자선 위쪽 (치식)
(1, "excluded", <area1_excluded_img_ndarray>), # 십자선 제외 나머지 (재질/옵션)
# 2번 영역 (Area 2): 치식 조각과 상세 정보 조각
(2, "target", <area2_target_img_ndarray>),
(2, "excluded", <area2_excluded_img_ndarray>),
# ... (영역 개수에 따라 반복)
3. 프로젝트에서의 데이터 흐름
우리 코드에서는 dental_piece_generator라는 이름의 공장이 PDF라는 원석을 깎아 세부 조각들을 만들어냅니다.
Step 1: 데이터 배출 (yield의 역할)
하위 함수인 find_cross_by_horizontal_line에서 이미지를 자른 뒤, 결과를 return하지 않고 yield를 사용하여 밖으로 던져줍니다.
# 하위 제너레이터: 이미지 조각을 하나씩 밖으로 전달
def find_cross_by_horizontal_line(img, region_index):
# (생략) 십자선 찾기 로직
# 잘라낸 조각을 "지금 바로 가져가세요"라고 밖으로 보냄
yield (region_index, "target", cross_crop)
yield (region_index, "excluded", img_other)
Step 2: 중첩 전달 (yield from의 역할)
중간 관리자인 dental_piece_generator는 하위 함수가 뱉어낸 조각들을 받아서 최종 분석 함수인 run_full_extraction으로 끊김 없이 전달합니다.
def dental_piece_generator(pdf_path):
for data in area_gen:
# 하위 함수가 뱉는 조각들을 그대로 이어서 밖으로 배달
yield from find_cross_by_horizontal_line(img, idx)

반응형