Crohasang Logo
#12

[Fedify] 안쓰는 Loader API를 정리하자

2025년 9월 30일 오전 02:13

documentLoader 삭제 PR 🔗 https://github.com/fedify-dev/fedify/pull/393

contextLoader 삭제 PR 🔗 https://github.com/fedify-dev/fedify/pull/393

Issue 🔗 https://github.com/fedify-dev/fedify/issues/376

Fedify 2.0을 대비해 사용하지 않는 API들을 정리하는 이슈가 올라왔다. 해당 이슈를 확인해보면 없애야할 API 리스트가 있는데, 처음에는 API들을 전부 다 없애고 PR을 올릴까 했지만 멘토님의 조언에 따라 API를 하나씩 삭제하고 PR을 올리기로 했다.

1. documentLoader property 삭제

먼저, ‘FederationOptions’ interface에 있는 ‘documentLoader’ property를 없애기로 했다. 해당 인터페이스에서는 이미 ‘documentLoader’를 대신하는 ‘documentLoaderFactory’가 선언되어있었다.

  /**
   * A custom JSON-LD document loader.  By default, this uses the built-in
   * cache-backed loader that fetches remote documents over HTTP(S).
   * @deprecated Use {@link documentLoaderFactory} instead.
   */
  documentLoader?: DocumentLoader;

documentLoader는 ActivityPub 객체나 다른 데이터를 나타내는 JSON-LD 문서를 원격 URL에서 가져오는 역할을 한다. 기본적으로는 내장된 캐시 기반 로더를 사용하지만, 사용자가 직접 만든 커스텀 로더를 제공하여 문서 로딩 방식을 변경할 수 있다.

JSON-LD 문서가 뭐지?

→ JSON-LD(JSON for Linked Data)는 간단히 말해 '의미가 부여된 JSON'이다. 일반적인 JSON 데이터에 '이것은 사람 이름이야', '이것은 주소야' 와 같이 데이터의 의미와 관계를 명확하게 설명하는 정보를 추가하는 표준 방식

예시

{
   "@context": "[https://schema.org/](https://schema.org/)",
   "@type": "Person",
   "name": "홍길동",
   "homepage": "[https://example.com](https://example.com/)",
   "image": "[https://example.com/profile.jpg](https://example.com/profile.jpg)"
}
  • @context : "이 문서에서 사용하는 용어들은 https://schema.org에 정의된 의미를 따를 거야"라고 선언하는 것 → schema.org는 웹에서 사용되는 다양한 용어(사람, 장소, 이벤트 등)를 표준화한 일종의 '어휘 사전'
  • @type: "Person": 이 데이터 덩어리는 '사람(Person)'에 대한 정보라고 명확히 알려줌

이제 컴퓨터는 이 데이터를 보고 다음과 같이 이해한다.

"아, 이건 schema.org 표준에 정의된 '사람(Person)'에 대한 정보구나. name은 그 사람의 이름이고, homepage는 웹사이트구나."


그러면 왜 documentLoader에서 documentLoaderFactory로 바꾸는 걸까?

documentLoader는 정적인 객체인 반면, documentLoaderFactory는 동적인 객체를 생성하는 함수

documentLoader

documentLoader는 Federation 객체가 처음 만들어질 때 단 한 번 생성되는 고정된 로더 객체다.

→ 한번 만들어지면, 모든 JSON-LD 문서를 가져오는 요청은 항상 이 동일한 로더를 사용해야한다.

documentLoaderFactory

그에 비해 documentLoaderFactory는 JSON-LD 문서를 가져와야 할 필요가 생길 때마다, 그 상황에 맞는 ‘DocumentLoader’ 객체를 즉석에서 생성하는 공장(Factory) 역할을 하는 함수이다.

