Judith
(Judith Meyer)
12월 1, 2023, 11:43오전
1
저희 조직이 보유한 모든 커스텀 앱에 Discourse 설치 환경을 쉽게 연결하고, 해당 앱을 통해 푸시 알림을 전달할 수 있도록(웹푸시가 작동하지 않는 iOS 환경에서 특히 유용합니다) 플러그인을 개발하고 있습니다. 플러그인 저장소는 GitHub - Sprachprofi/discourse-app-notifications: Send Discourse push notifications through FCM to any custom app · GitHub 입니다. 현재 이 플러그인은 사용자가 앱에서 기기를 등록한 후 로그인하여 알림 설정 페이지의 커스텀 필드에 기기의 키를 수동으로 붙여넣어야 합니다.
제가 겪고 있는 문제는 다음과 같습니다. 사용자가 앱을 설치하고 로그인한 뒤 기기 키를 복사하여 붙여넣으려고 하면, POST /app_notifications/subscribe 액션(그리고 구독 해제 액션도 동일하게)에 대해 "required plugin ‘discourse_app_notifications’ not found"라는 오류가 발생합니다. 그러나 같은 사용자가 앱을 강제 종료한 후 동일한 단계를 다시 수행하면 오류 메시지가 없고 푸시 알림이 정상적으로 작동합니다.
동일한 호출이 앱 내에서 이루어지는 상황에서, 한 경우에는 플러그인이 인식되고 다른 경우에는 인식되지 않는 원인은 무엇일 수 있을까요? 그 사이에 Discourse 설치 환경에는 아무런 변경 사항이 없었으며, 이 동작은 일관되고 재현 가능합니다.
이것이 문제를 반드시 해결해 주지는 않지만, 문제를 일으킬 수 있고, 특히 초보자에게는 코드를 이해하기 훨씬 어렵게 만듭니다.
플러그인의 구조가 매우 비전통적이므로 Zeitwerk 표준에 맞게 리팩토링하는 것을 고려해 보세요.
이것이 현재 겪고 있는 문제의 원인인지 확신할 수 없습니다.
많은 플러그인이 plugin.rb 안에 수많은 클래스 정의를 포함하거나, require_relative를 사용하여 ruby 파일을 로드합니다. 이 방식은 동작하지만 몇 가지 단점이 있습니다:
개발 중 변경 사항이 자동 재로드되지 않습니다. 변경 사항을 적용하려면 서버를 완전히 재시작해야 합니다.
require 호출 순서를 올바르게 맞추는 것이 번거로울 수 있습니다.
after_initialize 블록 외부에서 require되면, 다른 자동 로드되는 클래스/모듈이 사용 불가능할 수 있습니다.
해결책이 있습니다! 플러그인은 표준 Rails 자동 로드 시스템을 활용할 수 있습니다. 새로운 플러그인의 경우, 필요한 모든 것이 plugin-skeleton 에 정의되어 있습니다. 이 주제는 기존 플러그인을 어떻게 적응시키고 설정을 확장하는지 설명합니다.
1. 플러그인을 위한 모듈과 Rails::Engine 정의
plugin.rb에서 고유한 PLUGIN_NAME을 가진 플러그인용 모듈을 정…
pfaffman
(Jay Pfaffman)
12월 1, 2023, 1:38오후
3
저도 비슷한 문제를 겪었습니다(다만 에러가 아니라 경고였던 것 같지만요), 그런데 제 코드를 이렇게 수정했더니:
post '/subscribe' => 'push#subscribe'
post '/unsubscribe' => 'push#unsubscribe'
end
Discourse::Application.routes.append do
mount ::DiscourseAppNotifications::Engine, at: '/app_notifications'
end
require_dependency 'application_controller'
class DiscourseAppNotifications::PushController < ::ApplicationController
requires_plugin DiscourseAppNotifications::PLUGIN_NAME
layout false
before_action :ensure_logged_in
skip_before_action :preload_json
def automatic_subscribe
DiscourseAppNotifications::Pusher.subscribe(current_user, params[:token])
if DiscourseAppNotifications::Pusher.confirm_subscribe(current_user)
#flash.now[:notice] = "You have successfully subscribed to push notifications."
render json: success_json
PLUGIN_NAME을 사용하니까 해결이 됐습니다.
로버트가 말했듯이, 컨트롤러를 plugin.rb 안에 두지 않고 app/controllers에 두면 몇 가지 문제가 해결될 수 있습니다. 저도 어디에 문제가 있는지 헷갈렸거든요.
Judith
(Judith Meyer)
12월 2, 2023, 8:47오후
4
저는 requires_plugin DiscourseAppNotifications::PLUGIN_NAME을 사용하고 있으므로, 혹시 어떤 변경을 제안하시는 것인지, 혹은 제안이 있는 것인지 잘 모르겠습니다.
이 플러그인이 이렇게 구조화된 이유는 처음부터 코딩하는 대신 Pushover Notifications 플러그인을 기반으로 사용했기 때문입니다. 제 첫 플러그인인데, 앱과의 상호작용 때문에 디버깅이 악명 높게 어렵습니다. 그래서 이런 방식으로 몇 가지 버그를 피하려 했습니다…
pfaffman
(Jay Pfaffman)
12월 3, 2023, 12:46오전
5
아니요. 대부분 어깨를 으쓱하는 수준입니다. 저는 그 문제를 겪었지만, 당신도 제가 해결했던 것과 같은 조치를 취한 것 같습니다.
저라면 그렇게 했을 것 같습니다.
Rails는 많은 부분에서 까다롭습니다. plugin.rb에 그런 내용을 넣을 수 있을 줄은 몰랐습니다. 그리고 여러 다른 위치로 내용을 옮기는 것이 문제를 해결할지 저도 모르겠습니다. 죄송합니다.
Judith
(Judith Meyer)
12월 11, 2023, 5:40오후
6