본문으로 건너뛰기
2026. 6. 25
© WONKOOK LEE

이 API는 누가 부르나요?

세 종류의 호출자 — 클라이언트, 어드민, 그리고 다른 도메인의 서버

이 글은 직무 통합 과정에서 백엔드 실무를 맡게 된 프론트엔드 개발자가 실제 작업을 부딪히며 배운 것들을 주제 단위로 정리하는 시리즈입니다. 낯선 개념을 이미 아는 개념에 대응시키는 방식으로 씁니다.

  1. 도메인 모델은 왜 DB를 몰라야 할까요?
  2. DB 조회는 왜 아웃바운드일까요?
  3. 그 로직은 어디에 살아야 할까요?
  4. 이 API는 누가 부르나요? — 이 글
  5. Response는 모델을 닮아야 할까요?
  6. null은 비우기일까요, 건드리지 않기일까요?
  7. 컬럼일까요, JSON 컬럼일까요?
  8. DB 스키마에도 git이 필요할까요?
  9. 백엔드 도구들, FE로 치면 무엇일까요?

조회·수정 API를 만들고 나서 "다른 도메인 서버가 이 데이터를 쓸 수도 있으니 인터널 API도 지금 뚫어둘까요?"라고 물었습니다. 돌아온 답은 간단했습니다 — "필요하면 그때 만들면 됩니다." 그 짧은 대답 안에 API를 종류로 나누는 기준과, 만들지 않는 것도 설계라는 감각이 함께 들어 있었습니다.

같은 데이터를 내주는 API인데 왜 종류가 나뉘고, 그 기준은 무엇일까요?


이 글에서 다루는 내용

지난 글 끝에서 "권한을 어디에 거는가"를 한 층 더 밀면 API의 종류 이야기가 된다고 예고했습니다. 이번 글은 그 이야기입니다 — API를 퍼블릭·오퍼레이션·인터널로 나누는 기준(호출자), 인터널 API의 경계가 네트워크가 아니라 도메인 사이에 그어지는 이유, 그리고 문에서 통제하고 안에서는 신뢰하는 권한 구조를 다룹니다.





1. API는 세 종류입니다

기능적으로는 같은 데이터를 내주더라도 호출자가 누구냐에 따라 API는 세 종류로 나뉩니다.

종류호출자권한
퍼블릭(public)실제 고객의 클라이언트제어한다
오퍼레이션(operation)어드민·백오피스운영자 권한
인터널(internal)다른 도메인의 서버 (서버-투-서버)보통 느슨하게

처음엔 "API면 다 같은 API지, 왜 굳이 종류를 나누나" 싶었습니다. 그런데 이 셋은 호출자가 다르기 때문에 계약의 성격이 다릅니다. 퍼블릭은 불특정 다수의 고객이 부르니 권한을 엄격하게 제어하고 하위 호환에 민감합니다. 오퍼레이션은 운영자용이라 강력한 기능이 열리되 운영자 권한으로 잠급니다. 인터널은 신뢰된 서버끼리의 통로라 상대적으로 느슨합니다. 하나의 컨트롤러에 뭉쳐두면 이 세 가지 성격이 한 코드에 섞이게 됩니다.

프론트엔드에도 이 감각의 대응물이 있습니다. 패키지를 만들 때 public export(index.ts에서 내보내는 것)와 내부 모듈을 구분하는 것 — 같은 코드라도 "누가 가져다 쓰는가"에 따라 계약의 엄격함이 달라지는 그 구분입니다. 파일 안 주석("내부용입니다, 직접 import 금지")이 아니라 모듈 경계로 구분을 그어버린다는 점까지 같습니다.


Recap

API는 호출자를 기준으로 퍼블릭(고객 클라이언트), 오퍼레이션(어드민), 인터널(다른 도메인 서버)로 나뉩니다. 셋은 권한의 엄격함과 하위 호환의 민감도가 서로 달라서 분리되며, 패키지의 public export와 내부 모듈을 나누는 프론트엔드의 감각과 같은 결입니다.




2. 인터널의 경계는 네트워크가 아니라 도메인입니다

셋 중에서 프론트엔드 개발자에게 가장 낯선 것이 인터널입니다. 처음엔 "내부망에서 부르는 API"라는 뜻인 줄 알았는데, 인터널의 경계는 네트워크(클러스터 안/밖)가 아니라 도메인과 도메인 사이입니다.

예를 들어 급여 도메인이 급여 명세를 만드는 상황을 생각해 보겠습니다. 급여 도메인이 가진 것은 구성원의 식별자뿐이고 이름과 소속 같은 구성원 정보는 프로필 도메인의 것입니다. 이때 클라이언트가 두 도메인을 각각 불러서 화면에서 합치는 게 아니라, 급여 서버가 프로필 도메인의 인터널 API를 불러 완성본을 만들어 내려줍니다. 서버가 서버를 부르는 것입니다.

이 목적은 프론트엔드가 이미 아는 패턴과 정확히 같습니다 — BFF(Backend for Frontend)가 여러 서비스를 합쳐 뷰모델을 만들어 내려주는 것. 클라이언트가 여러 번 왕복하는 대신 서버가 조립을 대신한다는 목적이 동일하고, 다만 그 조립이 BFF라는 전용 층이 아니라 도메인 서버들 사이의 인터널 호출로 일어난다는 점이 다릅니다.


Recap

인터널 API의 경계는 네트워크가 아니라 도메인 사이입니다. 다른 도메인의 데이터가 필요할 때 클라이언트가 여러 번 부르는 게 아니라 서버가 서버를 불러 완성본을 내려주며, 이는 BFF가 여러 서비스를 조립해 뷰모델을 만드는 것과 같은 목적입니다.




3. 문에서 통제하고 안에서는 신뢰합니다

세 종류를 운영하는 원칙으로 배운 것이 세 가지 있습니다.

첫째, 모든 API가 인터널을 갖는 것은 아닙니다. 필요하면 그때 만듭니다. 서두의 "필요하면 그때"가 이것입니다 — YAGNI(You Aren't Gonna Need It). 요구가 없는데 미리 뚫어두면 쓰이지 않는 계약을 유지 보수하는 비용만 남습니다. 인터페이스는 소비자가 나타났을 때 소비자의 요구로 설계되는 것이 건강합니다.

둘째, "인터널은 읽기 전용" 같은 규칙은 세우지 않습니다. 알림처럼 인터널이 생성(create)을 하는 경우도 있습니다 — 다른 도메인 서버가 "이 사용자에게 알림을 만들어 달라"고 부르는 식입니다. 상황마다 다른 것을 규칙으로 묶으면 규칙이 곧 기술 부채가 됩니다. 상황마다 다른 것은 규칙화하지 않는 것이 규칙입니다.

셋째, 권한 제어는 퍼블릭에 겁니다. 인터널은 문 안쪽입니다 — 문을 따고 들어온 사람은 과자를 먹든 아이스크림을 먹든 자유지만, 외부인은 그 문 자체를 못 엽니다. 모든 방마다 자물쇠를 다는 대신 현관에서 통제하고 안에서는 신뢰하는 구조입니다. 프론트엔드에서 라우트 가드가 페이지 진입을 막으면 그 안의 컴포넌트들은 권한을 다시 묻지 않는 것과 같은 배치입니다.

물론 "안에서는 신뢰"가 공짜는 아닙니다. 문 안쪽이 신뢰할 만하려면 인터널을 부를 수 있는 주체가 실제로 통제되고 있어야 합니다 — 이 전제가 무너지는 규모가 되면 서비스 간 인증 같은 장치가 추가되곤 합니다. 원칙의 이름은 신뢰지만 실체는 "경계 안의 비용과 경계의 강도를 맞바꾸는 선택"에 가깝습니다.

이렇게 어떤 API를 낼지 정하고 나면 다음 질문이 기다립니다 — 그 API의 응답은 어떤 모양이어야 하는가, 모델을 닮아야 하는가. 다음 글에서 다루겠습니다.


Recap

인터널은 필요할 때 만들고(YAGNI), 상황마다 다른 것은 규칙화하지 않으며, 권한은 문(퍼블릭)에서 통제하고 안에서는 신뢰합니다. 라우트 가드가 진입을 막으면 안쪽 컴포넌트는 권한을 다시 묻지 않는 프론트엔드의 배치와 같은 구조이되, "안에서의 신뢰"는 인터널 호출 주체가 통제되고 있다는 전제 위의 선택입니다.




FE ↔ BE 대응표

이 글에서 다룬 대응입니다.

BE 개념FE에서 가장 가까운 것대응의 핵심
퍼블릭 / 인터널 분리public export vs 내부 모듈호출자에 따라 계약의 엄격함이 다르다
인터널 APIBFF의 서버 간 조립클라이언트 대신 서버가 합친다
문에서의 권한 통제라우트 가드관문에서 막고 안에서는 신뢰



References

API 경계와 조립

  1. Sam Newman — Backends For Frontends
  2. Martin Fowler, James Lewis — Microservices

만들지 않는 설계

  1. Martin Fowler — Yagni


좋은 사람들과 재미있는 일을 하며 열정적이고 즐겁게 살고 싶은 개발자