백엔드 관점에서 API 소비: 여러 엔드포인트의 데이터 정규화

발행: (2026년 1월 19일 오후 11:06 GMT+9)
9 min read
원문: Dev.to

I’m happy to translate the article for you, but I’ll need the actual text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source link and all formatting exactly as you requested.

모든 것이 시작된 곳

첫 번째로 사용한 API는 Open Library API였습니다. 작동은 했지만 일관되지는 않았습니다.

  • 일부 책은 ISBN 없이 반환되었습니다.
  • 다른 책들은 설명이 없었습니다.
  • 경우에 따라 저자 데이터가 약간 부정확하거나 불완전하게 느껴졌습니다.

처음에 나는 생각했습니다:

“아마도 이게 전부일지도 몰라요.”

하지만 더 풍부한 데이터가 필요했기에 두 번째 소스로 Google Books API를 추가했습니다. 내 생각은 간단했습니다:

“한 API에 무언가가 없으면, 다른 API에 그게 있을 가능성이 높다.”

그 부분은 사실이었습니다. 그러나 예상하지 못했던 새로운 문제들이 뒤따랐습니다.

상황이 복잡해지기 시작한 곳

한 번에 두 API에서 데이터를 소비하기 시작하자 거의 즉시 몇 가지를 눈치챘습니다:

  • 같은 책이 여러 번 나타났습니다.
  • 저자 이름이 다르게 포맷되었습니다.
  • ISBN이 한 응답에는 있었지만 다른 응답에는 없었습니다.
  • 설명이 항상 일치하지 않았습니다.

같은 책. 진실의 다른 버전.

간단한 예시

Open Library response

{
  "title": "The Hobbit",
  "authors": [{ "name": "J.R.R. Tolkien" }],
  "isbn_10": ["0345339681"]
}

Google Books response

{
  "volumeInfo": {
    "title": "The Hobbit",
    "authors": ["J. R. R. Tolkien"],
    "industryIdentifiers": [
      { "type": "ISBN_13", "identifier": "9780345339683" }
    ]
  }
}

두 응답 모두 정확하고 같은 책을 설명합니다. 하지만 이 데이터를 as‑is 그대로 저장한다면, 문제를 초래하게 됩니다.

실제 문제 (내가 깨닫는 데 시간이 걸린 문제)

문제는 Open Library가 아니었고, 확실히 Google Books도 아니었습니다. 문제는 외부 API들이 서로 일치할 것이라고 내가 가정한 것이었습니다. 실제로 그렇지 않습니다.

각 API는 자체적인 구조, 우선순위, 그리고 “완전한” 데이터가 어떤 모습인지에 대한 개념을 가지고 있습니다. 바로 그때 모든 것을 조용히 해결해 준 개념을 만나게 되었는데, 바로 정규화(Normalization) 입니다.

그래서… 정규화란 무엇인가?

가장 간단히 말하면:

정규화는 데이터가 어떻게 보여야 할지를 결정하고
그 외의 모든 것을 그에 맞추도록 강제하는 것입니다.

비전문가를 위해

  • 저장하기 전에 정보를 정리하고 표준화하는 것입니다.
  • 한 권의 책이 약간씩 다른 다섯 개의 정체성을 갖게 되는 일을 방지하는 것입니다.

기술자를 위해

  • 외부 API 응답을 하나의 내부 스키마로 매핑하는 것입니다.

어느 쪽이든 아이디어는 동일합니다:

하나의 시스템. 하나의 구조. 하나의 진실된 출처.

정규화가 실제로 중요한 이유

정규화 전 나는:

  • 데이터베이스에 중복된 책이 있었다.
  • 저자 이름이 일관되지 않았다.
  • ISBN 조회가 신뢰할 수 없었다.

정규화 후 나는:

  • 한 책 = 하나의 레코드.
  • 예측 가능한 필드.
  • 하위 로직이 훨씬 깔끔해졌다.

화려하지는 않지만, 나중에 디버깅에 드는 시간을 조용히 절약해준다.

Source:

