[260722 17일차] OpenAPI · HuggingFace · Transformers · OCR

2026. 7. 22. 17:28AI 기반 프론트엔드 웹개발자 양성과정

# AI 활용 학습일지

[OpenAPI · HuggingFace · Transformers · OCR]
공공 API · LLM · NLP · 문자 인식

2026.07.22 · 학습 범위: 공공 OpenAPI(ITS CCTV), HuggingFace, Transformers, OCR

📋 오늘 다룬 것들

오늘은 "이미 만들어진 AI·데이터를 가져다 쓰는" 하루였다. 공공기관의 OpenAPI로 전국 CCTV 영상을 받아 YOLO로 분석하고, HuggingFace로 LLM 채팅과 이미지 생성을, Transformers로 문장 유사도·감정분석·요약·번역을, 마지막으로 OCR로 이미지 속 글자까지 뽑아봤다. 모델을 직접 학습하지 않아도 API·라이브러리 몇 줄로 이만한 걸 한다는 게 신기했다.

공공 API
apiKeyurllibjson_normalize
LLM 채팅
InferenceClientDeepSeek
이미지 생성
FLUX.1text_to_image
NLP
pipeline유사도감정분석
요약·번역
t5-smalldeep_translator
문자 인식
Tesseractpytesseract

🔌 공공 OpenAPI — ITS CCTV

OpenAPI는 정부·공공기관 데이터 창고의 자동문 같은 것. 사람이 직접 가지 않고 프로그램이 인증키(열쇠)를 들고 필요한 데이터만 꺼내온다. 오늘은 국토교통부 ITS(지능형교통시스템)에서 전국 도로 CCTV 영상 주소를 받아왔다.

# 설치 (urllib·json은 파이썬 기본 내장)
pip install pandas ultralytics opencv-python
💡 곁들여 배운 개념 — MCP — AI에 새 능력을 더해주는 "USB-C 같은 약속". 도구마다 다른 연결 방식을 하나의 표준으로 통일한 것으로, AI가 혼자 모르는 것도 도구(기상청·노션·캘린더 등)를 꽂으면 진짜 정보를 가져와 할루시네이션(그럴듯한 거짓말)을 줄인다. OpenAPI가 "데이터를 직접 호출"하는 방식이라면, MCP는 그걸 AI가 알아서 쓰게 연결하는 상위 개념.

① API 키 · 요청 URL

인증키를 발급받고, 도로 유형(its 일반 / ex 고속)·관심 영역(경위도 범위)·응답 형식(json)을 붙여 요청 URL을 조립한다.

url_cctv = (
    f"https://openapi.its.go.kr:9443/cctvInfo"
    f"?apiKey={key}&type={Type}&cctvType=1"
    f"&minX={minX}&maxX={maxX}&minY={minY}&maxY={maxY}"
    f"&getType={getType}"
)

② 응답 처리 (urllib → JSON → DataFrame)

URL로 요청을 보내 받은 응답을 bytes → str → dict → 표(DataFrame) 순으로 가공한 뒤, 원하는 CCTV의 스트림 주소를 골라낸다.

response = urllib.request.urlopen(url_cctv)          # 요청 → 응답
json_str = response.read().decode("utf-8")         # bytes → str
json_object = json.loads(json_str)                  # str → dict
cctv_play = pd.json_normalize(json_object["response"]["data"])  # dict → 표
test_url = cctv_play["cctvurl"][77]                   # 77번 CCTV 선택
왜 두 번 변환? — 서버는 전송용 bytes(0·1)로 보내니 사람이 읽으려면 decodestr(글자)로 풀고, 값을 꺼내려면 json.loadsdict(사전)로 바꿔야 ["키"]로 접근된다. CCTV 목록이 response → data 안에 숨어 있어서 pd.json_normalize로 평평한 표로 펴 인덱싱했다.

③ 함수화 + YOLO 통합

반복되는 API 호출을 its_cctv(번호) 함수로 묶으니, 다른 파일에서 import 한 줄로 CCTV 주소를 얻어 바로 YOLO에 연결할 수 있었다.

from v15_03_cctv_its_def import its_cctv  # 만들어 둔 함수 재사용

test_url = its_cctv(50)              # 17줄 코드가 1줄로
cap = cv2.VideoCapture(test_url)
model = YOLO("yolo11n.pt")
# while 루프에서 프레임마다 model(frame)로 실시간 탐지
함수화의 장점 — 재사용(import 한 줄), 매개변수(번호만 바꿔 다른 CCTV), 가독성(메인 로직에서 API 세부 숨김), 유지보수(주소·키 바뀌면 함수 1곳만 수정). 참고로 알라딘·기상청·카카오·네이버도 같은 방식(키 발급 → URL/헤더에 담아 요청 → JSON 파싱)으로 쓴다.

🤗 HuggingFace — LLM · 이미지 생성

HuggingFace는 전 세계 AI 모델·데이터셋을 무료 공유하는 최대 허브. InferenceClient 한 줄로 GPT급 LLM이나 이미지 생성 모델을 바로 호출할 수 있다.

pip install huggingface_hub   # HuggingFace 공식 SDK → InferenceClient·model_info·login 등 일체 제공
🔑 토큰은 .env — HuggingFace 토큰은 절대 코드·주석에 직접 쓰지 말고 .env(gitignore됨)에 저장한다. load_dotenv()로 읽어 os.environ["HF_TOKEN"]으로 꺼내 쓴다. 키가 코드에 박히면 GitHub에 그대로 노출된다.

① LLM 채팅 (DeepSeek)

chat.completions.create로 DeepSeek 모델에 질문을 보낸다. ChatGPT와 동일한 messages(role + content) 패턴이다.

client = InferenceClient(provider="auto", api_key=os.environ['HF_TOKEN'])
completion = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-V3.2:novita",  # :novita → 무료 라우팅
    messages=[{"role": "user", "content": answer}],
)
print(completion.choices[0].message)   # 후보 중 첫 응답
provider="auto"는 가장 빠른 무료 서버를 자동 선택. LLM은 단일 질문이 아니라 대화 이력(messages 리스트)을 입력받고, 답은 후보 N개 중 choices[0].message로 꺼낸다.

② 이미지 생성 (Text-to-Image, FLUX)

텍스트 설명을 주면 FLUX.1-dev가 그림을 그려 PIL.Image 객체로 돌려준다. 그대로 .save()하면 파일로 저장된다.

image = client.text_to_image(answer, model="black-forest-labs/FLUX.1-dev")
image.save("tti_result.jpg")
프롬프트는 영어로 쓰면 품질이 오른다. 스타일 키워드(anime style, photorealistic)와 품질 키워드(high quality, 4K, detailed)를 붙이면 좋다. 무료 서버 기준 1회 1~3분 걸린다.

🧠 Transformers — 자연어 처리(NLP)

pipeline은 모델 로드 + 토크나이저 + 후처리를 한 줄로 묶어주는 진입점. 태스크 이름만 주면 알맞은 모델을 자동으로 붙여준다.

pip install transformers
pip install -U "transformers==4.46.3"
pip install deep-translator

① 문장 유사도 (SentenceTransformer · 코사인)

문장을 임베딩(숫자 벡터)으로 바꾸고, 두 벡터 사잇각의 코사인 유사도로 의미가 얼마나 비슷한지 수치화한다. 단어가 달라도 의미가 같으면 1에 가깝다.

pip install sentence-transformers   # 문장 임베딩 전용 패키지
model = SentenceTransformer("all-MiniLM-L6-v2")   # 경량 임베딩 모델
emb1 = model.encode(sen1, convert_to_tensor=True)
emb2 = model.encode(sen2, convert_to_tensor=True)
cos_sim = util.pytorch_cos_sim(emb1, emb2)
# -1 반대 · 0 무관 · 1 완전히 동일
임베딩 = 문장을 의미 좌표로 — "강아지"와 "개"는 가까운 점, "강아지"와 "비행기"는 먼 점이 된다. 코사인 유사도는 두 화살표의 각도만 보므로(길이 무시) 문장 길이에 영향받지 않는다. 실제로 어순만 다른 문장은 0.94, 무관한 문장은 0.15가 나왔다.

② 감정 분석 (Sentiment)

영어 문장을 POSITIVE / NEGATIVE로 판별하고 신뢰도(0~1)를 준다.

classifier = pipeline("sentiment-analysis")
results = classifier("I feel calm")
print(results[0]['label'], results[0]['score'])  # POSITIVE 0.8280
scoresoftmax를 통과한 확률값(모든 값 합=1)이라 "확신도"로 읽을 수 있다. 단, 기본 모델은 영어 전용이고 중립·복합 감정은 잘 못 잡는 한계가 있다.

③ 텍스트 생성 (GPT-2 / KoGPT2)

시드 문장을 주면 뒤 단어를 한 토큰씩 예측해 이어붙인다. 한국어는 skt/kogpt2-base-v2를 썼다.

generator = pipeline("text-generation", model="skt/kogpt2-base-v2")
results = generator(answer, max_new_tokens=50, num_return_sequences=1, truncation=True)
max_new_tokens는 생성 길이 상한(안 주면 무한 생성 위험), truncation=True는 입력이 모델 최대 길이를 넘으면 잘라준다. (1 토큰 ≈ 영어 4글자)

④ 요약 (T5-small)

긴 영어 단락을 핵심만 뽑아 다시 쓴다. T5는 모든 작업을 "텍스트 → 텍스트"로 통일한 모델이다.

summarizer = pipeline("summarization", model="t5-small")
summary = summarizer(text, min_length=20, max_length=60, do_sample=False)
print(summary[0]['summary_text'])
Task Prefix — T5는 "summarize: 원문"·"translate English to Korean: ..."처럼 앞머리(접두사)로 작업을 지시받게 학습됐다. 한 모델로 요약·번역·분류가 다 되는 비결. pipeline("summarization")"summarize: "를 자동으로 붙여준다. do_sample=False는 매번 같은 결과(결정적 생성).