방식

  1. JSON-LD 문서를 가져와야 하는 상황이 발생
  2. Fedify는 documentLoaderFactory 함수를 호출
  3. 현재 요청에 대한 정보(예: "이 요청은 'user-A'의 권한으로 보내는 거야")와 같은 컨텍스트를 Factory 함수에 전달 가능
  4. Factory 함수는 이 컨텍스트를 바탕으로 인증 정보가 포함된 맞춤형 DocumentLoader 객체를 새로 생성하여 반환
  5. Fedify는 방금 만들어진 이 맞춤형 로더를 사용해 문서를 안전하게 가져옴

즉, documentLoader를 documentLoaderFactory로 바꾼 이유는 정적인 '하나의 도구'를 계속 사용하는 방식에서, 필요할 때마다 상황에 맞는 '맞춤형 도구'를 즉석에서 만들어 사용하는 훨씬 더 유연하고 강력한 방식으로 전환하기 위해서이다.

코드 변경

먼저, fedify/src/federation/federation.ts에서 documentLoader 속성을 없앴다.

그리고 cli/src/inbox.tsx에서 createFederation에 documentLoader를 직접 전달하는 대신, getDocumentLoader() 함수로 로더를 딱 한번 만들고 계속 동일한 로더를 재사용하게 만들었다.

image 1

fedify/src/federation/middleware.ts에서는 documentLoader를 documentLoaderFactory 방식으로 변경하면서, allowPrivateAddress와 userAgent 검사 코드를 제거했다. 왜냐하면, documentLoaderFactory을 통해 해당 속성들을 지정할 수 있게 되었기 때문이다.

image 2

마지막으로, fedify/src/federation/middleware.test.ts에서는 변경된 기능에 맞춰 테스트 코드를 documentLoaderFactory 방식으로 수정했다.

image 3

또한, 테스트 간의 충돌을 방지하고 역할을 명확히 하고자 이전에는 하나로 사용하던 테스트용 가짜 서버 주소를 일반 객체 조회용(/object)과 인증 확인용(/auth-check)으로 나누어 분리했다.

image 4

2. contextLoader property 삭제

그리고 이제 contextLoader property를 삭제해보자. 위에서 documentLoader는 ActivityPub 객체나 다른 데이터를 나타내는 JSON-LD 문서를 원격 URL에서 가져오는 역할을 한다라고 했는데, 그러면 contextLoader는 무엇일까?

→ contextLoader는 JSON-LD 문서의 의미를 해석하는 데 필요한 @context를 가져오는 역할을 한다.

ActivityPub에서 사용하는 데이터 형식인 JSON-LD는 @context라는 필드를 사용한다. 이 @context 필드에는 주로 ‘어휘 사전’ 파일의 위치를 가리키는 URL이 들어간다. 이 사전을 참조함으로써, 컴퓨터는 "이 문서에서 Person은 '사용자 프로필'을, Note는 '게시물'을 의미한다"와 같이 각 용어의 정확한 의미를 해석할 수 있게 된다.

코드 변경

먼저, fedify/src/federation/federation.ts에서 contextLoader 속성을 없앴다.

그리고 fedify/src/federation/middleware.ts에서는 allowPrivateAddress 같은 보안 옵션을 켰다면, documentLoaderFactory와 contextLoaderFactory를 사용하지 못하도록 하는 코드를 추가했다.

image 5

fedify/src/federation/middleware.test.ts에서는 contextLoader를 contextLoaderFactory로 교체해주었다.

image 6

이렇게 documentLoader와 contextLoader, 두 개의 API를 정리했다. 이번 작업을 통해 documentLoader와 contextLoader가 Fedify에서 무슨 역할을 하는지 알 수 있었다. 이 Loader들을 Factory 함수들로 대체함으로써 단일 로더 방식에서 벗어나 상황에 맞는 맞춤형 로더를 동적으로 생성하는 유연한 구조를 갖출 수 있게 되었다.

위에 언급했던 이슈로 다시 돌아가보면 Loader들 이외에도 CreateFederationOptions, fetchDocumentLoader 등 정리해야될 API가 여러개 존재한다. 이 API들을 삭제하는 작업을 앞으로도 계속 한다면 Fedify가 어떻게 돌아가는지 더 깊게 이해할 수 있을 것 같다.