본문 바로가기
프로그램 (PHP,Python)

HTML 특수문자 코드를 해당 문자로 일괄 치환하는 String 함수 활용

by 날으는물고기 2024. 12. 10.

HTML 특수문자 코드를 해당 문자로 일괄 치환하는 String 함수 활용

HTML 특수문자 코드를 해당 문자로 치환하는 아래 코드는 배열을 사용하여 매핑을 생성하고, 그 값을 사용하여 치환을 수행합니다.

// 입력 데이터를 가져옵니다.
const items = $input.all();

// 각 아이템을 처리합니다.
items.forEach(item => {
  if (item.json && item.json.text) {
    let text = item.json.text;

    // HTML 특수문자 코드를 치환합니다.
    text = decodeHtmlEntitiesWithMappings(text);

    // 결과를 아이템에 저장합니다.
    item.json.text = text;
  }
});

return items;

function decodeHtmlEntitiesWithMappings(str) {
  // '&#NNN;' 형태의 모든 매치를 찾습니다.
  const regex = /&#(\d+);/g;
  let match;
  let mappings = [];
  let codes = new Set();

  // 중복을 제거하여 모든 코드를 수집합니다.
  while ((match = regex.exec(str)) !== null) {
    codes.add(match[1]);
  }

  // 매핑 배열을 생성합니다.
  codes.forEach(code => {
    const entity = `&#${code};`;
    const char = String.fromCharCode(code);
    mappings.push([entity, char]);
  });

  // 매핑을 사용하여 치환을 수행합니다.
  mappings.forEach(([entity, char]) => {
    str = str.split(entity).join(char);
  });

  return str;
}
  1. n8n에서 워크플로우를 생성하고, 처리할 데이터를 가져오는 노드를 추가합니다.
  2. 위의 코드를 포함한 코드 노드를 추가합니다.
  3. 코드 노드의 입력으로 이전 노드의 데이터를 연결합니다.
  4. 이 코드는 item.json.text 필드를 대상으로 합니다. 필요한 경우 코드를 수정하여 다른 필드를 처리할 수 있습니다.
  5. 워크플로우를 실행하여 HTML 특수문자 코드가 치환된 결과를 얻습니다.

설명

  • decodeHtmlEntitiesWithMappings 함수는 입력 문자열에서 모든 &#NNN; 형태의 특수문자 코드를 찾아 해당 유니코드 문자로 치환합니다.
  • 먼저 정규식을 사용하여 문자열에서 모든 특수문자 코드를 찾고, Set을 사용하여 중복을 제거합니다.
  • 각 코드에 대해 매핑 배열을 생성하고, 이를 사용하여 문자열에서 치환을 수행합니다.
  • 최종적으로 치환된 문자열을 반환하고, 이는 각 아이템의 item.json.text 필드에 저장됩니다.

이 코드를 사용하면 HTML 특수문자 코드를 해당 문자로 효율적으로 치환할 수 있습니다.

HTML 특수문자 코드에 대한 배경 정보

HTML에서 텍스트를 표시할 때, 특정 문자들은 브라우저에서 특별한 의미를 가지거나 올바르게 표시되지 않을 수 있습니다. 예를 들어, <, >, & 등은 HTML 태그나 엔티티를 나타내는데 사용되므로, 이들을 그대로 사용하면 의도치 않은 결과가 발생할 수 있습니다. 이를 방지하기 위해 HTML에서는 이러한 특수 문자를 엔티티 코드 또는 문자 참조(character reference)를 사용하여 표현합니다.

  • 엔티티 코드
    • &amp;, &lt;, &gt;와 같이 앰퍼샌드(&)로 시작하여 세미콜론(;)으로 끝나는 형태입니다.
  • 숫자 참조
    • 10진수 형태: &#35; (숫자 35는 # 문자를 나타냄)
    • 16진수 형태: &#x23; (16진수 23은 10진수 35와 동일)