⑤ 요약 + 한국어 번역

T5는 영어만 잘하니, 요약(영어) 결과를 deep_translator의 GoogleTranslator로 한국어로 옮겨 한계를 보완했다(API 키 불필요).

from deep_translator import GoogleTranslator

def translate_ko(sentence):
    return GoogleTranslator(source='en', target='ko').translate(sentence)

ko_sum = translate_ko(sum_text)   # 영어 요약 → 한국어
파이프라인 흐름: 원문(영) → T5 요약 → 요약(영) → GoogleTranslator → 요약(한). 무료·키 불필요·다국어라 편했지만, 인터넷이 필요하고 호출이 많으면 차단될 수 있다.

🔤 OCR — 이미지 속 글자 읽기

OCR(광학 문자 인식)은 사진 속 글자를 읽어내는 기술. 구글 Tesseract 엔진을 파이썬 pytesseract로 감싸 사용한다.

① OCR 개요 & 설치

설치 순서 — ① Tesseract 실행 파일 설치 → ② Python 라이브러리 설치 → ③ 실행 파일 경로 지정

# ① Tesseract-OCR 설치 (Windows)
# 공식 설치 경로: https://github.com/UB-Mannheim/tesseract/wiki
# 설치 후 기본 경로: C:/Program Files/Tesseract-OCR/tesseract.exe
# (한국어 인식은 설치 시 Korean 언어팩 체크)
# ② Python 라이브러리 설치
pip install pytesseract pillow
pytesseract — 파이썬에서 Tesseract를 부르는 통역사.  PIL(pillow) — 사진 파일을 여닫는 파이썬 이미지 도구.

② 이미지 텍스트 인식 (v18_01_ocr_img.py)

PIL로 사진을 열고 image_to_string으로 글자를 뽑아내는 4단계 흐름이다.

1경로 지정tesseract_cmd로 Tesseract 실행 파일 위치 알려주기
2이미지 열기Image.open(경로)로 사진 파일 불러오기
3OCR 수행image_to_string(image, lang)으로 글자 추출
4결과 출력추출된 문자열 print
import pytesseract
from PIL import Image
import os

# 1. Tesseract 실행 파일 경로 지정
pytesseract.pytesseract.tesseract_cmd = "C:/Program Files/Tesseract-OCR/tesseract.exe"

# 2. 이미지 불러오기
image = Image.open("image.png")

# 3. OCR 수행
results = pytesseract.image_to_string(image, lang='eng')

# 4. 결과 출력
print(results)
# Optical Character
# Recognition (OCR)
핵심 함수
· pytesseract.tesseract_cmd — Tesseract 실행 파일 위치 알려주기
· Image.open(경로) — PIL로 사진 파일 열기
· image_to_string(image, lang) — 사진에서 글자 뽑아 문자열로 반환
· lang='eng' — OCR이 쓸 언어 지정 (언어팩 설치 필수)

③ lang 파라미터 & 결과 해석

lang은 OCR에게 읽을 언어를 알려주는 값. +로 여러 언어를 동시에 인식할 수 있다(예: eng+kor).

lang 값설명예시 코드
eng영어 (기본값, 별도 설치 없이 사용 가능)lang='eng'
kor한국어 (언어팩 별도 설치 필요)lang='kor'
eng+kor영어 + 한국어 동시 인식lang='eng+kor'
chi_sim중국어 간체lang='chi_sim'
jpn일본어lang='jpn'
# 영어 + 한국어 동시 인식
results = pytesseract.image_to_string(image, lang='eng+kor')
print(results)
· 결과에 줄바꿈(\n)이 포함됨 → .strip()으로 공백 제거
· 사진 해상도가 낮거나 글꼴이 특수하면 인식률 저하 → 전처리(흑백 변환·크기 조정)로 개선
· tesseract_cmd로 엔진 실행 파일 위치를 먼저 지정해야 함(설치 필수)
· 더 똑똑한 대안: 딥러닝 기반 EasyOCR · PaddleOCR

✍️ 마치며

오늘은 "밑바닥부터 만들기"가 아니라 "잘 만들어진 걸 조립하기"의 힘을 느낀 하루였다. 공공 API로 실시간 데이터를 끌어오고, HuggingFace·Transformers로 남이 학습해 둔 거대 모델을 몇 줄로 불러 쓰고, OCR로 이미지를 텍스트로 바꾸는 것까지 — 결국 중요한 건 각 도구의 입력·출력 형태(JSON 파싱, messages 리스트, 임베딩 벡터, lang 옵션)를 이해하고 이어 붙이는 감각이었다. .env로 키를 안전하게 관리하는 습관도 오늘 확실히 챙겼다. 다음엔 이 조각들을 엮어 작은 AI 서비스를 만들어볼 생각이다.

🏷️ OpenAPI  |  HuggingFace  |  Transformers  |  OCR  |  NLP  |  학습일지