정규화 달성

1단계: “책”이 당신에게 의미하는 바 정의하기

API 로직을 건드리기 전에, 나는 간단한 질문에 답해야 했다:

“내 시스템 안에서 책은 어떻게 보이는가?”

내가 선택한 구조는 다음과 같다:

Book = {
    "title": str,
    "authors": list[str],
    "isbn_10": str | None,
    "isbn_13": str | None,
    "description": str | None
}

이것이 내 기준점이 되었다. 외부에서 들어오는 모든 데이터는 이 형태에 맞게 재구성되어야 했다.

2단계: 각 API를 별도로 정규화하기

로직을 뒤섞지 않고, 각 API를 독립적으로 다루었다.

Open Library 정규화

def normalize_openlibrary(data):
    return {
        "title": data.get("title"),
        "authors": [a.get("name") for a in data.get("authors", [])],
        "isbn_10": data.get("isbn_10", [None])[0],
        "isbn_13": data.get("isbn_13", [None])[0],
        "description": data.get("description")
    }

Google Books 정규화

def normalize_googlebooks(data):
    info = data.get("volumeInfo", {})

    isbn_10 = None
    isbn_13 = None

    for identifier in info.get("industryIdentifiers", []):
        if identifier["type"] == "ISBN_10":
            isbn_10 = identifier["identifier"]
        elif identifier["type"] == "ISBN_13":
            isbn_13 = identifier["identifier"]

    return {
        "title": info.get("title"),
        "authors": info.get("authors", []),
        "isbn_10": isbn_10,
        "isbn_13": isbn_13,
        "description": info.get("description")
    }

이 시점에서 두 API는 마침내 같은 언어를 사용하게 되었다.

3단계: 중복 없이 병합하기

정규화는 데이터를 동일한 형태로 만든다. 병합은 어느 데이터가 우선할지를 결정한다.

내 규칙은 간단했다:

  • ISBN‑13이 있으면 그것을 우선한다.
  • 설명이 없을 경우 Google Books를 대체 데이터로 사용한다.
def merge_books(primary, fallback):
    return {
        "title": primary["title"] or fallback["title"],
        "authors": primary["authors"] or fallback["authors"],
        "isbn_10": primary["isbn_10"] or fallback["isbn_10"],
        "isbn_13": primary["isbn_13"] or fallback["isbn_13"],
        "description": primary["description"] or fallback["description"],
    }

특별한 트릭은 없으며, 명확한 규칙만 있을 뿐이다.

내게 도움이 된 사고 모델은 다음과 같다: API는 원재료이고, 정규화는 레시피이며, 데이터베이스는 최종 요리다. 레시피 없이도 음식을 만들 수는 있지만, 자신 있게 제공할 수 있는 요리는 아니다.

내가 얻은 교훈

  • 외부 API가 일치한다고 가정하지 마세요.
  • 초기에 단일 진실의 원천을 정의하세요.
  • 병합하기 전에 각 소스를 정규화하세요.
  • 병합 로직을 단순하고 결정적으로 유지하세요.
  • 지금 데이터 위생에 투자하세요; 나중에 보답을 받을 것입니다.

코딩을 즐기세요, 그리고 여러분의 데이터가 항상 깨끗하길 바랍니다!

PIs don’t owe you consistency

  • 더 많은 데이터 소스 = 더 큰 책임
  • 규모가 커지면 정규화는 선택 사항이 아니다

무엇보다도, 백엔드 작업은 단순히 데이터를 가져오는 것이 아니라, 시스템에서 진실이 어떤 모습인지 결정하고 이를 강제한다는 것을 배웠습니다.

여러 API를 사용하고 있는데 뭔가 약간 어긋난 느낌이 든다면, 정규화가 빠진 부분일 가능성이 높습니다.

행복한 개발 되세요 🚀

Back to Blog

관련 글

더 보기 »

왜 Java 또는 C#를 공부해야 할까?

‘왜 Java 또는 C를 공부해야 하는가’에 대한 표지 이미지 https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploa...