TIL no.67 - Next.js 외부에서 만든 웹페이지 삽입하기

김종진·2021년 10월 8일
1

Next.js 외부에서 만든 웹페이지 삽입하기

HTML

SSR로부터 HTML 텍스트를 받아오면

dangerouslySetInnerHTML를 사용하여 웹 페이지 안에 삽입 할 수 있다.

import React, { useEffect } from 'react'
import Head from 'next/head'

const externalPage = ({data}) => { 

    const htmlString = data.html_text
    
    function Template({ htmlString }) {
    return <div dangerouslySetInnerHTML={{ __html: htmlString }}></div>
  }
  
  return (
  	<section>
          <Template htmlString={htmlString} />
        </section>
  )
}

CSS

next.js의 <HEAD> 태그안에 <link> 태그를 넣어 css파일을 연결하면 해당 페이지에 css를 적용시킬 수 있다.

import React, { useEffect } from 'react'
import Head from 'next/head'

const externalPage = ({data}) => { 

    const htmlString = data.html_text
    const pageStyle = `${data.css_file}`
    
    function Template({ htmlString }) {
    return <div dangerouslySetInnerHTML={{ __html: htmlString }}></div>
  }
  
  return (
  <>
    <Head>
      <link rel="stylesheet" href={pageStyle} />
    </Head>
      <section>
          <Template htmlString={htmlString} />
      </section>
  )
  </>
}

JS

외부 파일의 JavaSrcipt를 실행시키려면 Window.postMessage()를 활용하는 방법이 있다.

Window.postMessage() 공식문서

window.postMessage() 메소드는 Window 오브젝트 사이에서 안전하게 cross-origin 통신을 할 수 있다고 한다.

// 외부 HTML

<body>
    <div class="input">
        <button class="inquiry_btn">
        	문의하기
        </button>
    </div>

    <script type="text/javascript">
        var btn = document.querySelectorAll(".inquiry_btn")[0];
          function onClick(e) {
               e.preventDefault();
               const name = document.getElementById('name')
               const contents = document.getElementById('contents')

               if(name['value'] === '') {
                    alert('이름을 입력해주세요'); 
                    return;
                }

                if(contents['value'] === '') {
                    alert('요청사항을 입력해주세요');
                    return;
                }

            window.postMessage({
                functionName: 'postInquiry', 
                data: {
                request_name: name['value'],
                request_content: contents['value'],
            }}, '*');
          }
          btn.addEventListener('click', onClick);
      </script>
</body>

// next.js Page

import React, { useEffect } from 'react'
import Head from 'next/head'

const externalPage = ({data}) => { 

    const htmlString = data.html_text
    const pageStyle = `${data.css_file}`
    
    function Template({ htmlString }) {
    return <div dangerouslySetInnerHTML={{ __html: htmlString }}></div>
  }
  
    const postInquiry = async (e) => {
    e.preventDefault()
    try {
      const result = await API.post(
        `/(api주소)`,
        e.data.data
      )
      if (result.status === 200) {
        alert('문의 작성이 완료되었습니다.')
      }
      return
    } catch (err) {
      console.log(err)
    }
  }

  const receiveMessage = (e) => {
    e.preventDefault()
    if (e.data.functionName == 'postInquiry') {
      postInquiry(e)
    }
  }
  // useEffect로 receiveMessage함수가 실행되고 next.js에 있는 함수를 실행시키는데
  e.data.functionName == 'postInquiry'라는 조건을 걸어 원하는 타이밍에 함수를 실행시킬수 있다.

  useEffect(() => {
    window.addEventListener('message', receiveMessage)
    return () => {
      window.removeEventListener('message', receiveMessage)
    }
  }, [])

  
  return (
  <>
    <Head>
      <link rel="stylesheet" href={pageStyle} />
    </Head>
      <section>
          <Template htmlString={htmlString} />
      </section>
  )
  </>
}

HTML의 버튼을 누르면 script의 onClick 함수가 실행되고 그 결과를 window.postMessage()를 통해 next.js에 보내면 받은 event를 통해 next.js에서 계속해서 활용 할 수 있다.

profile
FE Developer

0개의 댓글