현재 특정 사용자 프로필 페이지에 비디오를 추가하려고 시도하고 있습니다. 이렇게 하면 모든 후원자(patron)의 프로필에 특정 배경 비디오가 표시되도록 할 수 있습니다. (조금 과민 반응할 필요는 없습니다. 전체 비디오가 아니라 루프 애니메이션일 뿐이며, Steam 프로필 배경처럼 꽤 그럴듯해 보일 것입니다.)
다음 HTML 및 CSS 코드는 모든 사용자에게 적용되지만, 분명히 우리가 원하는 결과는 아닙니다:
body.category-general을 사용하여 ‘general’ 카테고리의 페이지에만 이미지를 추가하는 것과 달리, 특정 그룹에 속하거나 특정 사용자 이름을 가진 사용자의 프로필 페이지에는 특정 슬러그(slug)가 할당되어 있지 않은 것 같습니다. 우리는 이 분야에 꽤 초보이며 HTML 직접 작업보다는 CSS에 더 익숙하므로, 우리가 원하는 방식으로 작동하도록 만드는 간단하고 편리한 방법이 있는지 확실하지 않습니다.
우리는 사용자 프로필에 그룹 기반의 유사한 슬러그를 추가하는 것이 최선의 접근 방식이라고 생각하지만, 이를 어떻게 구현할지, 그리고 비디오가 올바른 콘텐츠가 있는 페이지에서만 표시되도록 하는 방법을 알지 못합니다. 또한 더 쉬운 다른 방법이 있다면 반드시 이 방식을 사용해야 한다는 생각에 얽매이지 않겠습니다.
예를 들어, 그룹별이 아니라 사용자별로 처리하는 방식도 더 쉬운 경우라면 열려 있습니다.
우리는 비디오를 모든 페이지에 하드코딩하는 것은 피하고 싶으며, 해당 특정 사용자(들)의 페이지에 있을 때만 로드되도록 하기를 원합니다.
수정: 만약 이것이 어떤 영향을 미친다면, 우리가 stable 브랜치를 사용 중이라는 점을 언급해야 할 것 같습니다.
현재 우리의 접근 방식은 canonical 링크를 통해 특정 사용자의 페이지에 있는지 단순히 감지하고, 그렇다면 해당 비디오를 적용하는 것입니다. 이를 위해 다음 코드를 사용하고 있습니다:
<script type="text/discourse-plugin" version="0.8">
api.onPageChange(() =>{
determineUser();
});
function determineUser() {
var pageURL = document.querySelector("link[rel='canonical']").getAttribute("href");
var isUserPage = pageURL.includes("https://www.fortressoflies.com/u/");
document.documentElement.style.setProperty('--currUsername', pageURL);
if(isUserPage)
{
document.documentElement.style.setProperty('--lastUsername', pageURL);
$('body').css('background-color', '#'+(Math.random()*0xFFFFFF<<0).toString(16));
}
}
</script>
하지만 이 방법은 전체 새로고침(full refresh) 시에만 작동하는 것 같습니다. 어떤 이유에서인지 페이지를 이동하며 클릭할 때 --currUsername 속성이 업데이트되지 않습니다. 그 결과, 사용자 페이지에 무작위 색상의 배경을 적용하는 대신, 마지막에 F5 키를 누른 페이지가 사용자 페이지였다면 모든 페이지에 무작위 색상의 배경이 적용되고, 마지막에 F5 키를 누른 페이지가 사용자 페이지가 아니었다면 어떤 페이지에도 배경이 적용되지 않습니다.
솔직히 JavaScript에 대해 충분히 숙련되지 않아서 왜 그런지 알지 못합니다. 제 생각에는 페이지 변경 시 함수가 실행되어야(실제로도 실행됩니다) pageURL 변수가 업데이트되고, 이는 페이지 로드 시 --currUsername 속성이 업데이트되어야 합니다. 하지만 전체 새로고침 시에만 이러한 일이 발생하며, 그렇지 않으면 변수가 변경되지 않는 것으로 보입니다.
정규화 URL(canonical URL)은 업데이트되지 않는 반면, “og:url” 속성은 업데이트되는 것 같습니다.
문제는 var pageURL = document.querySelector("meta[property='og:url']").getAttribute("content");를 사용하면 메타 태그 자체가 업데이트되기 전에 값이 갱신된다는 점입니다. 즉, 이 코드는 현재 페이지의 URL이 아니라 이전 페이지의 URL을 가져오게 됩니다.
비디오가 모든 프로필에 표시되기를 원하지 않고, 특정 조건에 따라만 표시되기를 원합니다. 그러면 어떻게 해야 할까요? 두 가지가 필요합니다. 소비할 데이터와 약간의 JavaScript입니다.
데이터를 찾아보겠습니다. 플러그인 아웃렛이 예약된 공간이라고 했을 때 기억나시나요? 컨텍스트 없이 그것들을 가질 목적은 무엇일까요? 그래서 Discourse는 각 플러그인 아웃렛에 관련 컨텍스트 조각을 전달합니다… 하지만 먼저 한 걸음 뒤로 물러나 보겠습니다. 여기에 이것을 추가할 때
이 중 도움이 되는 것이 있을까요? 네… 하지만 지금은 아닙니다. 나중에 다시 돌아오겠습니다. 한 걸음 더 뒤로 물러나서 Discourse가 컨텍스트를 아웃렛에 전달하는 방식을 살펴봅시다. Github에서 - 또는 로컬에서 - 아웃렛 이름을 검색하면 이것을 얻게 됩니다.
좋습니다, 이제 필요한 데이터를 가지고 있으므로 남은 일은 그것에 기반한 조건을 추가하는 것입니다.
같은 스니펫에서 그것을 할 수 있다고 생각할 수 있지만, 불행히도 그럴 수 없습니다. Handlebars는 템플릿 언어입니다. 논리에 대한 지원이 매우, 매우 기본적입니다 - 단순한 참/거짓 조건과 루프를 넘어가는 것은 없습니다. 비교와 같은 다른 작업을 수행할 수 없습니다.
그렇다면 정확히 어디서 그것을 수행할 수 있을까요? 커넥터 클래스(connector class)에서, 꽤 멋져 보이죠… 압니다.
간단히 말해, 커넥터 클래스는 본질적으로 아웃렛에 첨부된 JavaScript 조각입니다. 그것보다 훨씬 더 뉘앙스가 있지만, 지금은 이것만 알면 충분합니다.
커넥터 클래스 내부에서 일부 작업을 수행할 수 있습니다… 하지만… 그것은 일반적인 javaScript 파일과는 다르다는 점을 명심해야 합니다. 더 나은 설명이 부족하지만… 다이어트 중인 Ember 컴포넌트라고 생각하세요. 이 주제에 대해 더 깊이 들어가는 것은 여기서는 약간 벗어난 내용이므로 넘어가겠습니다.
그런 다음 버튼이 눌릴 때와 같이 아웃렛 내부에서 해당 동작을 호출할 수 있습니다. 여기서는 이것이 필요하지 않으므로 넘어가겠습니다.
api.registerConnectorClass("above-user-profile", "add-profile-videos", {
shouldRender(args, component) {
// return true or false here
}
});
아웃렛은 프로필 페이지에서만 렌더링되고 현재 다른 요구사항이 없으므로 이것도 사용하지 않을 것입니다. 그러나 아웃렛이 렌더링되기 전에 테스트하려는 모든 조건을 추가하는 데 사용할 수 있습니다. 예를 들어, 현재 사용자의 신뢰 수준(trust-level)이나 그런 것들입니다. 넘어가겠습니다…
이전에 본 것과 동일한 정보를 브라우저 콘솔에서 볼 수 있습니다. 프로필 소유자가 속한 그룹입니다. 여기서 재미있는 부분이 시작됩니다. 이제 데이터를 가지고 있고 올바른 훅(hook)을 가지고 있습니다. 따라서 여기서 원하는 것을何でも 할 수 있습니다. 예를 들어, 비디오가 특정 그룹에 속한 멤버의 프로필에서만 표시되기를 원한다면 이렇게 할 수 있습니다.
정말 심도 있는 내용인데, 다음 주에 시간이 되면 꼭 자세히 살펴볼게요. 일단 대충 훑어본 바로는, 제 현재 구현 방식(비디오를 모든 페이지에 임베드하고, 스크립트를 사용해 계정명이 특정 값일 때만 사용자 프로필에 비디오를 표시하는 방식)보다 훨씬 나은 것 같아요. 이렇게 자세한 설명을 해주셔서 감사합니다. 시간 나면 바로 적용해볼게요!