이에 대해 몇 가지 생각을 나누고 싶습니다.
유료 디스커스 코스 개발
Udemy나 Coursera와 같은 플랫폼에서 디스커스 개발과 관련된 코스를 개설하는 아이디어는 흥미롭습니다. 다만, 디스커스 팀 외부에서 디스커스 개발 코스를 만들 자격이 있는 사람이 많지 않을 것 같고, 해당 코스의 잠재적 수강생 수도 꽤 제한적일 것이라 추정됩니다. 그럼에도 불구하고, 디스커스 테마나 플러그인 개발과 관련된 좋은 코스는 시간이 지나면 노력이 보답받을 만큼 충분한 수강생을 확보할 수 있을 것이라고 확신합니다.
또한, 디스커스 코스에 비용을 부과하는 것이 이 포럼의 정신에 반할 수 있다는 문제도 있습니다. 이 부분은 제 추측일 뿐입니다.
디스커스 개발 튜토리얼
많은 디스커스 플러그인, 테마, 테마 컴포넌트의 실제 구현이 꽤 단순하다는 관찰은 정확하다고 생각합니다. 다른 플랫폼 개발과 마찬가지로, 문제는 각 부분이 어떻게 조화를 이루는지에 대한 이해가 부족하여 초기 장벽을 넘지 못하는 것입니다. 디스커스 팀(또는 기타 자격을 갖춘 개발자)들이 기능적인 테마, 테마 컴포넌트, 플러그인을 만드는 전체 과정을 안내하는 몇 가지 튜토리얼을 작성하여 이 문제를 해결하는 데 도움을 줄 수 있습니다. 예를 들어, Discourse Placeholder와 같은 테마 컴포넌트를 만드는 단계별 가이드를 제공할 수 있습니다.
이것이 상당한 시간 투자가 필요하다는 점을 인지하고 있으므로, 이는 디스커스의 비즈니스 목표와 일치해야 합니다.
현재 이용 가능한 리소스
조금만 검색해 보면 이 포럼에서 디스커스 개발에 대한 많은 양질의 정보를 찾을 수 있습니다. 또한 디스커스 GitHub 저장소의 코드 예제를 살펴보는 것도 학습에 매우 좋은 방법입니다.
간과해서는 안 되는 최근 도구로는 GitHub Copilot이 있습니다. 개발 환경을 올바르게 구성하면, 디스커스 테마와 플러그인을 개발하는 방법에 대한 감각을 익히는 데 도움이 될 수 있습니다. 디스커스 테마 개발의 경우, 제가 발견한 최선의 접근법은 로컬 디스커스 설치 환경의 루트 디렉터리에서 테마를 개발하는 것입니다(Discourse Theme CLI 사용). 이렇게 구성하면 Copilot이 디스커스 코드베이스에 쉽게 접근할 수 있습니다. (플러그인 개발의 경우, plugins 폴더는 이미 루트 /discourse 디렉터리에 위치하고 있습니다. 참고로, Copilot이 IDE에 로드한 디스커스 코드베이스에 실제로 접근하는지에 대해 제 추측이 틀릴 수도 있습니다. 어쨌든, 제 자신의 참고를 위해 코어 디스커스 코드를 사용할 수 있게 하는 것이 유용합니다.)
집중을 방해하지 않고 Copilot을 학습 도구로 활용하는 데 초점을 맞추기 위해, 저는 IDE(VS Code)에서 Copilot Completions을 끄고 채팅을 통해만 Copilot과 상호작용합니다. Copilot이 제공할 수 있는 지원의 예시는 다음과 같습니다. (shopify.js는 테마의 /javascripts/discourse/api-initializers/ 디렉터리에서 Theme CLI에 의해 생성된 파일입니다.)
Copilot과의 대화
scossar:
shopify.js의 기본 내보내기(default export)가 무엇을 하는지 설명해 줄 수 있나요? 기본적으로discourse_theme게мом 테마가 생성될 때 디스커스가 제공하는 보일러플레이트 코드입니다. 저는 각 페이지 변경 사항을 로그로 기록하도록 보일러플레이트 코드를 수정했습니다.api.onPageChange호출은 이해하지만,api객체가 제 코드로 어떻게 주입되는지에 대해서는 명확한 이해가 없습니다.
GitHub Copilot:
api객체는apiInitializer가 반환하는 객체의initialize메서드에서 호출되는withPluginApi함수를 통해 코드로 주입됩니다.여기서 일어나는 일의 단순화된 버전은 다음과 같습니다:
디스커스가 시작되면 모든 초기화자(initializers)가 실행됩니다.
apiInitializer함수는"inject-objects"초기화자 이후에 실행되는 초기화자를 생성합니다.이 초기화자가 실행되면
version,cb,opts매개변수를 전달하여withPluginApi함수를 호출합니다.
withPluginApi함수는 현재 디스커스 버전이 지정된 버전과 호환되는지 확인합니다. 호환되면 콜백 함수(cb)를 호출하고PluginApi인스턴스를 인자로 전달합니다. 이PluginApi인스턴스가 코드에서 볼 수 있는api객체입니다.즉,
api객체는PluginApi의 인스턴스이며,withPluginApi함수를 통해 코드로 전달됩니다. 이 객체는onPageChange와 같이 디스커스와 상호작용할 수 있도록 하는 여러 메서드를 제공합니다.
scossar: 그렇다면
shopify.js의 기본 내보내기의 두 번째 인자인 함수가apiInitializer가 받는 콜백 함수인가요?
GitHub Copilot: 네, 맞습니다.
apiInitializer의 두 번째 인자는 콜백 함수입니다. 이 함수는 초기화자가 실행될 때(현재 디스커스 버전이 지정된 버전과 호환된다는 가정 하에)PluginApi인스턴스를 인자로 받아 호출됩니다. 이것이api객체가shopify.js파일에서 사용 가능하게 되는 방식입니다.
이것을 파악한 후…
scossar: …또 다른 생각이 있는데,
api.decorateCooked를 사용하여 외부 애플리케이션(예: 제가 개발 중인 Shopify 앱이 호스팅하는)에 호스팅된 평가(ratings) iframe을 주입할 수 있을까요?
GitHub Copilot: 네,
api.decorateCooked를 사용하여 게시글에 iframe을 주입할 수 있습니다. 이렇게 할 수 있는 대략적인 예시는 다음과 같습니다:api.decorateCooked($elem => { const postId = $elem.data('post-id'); const iframe = document.createElement('iframe'); iframe.src = `https://your-app.com/ratings?post_id=${postId}`; iframe.width = '100%'; iframe.height = '200'; // 필요에 따라 조정 $elem.append(iframe); }, { id: 'rating-iframe' });이 예시에서
api.decorateCooked는 각 게시글에 iframe을 추가하는 데 사용됩니다. iframe의 소스는 외부 애플리케이션의 URL로 설정되며, 게시글 ID가 쿼리 매개변수로 포함됩니다.'https://your-app.com/ratings'를 실제 평가 페이지의 URL로 대체해야 합니다.이것은 단순화된 예시임을 유의하십시오. 필요에 맞게 조정해야 할 수 있으며, 올바르게 작동하고 안전하게 유지되도록 오류 처리 및 기타 필요한 조치들을 반드시 추가해야 합니다.
이 시점에서 Copilot이 모든 코드를 실제로 작성하도록 기대하는 것은 합리적이지 않지만, 디스커스 코드를 작성하는 방법을 학습하는 데에는 훌륭한 도구입니다.