개발 노트/개발 삽질

티스토리에 뉴스레터 적용하기

j4ko 2023. 9. 24. 02:22
728x90
반응형

목차

    개요

    안녕하세요 jako입니다.

     

    최근 개인 뉴스레터를 운영해보고 싶은 것에 대해 관심이 생겼습니다. 공수를 들여 작성한 독자분들께 직접 전송하여 정보가 유익했는지 혹은 피드백을 얻기 위하는데 목적이 있었죠. 그리하여 뉴스레터를 운영해 보기 위해 조사를 거쳤습니다. 제일 먼저 티스토리에서 뉴스레터를 사용할 수 있게 해주는 플러그인이 있는지 찾아봤지만 자료가 나오지 않았습니다. 그래서 따로 뉴스레터를 운영할 수 있는 플랫폼을 찾아본 결과 stibee, 글리버리와 같은 플랫폼이 존재했습니다.

     

    그런데 제 기준에서는 각각 다음과 같은 특징이 있었습니다.

    스티비

    - 입맛에 맞게 커스텀할 수 있는 여러 요소들을 제공해 주는 것으로 확인했으나 티스토리에 연결해서 사용하는 방법을 찾지 못함

    글리버리

    - 뉴스레터를 발행하는데 심플하지만 티스토리에 연결해서 사용하는 방법을 찾을 수 없고 글리버리 계정을 만들어야지 해당 구독이 가능함

     

    목표로 삼았던 것은 티스토리의 포스팅 글 하단에 뉴스레터 안내와 함께 독자분의 이메일을 입력하면 글이 발행될 때마다 해당 이메일로 안내하는 것이기 때문에 어느 플랫폼을 사용한다해도 찜찜함이 남았습니다. 

    벤치마킹 한 뉴스레터 안내 양식

    그런데 잠시 생각해 보니 티스토리는 html과 css 그리고 js에 대해 사용자가 직접 작성한 소스를 반영해 주도록 허용하고 있다는 점이 문득 떠올랐습니다.

     

    이 특징을 잘 활용하면 뉴스레터 구독 안내 양식을 직접 만들어서 티스토리에 적용할 수 있지 않을까 하는 생각이 머리에 스쳤습니다.

     

    그리하여 이 글에는 티스토리에 뉴스레터 양식을 적용하기 위해 거쳤던 과정을 기록해 보고자 합니다.


    0. Ideation

    티스토리에 뉴스레터를 적용하기 위해 간단히 다음과 같은 아이디어를 구상해냈습니다.

     

    tistory부터 slack까지 데이터 옮기기

    1. Tistory 글 하단에 뉴스레터 양식을 적용하고 사용자가 이메일을 입력받을 수 있게 마크업을 적용한다.
    2. email 입력 후 “제출”시 이를 javascript에서 캐치하여 fetch() API를 사용하여 로컬에서 동작중인 ngrok로 데이터를 보낸다.
    3. ngrok와 연계된 application이 데이터를 응답받으면 application에서는 이를 개인 slack 채널에 보내준다.

    여기서 Slack 채널로 사용자 이메일을 전송받는 이유는 "어떤 뉴스레터 플랫폼에도 의존하지 않고 직접 만들어서 사용해본다면 어떨까?"를 토대로 한 것입니다.

     

    그런데 어떻게 됐든 로컬에서 검증을 한 번 거쳐야 하므로 뉴스레터 양식을 티스토리에 어떻게 적용해야 되고 티스토리에서 javascript를 통해 ngrok로 데이터를 전송할 수 있을지가 의문이었습니다.

     

    1. Template 선정하기

    Ngrok부터 Application 연결과 Slack Channel에 메시지를 보내는 건 몇 번 해봐서 어렵지 않은 일이기에 뉴스레터 양식과 그 양식을 마크업 하기 위한 코드를 구하는 것을 출발점으로 삼았습니다.

     

    개인적인 경험에서는 대체로 Front는 BootStrap으로 여러 컴포넌트를 조합해 보면서 하나씩 만들어나가지만 이번에는 삽질의 시간을 줄이고자 미리 완성된 뉴스레터 템플릿을 구하여 그대로 티스토리에 적용해 보는 방법을 사용하기로 결정했습니다.

     

    이런 경우에는  codepen.io 에서 이와 관련한 소스를 찾는 것으로 시작하곤 합니다.

     

    이번에도 적당한 뉴스레터 양식을 codepen에서 찾을 수 있었습니다. 해당 코드를 복붙 하여 입맛에 맞게 수정하여 사용했습니다.

    2. JavaScript의 데이터 전송 처리하기

    codepen에서 참고한 뉴스레터를 티스토리에 적용하기 전에 Local에서 JavaScript를 이용해 ngrok에 데이터를 보낼 수 있을지 테스트해야했습니다. html의 form 태그를 통해 이메일을 입력받으면 이를 javascript에서 hook을 시도하기위해 다음과 같은 코드를 사용했습니다.

    function handleNewsLetterFormSubmit(event) {
      	event.preventDefault(); // 기본 동작(페이지 리로딩)을 막습니다.
       
        let username = document.getElementById("newsletter_email")
    
        let url = "" // Ngrok URL    
        
        fetch(url+ new URLSearchParams({
            user_email: user_email.value
        }), {
            method : "GET",
            headers: {
                'Content-Type': 'application/json; charset=utf-8',
                'Accept': 'application/json',
                "Access-Control-Allow-Origin" : "*",
                "Origin": location.origin
                
            },
        })
    }

     

    3. Ngrok와 Application Setting

    ngrok는 사용법이 너무 간단한지라 언급할게 없습니다. Ngrok는 활용법이 굉장히 실용적이라고 생각됩니다 개인적으로는 domain을 구입할 여력이 없거나 지금 당장 WAN을 통해 데이터 경유하는지를 보고 싶을 때 많이 사용하는 편입니다.

    $ ngrok http 8080
    

    이제 ngrok과 연결되는 application을 띄워야 합니다. 실제 서버를 운영할것이라 기대하고 application을 띄운다면 FastAPI나 Flask와 같은 FrameWork를 고려할 수 있겠지만 데이터가 제대로 들어오는지만 보기 위해서는 python에서 제공하는 간단한 http.server로도 충분합니다.

    $ python -m http.server 8080
    

     

    4. CORS 해결하기

    2번과 3번 과정을 통해 준비를 끝낸 뒤 실제로 데이터를 전송해보고 나니 Cross Origin Resource Sharing 문제를 만났습니다. JavaScript의 fetch()를 다룰때마다 한번씩 만나는 아주아주 고통스러운 문제입니다.

     

    앞서 application으로 python -m http.server 8080을 통해 ngrok와 연계되는 간단한 서버를 띄웠습니다. 하지만 이는 Python에서 제공하는 기본적인 기능만 수행하는 server를 띄운것이기에 CORS 문제를 해결해주지 못하더군요

     

    다음은 이를 해결하기 위해 사용된 python 코드입니다.

    #!/usr/bin/env python3
    from http.server import HTTPServer, SimpleHTTPRequestHandler
    import sys
    
    class CORSRequestHandler(SimpleHTTPRequestHandler):
        
        def end_headers(self):
            self.send_header('Access-Control-Allow-Origin', '*')
            self.send_header('Access-Control-Allow-Methods', '*')
            self.send_header('Access-Control-Allow-Headers', '*')
            self.send_header('Cache-Control', 'no-store, no-cache, must-revalidate')
            return super(CORSRequestHandler, self).end_headers()
    
        def do_OPTIONS(self):
            self.send_response(200)
            self.end_headers()
    
    host = sys.argv[1] if len(sys.argv) > 2 else '0.0.0.0'
    port = int(sys.argv[len(sys.argv)-1]) if len(sys.argv) > 1 else 8080
    
    print("Listening on {}:{}".format(host, port))
    httpd = HTTPServer((host, port), CORSRequestHandler)
    httpd.serve_forever()

    이 코드를 파일로 저장해 다시 실행시키니 로컬에서 javascript의 fetch가 ngrok를 경유해 python http.server까지 전송되는 결과를 확인할 수 있었습니다.

     

     

    5. 티스토리에 적용하기

    로컬에서 간단한 검증을 모두 마쳤으니 티스토리에 적용해봅시다.

     

    5.1 티스토리에 css 삽입하기

    티스토리에 뉴스레터 마크업의 CSS를 등록하기 위해 “스킨편집”으로 들어가 CSS를 맨 아래에 복사붙여넣기 해줍니다.

     

    5.2 티스토리에 js 업로드하기

    이후 파일업로드 탭으로 이동하여 앞서 준비한 javascript 파일을 업로드했습니다.

    주의할점은 티스토리에서 해당 javascript 파일을 찾을 수 있도록 설정해야한다는 점이었습니다. HTML 탭으로 돌아와 다음과 같이 경로를 삽입했습니다.

     

    5.3 뉴스레터 html 삽입 후 결과 확인하기

    이후 뉴스레터 html을 티스토리 글에 표출되도록 하기 위해 다음과 같이 코드를 직접 삽입하여 글을 발행합니다.

    이후 발행된 글은 다음과 같은 모습을 가지게 됩니다.

     

    6. Slack 연결하기

    이 부분이 과정 상에서는 마지막 부분이었습니다. 지금까지 티스토리에 뉴스레터 양식을 적용하고 뉴스레터 입력 양식에 이메일을 입력하면 ngrok를 통해 http.server 까지 거쳐 데이터가 전송되는 걸 확인했습니다.

     

    데이터가 정상적으로 들어오는 것을 확인했으니 데이터를 Slack까지 포워딩시키기 위해 http.server 대신 FastAPI로 Endpoint를 만들고 slack_sdk와 slackbot을 활용하면 다음과 같은 결과를 얻을 수 있었습니다.

     

     

     

    마치며

    티스토리에 이런 게 될까라며 시도해봤습니다. 도중에 무엇이 안되는지는 왜 이런 오류가 나오는지를 트러블슈팅하는데 꽤 시간이 들였지만 역시 해놓고보니 성취감이 남습니다.

     

    개인 뉴스레터를 티스토리에 적용하려면 일단 서버가 필요로 할 듯 하니 적용하는 건 개인 서버를 준비할때까지로 미루고 그동안은 stibee를 사용하도록 해야겠습니다.

     

     

     


    안녕하세요 jako입니다.

    해당 글을 통해 유용한 정보를 얻으셨길 바랍니다.

    경험과 지식의 공유를 통해 조금 더 양질의 정보를 생성하기위한 뉴스레터를 만들었습니다.

    블로그에는 기재되지 않을 유용한 정보 또한 뉴스레터에 담아 발행하고자합니다. 

     링크를 클릭하여 뉴스레터를 구독해주세요.

    양질의 정보와 함께 찾아뵙겠습니다.


     

    728x90
    반응형