이러한 코드를 사용하면 브라우저는 해당 코드를 해석하여 올바른 문자를 화면에 표시합니다.

String.fromCharCode()를 활용한 치환 방식의 예시 설명

위에서 제시한 코드는 HTML 특수문자 코드(숫자 참조)를 해당 문자로 치환하기 위해 JavaScript의 String.fromCharCode() 함수를 활용하고 있습니다. 이 함수는 유니코드 값(10진수)을 받아 해당하는 문자로 변환합니다.

String.fromCharCode(35); // 반환값: "#"
function decodeHtmlEntitiesWithMappings(str) {
  // '&#NNN;' 형태의 모든 매치를 찾습니다.
  const regex = /&#(\d+);/g;
  let match;
  let mappings = [];
  let codes = new Set();

  // 중복을 제거하여 모든 코드를 수집합니다.
  while ((match = regex.exec(str)) !== null) {
    codes.add(match[1]);
  }

  // 매핑 배열을 생성합니다.
  codes.forEach(code => {
    const entity = `&#${code};`;
    const char = String.fromCharCode(code);
    mappings.push([entity, char]);
  });

  // 매핑을 사용하여 치환을 수행합니다.
  mappings.forEach(([entity, char]) => {
    str = str.split(entity).join(char);
  });

  return str;
}
  • 정규식 사용 (/&#(\d+);/g): 입력 문자열에서 &#로 시작하고 ;로 끝나는 숫자 참조를 모두 찾습니다. (\d+)는 하나 이상의 숫자에 매칭되며, 이는 캡처 그룹으로 저장됩니다.
  • 코드 수집 및 중복 제거 (Set 사용): while 루프를 통해 문자열에서 모든 매치 결과를 찾아 codes 집합에 추가합니다. Set을 사용하여 동일한 코드가 여러 번 나타나도 중복을 제거합니다.
  • 매핑 배열 생성
    • 각 코드에 대해 원래 엔티티(&#NNN;)와 해당하는 문자(String.fromCharCode(code))를 매핑하여 배열에 저장합니다.
  • 치환 수행
    • 생성된 매핑 배열을 순회하며, 문자열에서 엔티티를 해당 문자로 치환합니다.
    • str.split(entity).join(char)를 사용하여 모든 엔티티를 한 번에 치환합니다.

String.fromCodePoint()에 대한 상세 설명

String.fromCodePoint()는 ES6에서 도입된 함수로, 유니코드 코드 포인트를 받아 해당하는 문자로 변환합니다. 이 함수는 String.fromCharCode()와 유사하지만, 서로 다른 점이 있습니다.

  • String.fromCharCode()는 UCS-2 코드 단위를 사용하며, 0xFFFF(65535)까지의 코드 포인트만 처리할 수 있습니다.
  • String.fromCodePoint()는 UTF-16 코드 포인트를 지원하며, 0x10FFFF(1114111)까지의 모든 유니코드 코드 포인트를 처리할 수 있습니다. 따라서 이모지나 기타 보조 평면 문자들을 올바르게 처리할 수 있습니다.
// 이모지 코드 포인트 (U+1F600)는 128512
String.fromCharCode(128512); // 반환값: 오류 또는 예기치 않은 문자
String.fromCodePoint(128512); // 반환값: "😀"

따라서, 만약 처리하려는 코드 포인트가 0xFFFF를 넘는 경우(예: 이모지), String.fromCodePoint()를 사용하는 것이 적절합니다.

String.raw()에 대한 상세 설명

String.raw()는 태그된 템플릿 리터럴의 일종으로, 템플릿 문자열 내에서 이스케이프된 시퀀스를 그대로 처리할 수 있게 해줍니다.

  • 일반적으로 템플릿 문자열 내에서 \n, \t 등의 이스케이프 시퀀스는 해당하는 제어 문자로 변환됩니다.
  • String.raw()를 사용하면 이러한 이스케이프 시퀀스를 실제 문자 그대로 취급합니다.
const str = String.raw`Hello\nWorld`;
// str의 값: "Hello\\nWorld"
// 실제 출력 시: Hello\nWorld (이스케이프가 적용되지 않음)

이 기능은 정규식 패턴이나 파일 경로 등 이스케이프 시퀀스를 그대로 유지해야 하는 경우에 유용합니다.

종합적으로 활용에 대한 도움말

  • HTML 특수문자 코드 처리 시
    • String.fromCharCode(): 기본적인 유니코드 값(0~65535)에 해당하는 문자를 얻을 때 사용합니다.
    • String.fromCodePoint(): 서플리먼터리 플레인(보조 평면) 문자들, 예를 들어 이모지나 기타 특별한 문자를 처리할 때 사용합니다.
      • 따라서, 치환해야 하는 코드 포인트가 65535를 넘을 가능성이 있다면 String.fromCodePoint()를 사용하는 것이 좋습니다.
    • 예시
      const char = String.fromCodePoint(code);
  • 이스케이프된 문자열을 처리할 때
    • String.raw()를 사용하여 이스케이프 시퀀스를 그대로 유지하는 문자열을 생성할 수 있습니다.
    • 이는 정규식 패턴, 파일 경로, 또는 HTML 템플릿 등을 작성할 때 유용합니다.
  • 추가적인 함수 및 메서드
    • encodeURI(), decodeURI(): URL 전체를 인코딩/디코딩할 때 사용합니다.
    • encodeURIComponent(), decodeURIComponent(): URL의 일부(쿼리 파라미터 등)를 인코딩/디코딩할 때 사용합니다.
    • escape(), unescape(): 문자열을 유니코드 이스케이프 형태로 인코딩/디코딩합니다. 하지만 이는 더 이상 사용이 권장되지 않습니다.

실용적인 조언

  • 데이터의 범위 파악: 처리하려는 특수문자 코드의 범위를 파악하여 적절한 함수를 선택합니다. 이모지나 확장 유니코드 문자가 포함될 수 있다면 String.fromCodePoint()를 사용하세요.
  • 성능 고려: 대량의 텍스트를 처리할 때는 정규식과 반복문을 효율적으로 사용하여 성능을 최적화해야 합니다.
  • 보안 이슈: 입력 데이터가 외부로부터 제공되는 경우, 악의적인 코드 삽입을 방지하기 위해 추가적인 검증이나 인코딩이 필요할 수 있습니다.

예시 코드 개선

위의 내용을 반영하여, String.fromCodePoint()를 사용하도록 코드를 수정하고, 이모지 등 확장 문자를 안전하게 처리할 수 있게 합니다.

function decodeHtmlEntitiesWithMappings(str) {
  // '&#NNN;' 형태의 모든 매치를 찾습니다.
  const regex = /&#(\d+);/g;
  let match;
  let mappings = [];
  let codes = new Set();

  // 중복을 제거하여 모든 코드를 수집합니다.
  while ((match = regex.exec(str)) !== null) {
    codes.add(parseInt(match[1], 10));
  }

  // 매핑 배열을 생성합니다.
  codes.forEach(code => {
    const entity = `&#${code};`;
    const char = String.fromCodePoint(code);
    mappings.push([entity, char]);
  });

  // 매핑을 사용하여 치환을 수행합니다.
  mappings.forEach(([entity, char]) => {
    str = str.split(entity).join(char);
  });

  return str;
}

이러한 함수들과 방법들을 종합적으로 이해하고 활용하면, HTML 특수문자 코드뿐만 아니라 다양한 문자열 처리 작업에서 강력한 도구로 활용할 수 있습니다. 특히 유니코드와 이스케이프 시퀀스에 대한 이해는 웹 개발에서 중요한 부분이므로, 필요에 따라 적절한 함수를 선택하여 사용하시기 바랍니다.

728x90

댓글