9Cells

Laravel Websockets, Sanctum, Electron 환경을 구축하면서 SSL과 Electron 설정에서 경험한 문제들을 정리합니다.

SSL 설정 문제

Laravel Websockets의 SSL 설정 방법은 크게 두 가지로 나눌 수 있습니다.

처음에 프록시 설정 방식은 설치환경마다 설정이 달라지고 이런 설정방식이 코드와 함께 버전관리가 되기 어렵다는 이유 때문에 전자를 선택했습니다. 그런데 잘 되지도 않고 해결했다는 문서들의 내용을 보면 이렇게 설정해도 되는지 그 파급효과를 이해하고 사용하기 어려워서 곤란했습니다.

그러던 중 Laravel Websockets 공식 문서에서 Laravel Forge 배포 방법에 대한 외부 문서 링크를 발견하여 읽어보니 websockets.php 설정을 바꾸는 것보다 NGINX로 설정을 하고 내부는 http로 구성하여 bypass 하는 게 더 빠르고 간단하다는 설명을 읽어 바꾸게 됐습니다.

공식 문서를 보고 쉽게 진행 가능했습니다. map을 만들고 @web, @ws에 대한 location 설정을 하니 쉽게 됐습니다.

map $http_upgrade $type {
  default "web";
  websocket "ws";
}

server {
  # Your default configuration comes here...

  # 추가
  location / {
    try_files /nonexistent @$type;
  }

  # 기존 location / 설정을 아래처럼 바꿈  
  location @web  {
    try_files $uri $uri/ /index.php?$query_string;
  }

  # 웹소켓용 설정
  location @ws  {
    proxy_pass             http://127.0.0.1:6001;
    proxy_set_header Host  $host;
    proxy_read_timeout     60;
    proxy_connect_timeout  60;
    proxy_redirect         off;

    # Allow the use of websockets
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

Electron에서 Laravel Echo 접속

다음은 Electron에서 Laravel과 통신하는 부분입니다.

먼저 public channel에 대한 통신은 쉽게 됐습니다. Echo를 웹페이지에서 사용한 방식 그대로 Electron에 적용하고 authEndpoint를 제 주소로 바꿨습니다.

문제는 private channel인데 echo 접속 시에 sanctum 인증을 어떻게 해야하는 것인지 알기 어려웠습니다. 인터넷에서 찾아보면 다양한 답변이 있지만 제가 최종적으로 선택한 설정 방법은 이렇습니다.

BroadcastServiceProvider.php에 다음처럼 추가합니다.

public function boot()
{
  Broadcast::routes();
  Broadcast::routes(['prefix' => '/api', 'middleware' => ['auth:sanctum']]); // 추가

  require base_path('routes/channels.php');
}

그리고 JS에서 아래 코드처럼 Echo 인스턴스 생성을 합니다.

// Electron 쪽의 코드

new Echo({
    broadcaster: 'pusher',
    key: '<key>',
    cluster: 'mt1',
    wsHost: 'my.test',
    wsPort: 6001,
    wssPort: 443,
    forceTLS: false,
    auth: {
        headers: {
            'Authorization': 'Bearer <token>',
        },
    },
    authEndpoint: 'http://my.test/api/broadcasting/auth'
})

Sanctum 인증을 위해 Broadcast::routes(['prefix' => '/api', 'middleware' => ['auth:sanctum']]);를 추가했습니다. 새로운 routes에 /api를 추가해야 웹브라우저로 소켓에 연결하는 것도 지원이 됩니다.

routes()에 /api prefix를 추가했으므로 Echo 설정의 authEndpoint에도 /api 를 추가해줍니다.

auth 항목은 sanctum 로그인에서 사용하는 설정과 같습니다.

참고로 이 코드를 Electron의 main 프로세스에 넣지않고 renderer 프로세스에 넣었더니 메세지가 즉시 전달이 안 되고 ping – pong을 주고 받을 때 한 번에 받아지는 것처럼 보여지는 증상이 있었습니다. 단순하게 renderer의 코드를 main으로 옮기는 것으로 해결됐습니다.