리액트(React) 컴포넌트, 라이프사이클의 과거와 현재(useEffect)

클래스형 컴포넌트와 함수형 컴포넌트의 라이프사이클과 이벤트

1. 클래스형 컴포넌트와 라이프사이클(Life-cycle)

라이프사이클 이벤트는 컴포넌트의 렌더링과 DOM 이벤트 등을 의도대로 관리할 수 있으며, 이를 통해 성능을 개선할 수 있습니다.

클래스형 컴포넌트의 라이프사이클은 다음과 같이 세 가지로 분류하며, 각 메소드는 자주 사용하거나 유의할 부분만 정리하겠습니다.


  • 마운팅(Mounting) – 컴포넌트가 생성될 때 한 번만 실행(아래 순서대로 실행)

– constructor()

UNSAFE_componentWillMount() -> version 17부터 공식적으로 권장X

render()

– componentDidMount()

  • 업데이트(Update) – props 또는 state가 변경될 때마다 실행

UNSAFE_componentWillReceiveProps() -> 권장X

UNSAFE_componentWillUpdate() -> 권장X

render()

– componentDidUpdate(prevProps, prevState, snapshot)

  • 언마운팅(Unmounting) – 컴포넌트가 제거될 때 한 번만 실행

– componentWillUnmount()


위와 같이 각각의 컴포넌트는 [ 마운팅 -> 업데이트(반복) -> 언마운팅 ]의 라이프사이클을 갖습니다.

이전에는 직관적인 이름을 갖는 다양한 메소드(componentWillMount, componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate)를 통해 이벤트 발생 시점마다 세세한 조작이 가능했으나 현재는 버그나 안전성의 이유로 점점 더 단순해지고 있습니다.

위 기능을 모두 대체하는 훅(Hook)이 너무 편해서 클래스형 컴포넌트를 반드시 사용해야 하는 상황이 아니라면 함수형 컴포넌트와 함께 useEffect를 사용하는 방법이 권장되고 있습니다.

라이프사이클 별로 메소드를 사용하는 방법은 다음과 같습니다.

class TestList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter:0
    }
  }

  // 마운팅 직후 실행
  // 마운팅 전 실행은 constructor() 사용
  componentDidMount(){
     console.log('component Mounted');
  }

  // 업데이트 후 이전 데이터를 파라미터로 가져옴
  componentDidUpdate(prevProps) {
     if(prevProps !== this.props) {
            this.setState({counter:++this.state.counter})
     }
  }

  // 언마운팅 직전 실행
  componentWillUnmount(){
     console.log('component Unmounted');
  }

  render() {
    return (
      <div>{this.state.counter}</div>
    );
  }
}

마운팅 이벤트는 실제 DOM에 컴포넌트를 추가하는 이벤트입니다.

마운팅 이벤트는 다른 프레임워크나 라이브러리 또는 데이터와 연결하는 작업에 적절합니다.

업데이트 이벤트는 컴포넌트의 업데이트와 관련이 있으며, props, state 등의 변경이 있을 때 렌더링 관련한 작업을 설정합니다.

언마운팅은 DOM에서 요소를 분리하거나 제거하는 이벤트입니다.

언마운팅 이벤트는 타이머 제거, 요소 제거, 이벤트 제거 등 설정한 요소의 정리, 제거에 사용합니다.


2. 함수형 컴포넌트와 useEffect(Hook)

리액트 16.8부터 추가된 훅(Hook)은 클래스를 사용하지 않아도 state 또는 리액트의 여러 기능을 편하게 사용하도록 해주는 기능입니다.

이 중 useEffect 훅은 라이프사이클과 관련이 있는데요.

리액트 공식 문서에서 useEffect를 위와 같이 설명합니다.

즉 componentDidMount, componentDidUpdate, componentWillUnmount를 모두 합쳐 놓은 것과 같은 기능을 하는 것이 useEffect입니다.

모두 합쳐 놓았지만 작성 방법에 따라 각각의 기능을 구현할 수 있습니다.

먼저 함수의 시그니쳐는 다음과 같은 모습이며, 첫 번째는 실행할 함수, 두 번째는 조건을 배열로 전달하며 두 번째 매개변수는 생략이 가능합니다.

useEffect(함수, 배열);

  useEffect(() => {
      console.log('useEffect is working');
  });

– 마운팅만 설정(=componentDidMount)

마운팅 시에만 실행하고 싶은 경우에는 두 번째 매개변수로 빈 배열을 전달하면 됩니다.

function testStatus(props) {

  useEffect(() => {
      console.log('useEffect on mounting');
  },[]);

  return <div>test</div>;
}

– 언마운팅만 설정(=componentWillUnmount)

언마운팅 시에만 실행하고 싶은 경우에는 함수를 리턴하면서 두 번째 매개변수로 빈 배열을 전달하면 됩니다.

function testStatus(props) {

  useEffect(() => {
      
      console.log('useEffect on mounting');

      return () => {
        console.log('useEffect on unmounting');
      }

  },[]);

  return <div>test</div>;
}

– 데이터 업데이트마다 설정(=componentDidUpdate)

useEffect에서 두 번째 매개변수를 전달하지 않으면 렌더링마다 해당 훅이 실행됩니다.

하지만 관련 없는 데이터로 인한 리렌더링에도 훅이 실행되면 의도치 않은 결과를 낳거나 성능의 저하를 불러올 수 있으므로 실행의 기준이 되는 데이터를 지정하고 실행 시점을 설정할 수 있습니다.

이를 위해서는 두 번째 매개변수인 배열에 체크할 데이터를 넣으면 됩니다.

function testEffect(props) {

  useEffect(() => {
      console.log('re-rendering');
  });

  useEffect(() => {     
      console.log('props is changed');
  },[props.data]);

  return <div>test</div>;
}


useEffect를 사용하면서 몇 번의 시행착오만 거치면 원하는 기능을 어느 정도 구현할 수 있습니다.

하지만 라이프사이클에 대한 이해 없이 계속 사용한다면 어느 순간 ‘시간을 갈아 넣어 짠 코드’는 시간 앞에 무릎을 꿇게 될 수도 있을 것 같습니다.

ジャバスクリプトで配列を結合(マージ)する良い方法(javascript)

配列を結合する便利な三つのやり方(concat(), …spread, push())

ジャバスクリプトを使ってデータを扱うことが多くなり、配列を使用する仕組みも増えていきます。

その中、マージ(結合)についてちらっと調べてみますね。


配列(array)はインデックスを持つ要素を順に並べる構造です。

一つの配列ならインデックスまたはメソッド(unshift(), push(), shift(), pop(), splice(), find(), includes(), join(), indexOf()など)を使って配列中のデータを便利に操作することができます。

配列間のマージ方法も同じくconcat(), push(), …spreadなどが存在します。

一つづつ確認してみます。

1. 配列結合の三つ方法

concatenate(連結する意味)の略字であるconcat()は意味通り配列両方を繋ぎます。

次のように扱うので、サンプルから確認してみます。

  • [array1].concat([array2]…..)
  • [].concat([array1], [array2]……)
  • const color1 = ['blue', 'pink', 'white'];
    const color2 = ['black', 'orange', 'yellow'];
    const num1 = [100, 200, 300];
    const num2 = [400, 500, [600, 700]];
    
    const allColor = color1.concat(color2); 
    //['blue', 'pink', 'white', 'black', 'orange', 'yellow']
    console.log(allColor); 
    
    const colorPlus = color1.concat('gold', ['silver', 'bronze']); 
    //['blue', 'pink', 'white', 'gold', 'silver', 'bronze']
    console.log(colorPlus);
    
    const colorAndNum = color1.concat(num1);   
    //['blue', 'pink', 'white', 100, 200, 300]
    console.log(colorAndNum); 
    
    const allNum = num1.concat(num2);   
    //[100, 200, 300, 400, 500, [600, 700]]
    console.log(allNum); 
    

    concatは一つ以上の配列を結合し、一つの配列にします。

    配列中のデータの形式(タイプ)にかかわらず結合できるし、ネストされている配列(配列中にまた配列がある構造)の結合もできます。


    ES6から追加された文法の一つであるスプレッド構文は配列或はオブジェクトを速くて安全にコピーすることができます。

    深いコピー(deep copy)方法でコピーするので、既存のデータとは違うメモリーアドレスを使いますね。

    なので配列の結合方法の中では一番いい方法だと言えます。

    const musician = ['Chet Baker', 'Miles Davis'];
    const actor = ['Clint Eastwood', 'George Clooney'];
    
    const favorites = [...musician, ...actor];    
    // ['Chet Baker', 'Miles Davis', 'Clint Eastwood', 'George Clooney'];
    console.log(favorites); 
    
    const favoritesReverse = [...actor, ...musician];
    // ['Clint Eastwood', 'George Clooney', 'Chet Baker', 'Miles Davis'];
    console.log(favoritesReverse)
    
    

    また、スプレッド構文は次のように非構造化ではよくつかわれています。

    const myColor = ['beige', 'burgundy', 'charcoal', 'ivory'];
    
    const [color1, color2, ...others  ] = myColor;
    console.log(color1);   // 'beige'
    console.log(color2);   // 'burgundy'
    console.log(others);   // ['charcoal', 'ivory']

    push()は配列の最後に要素を追加するときよく使うメソッドです。

    push()メソッドとスプレッド構文を一緒に使うと配列の結合ができます。

    でもこの方法は既存データの上に新しいデータを上書きするので既存データの変更に注意する必要があります。

    const pizza = ['dough', 'cheese', 'meat', 'source'];
    const pizzaAdd = ['parmesan', 'tabasco'];
    
    pizza.push(...pizzaAdd);   
    
    // ['dough', 'cheese', 'meat', 'source', 'parmesan', 'tabasco'];
    console.log(pizza); 
    

    2. 総合

    配列を結合する方法の中concat(), …spread, push()について調べてみました。

    状況により必要な方法が違うので、システムやロジックを考えた上で選んだら問題はないと思います。

    あざーす!

    개발자의 중국어 사전(程序员的词典)

    프로그래밍 관련 중국어(汉语)-한국어(韩语) 용어 사전

    프로그래밍 관련 서적 번역 중 정리한 프로그래밍 관련 단어입니다.

    中韩翻译过程中遇到的常用单词和编程术语。


    ㄱ – ㅁ

    • 내림차순 – 降序排序 (jiàng xù pái xù)
    • 너비우선 검색 – 广度优先搜索 (guǎng dù yōu xiān sōu suǒ)
    • 네임스페이스 – 命名空间 (mìng míng kōng jiān)
    • 동적계획법 – 动态规划 (dòng tài guī huá) = 动归 (dòng guī)
    • 디버깅 – 调试 (diào shì)
    • 로직 – 逻辑 (luójí)
    • 리스트 – 列表 (liè biǎo)
    • 리턴 – 返回 (fǎn huí)
    • 링크드리스트 – 链表 (liàn biǎo)
    • 메모리 – 内存 (nèi cún)
    • 메모이제이션 备忘录 (bèi wàng lù)
    • 메서드 – 成员函数 (chéng yuán hán shù)
    • 매핑 – 映射 (yìng shè)
    • 무차별 탐색(brute force search) – (暴力解法 bào lì jiě fǎ) (=완전 탐색)
    • 문자열 – 字符串 (zì fú chuàn)
    • 미들웨어 – 中间件 (zhōng jiān jiàn)

    ㅂ – ㅈ

    • 바이너리 – 二叉(èr chā)
    • 배열 – 数组 (shù zǔ)
    • 선언 – 声明 (shēng míng)
    • 순회 – 遍历 (biàn lì)
    • 스택 – 堆栈 (duī zhàn)
    • 액세스 – 访问 (fǎng wèn)
    • 역직렬화 – 反序列化 (fǎn xù liè huà)
    • 역추적 – 回溯 (huí sù)
    • 오름차순 – 升序排序 (shēng xù pái xù)
    • 오버플로우 – 溢出 (yìchū)
    • 완전 탐색 穷举算法 (qióng jǔ suàn fǎ) (=무차별 탐색)
    • 음수 – 负数 (fùshù)
    • 의사 결정 트리 – 决策树 (jué cè shù)
    • 의사코드 – 伪码 (wěi mǎ)
    • 입력 – 输入 (shū rù)
    • 조건문 – 条判断语句 (tiáo pàn duàn yǔjù)
    • 직렬화 – 序列化 (xù liè huà)

    ㅊ – ㅎ

    • 카운터 – 计数器(jì shù qì)
    • 캐시 – 缓存(huǎn cún)
    • 큐 – 队列 (duì liè)
    • 쿼리 – 查询 (chá xún)
    • 텍스트 – 文本 (wén běn)
    • 트리 – 树 (shù)
    • 트리거 – 触发 (chù fā)
    • 패키지 – 包 (bāo)
    • 피보나치 수열 – 斐波那契数列(fēi bō nà qì shù liè)
    • 클래스 – 类 (lèi)
    • 클립보드 – 剪贴板 (jiǎn tiē bǎn)
    • 할당 – 赋值 (fù zhí)
    • 함수 시그니쳐 – 函数签名 (hán shù qiān míng)
    • 해시테이블 – 哈希表 (hā xī biǎo)
    • 헤더 – 头文件 (tóu wén jiàn)

    자바스크립트, 편리한 배열 병합 방법(Merge Arrays in Javascript)

    자바스크립트의 배열 병합 방법(concat(), …spread, push())

    자바스크립트를 사용해 데이터를 다루는 일이 점점 더 많아지고, 배열을 사용하는 관련 작업을 많이 하게 됩니다.

    그 중에서도 병합과 관련된 부분에 대해 알아보도록 하겠습니다.


    배열은 인덱스(Index)를 갖는 요소를 순서대로 나타낸 데이터 구조입니다.

    하나의 배열이라면 인덱스 또는 메소드(unshift(), push(), shift(), pop(), splice(), find(), includes(), join(), indexOf() 등)를 사용해 배열 내부의 데이터를 쉽게 다룰 수 있죠.

    배열의 병합(Merge) 또한 마찬가지입니다.

    concat(), push(), 스프레드 연산자(…spread), 등 배열의 병합을 위한 여러 방법이 존재합니다.

    하나씩 확인해 보겠습니다.

    1. 배열 병합의 3가지 방법

    concatenate(연결시키다, 사슬같이 잇다)의 약자인 concat()은 말 그대로 두 배열을 연결하는 역할을 합니다.

    크게 다음과 같은 방식으로 사용하며, 샘플 코드를 통해 조금 더 상세한 부분을 확인하겠습니다.

    • [array1].concat([array2]…..)
    • [].concat([array1], [array2]……)
    const color1 = ['blue', 'pink', 'white'];
    const color2 = ['black', 'orange', 'yellow'];
    const num1 = [100, 200, 300];
    const num2 = [400, 500, [600, 700]];
    
    const allColor = color1.concat(color2); 
    //['blue', 'pink', 'white', 'black', 'orange', 'yellow']
    console.log(allColor); 
    
    const colorPlus = color1.concat('gold', ['silver', 'bronze']); 
    //['blue', 'pink', 'white', 'gold', 'silver', 'bronze']
    console.log(colorPlus);
    
    const colorAndNum = color1.concat(num1);   
    //['blue', 'pink', 'white', 100, 200, 300]
    console.log(colorAndNum); 
    
    const allNum = num1.concat(num2);   
    //[100, 200, 300, 400, 500, [600, 700]]
    console.log(allNum); 
    

    위와 같이 concat은 하나 이상의 배열을 합쳐 하나의 배열로 만듭니다.

    배열 내부 데이터 타입에 상관없이 병합이 가능하며, 중첩된 배열의 병합도 가능합니다.

    ES6에서 추가된 문법인 스프레드 연산자는 배열이나 객체를 빠르고 안전하게 복사할 수 있습니다.

    깊은 복사(Deep copy) 방식으로 복사를 진행해 기존의 배열 데이터와는 다른 메모리 주소를 사용하므로 배열 병합 방법 중에서는 가장 좋은 방식이라고 볼 수 있습니다.

    const musician = ['Chet Baker', 'Miles Davis'];
    const actor = ['Clint Eastwood', 'George Clooney'];
    
    const favorites = [...musician, ...actor];    
    // ['Chet Baker', 'Miles Davis', 'Clint Eastwood', 'George Clooney'];
    console.log(favorites); 
    
    const favoritesReverse = [...actor, ...musician];
    // ['Clint Eastwood', 'George Clooney', 'Chet Baker', 'Miles Davis'];
    console.log(favoritesReverse)
    
    

    스프레드 연산자는 다음과 같이 비구조화 할당에서도 자주 사용됩니다.

    const myColor = ['beige', 'burgundy', 'charcoal', 'ivory'];
    
    const [color1, color2, ...others  ] = myColor;
    console.log(color1);   // 'beige'
    console.log(color2);   // 'burgundy'
    console.log(others);   // ['charcoal', 'ivory']

    push() 메소드는 배열 끝에 데이터를 추가할 때 자주 사용하는 메소드입니다.

    push() 메소드와 스프레드 연산자를 같이 사용하면 배열 병합이 가능하지만 기존 배열에 데이터를 추가하는 방식이므로 기존 배열이 변경되는 부분을 주의해야 합니다.

    const pizza = ['dough', 'cheese', 'meat', 'source'];
    const pizzaAdd = ['parmesan', 'tabasco'];
    
    pizza.push(...pizzaAdd);   
    
    // ['dough', 'cheese', 'meat', 'source', 'parmesan', 'tabasco'];
    console.log(pizza); 
    

    2. 마무리

    배열을 병합하는 여러 가지 방법 중 concat(), …spread, push() 세 가지를 소개하였습니다.

    각 상황에 따라 필요한 방법이 다르니 필요에 따라 맞는 것을 골라 사용하면 좋을 것 같습니다.

    감사합니다!

    やすくて速い正規表現(Easy Regular Expression)

    正規表現の構成と意味、ジャバスクリプト(Javascript)でのお扱い

    正規表現というのは検索パータンを指定し記号で表示したものです。

    このアイデアはアメリカの数学者であるスティーブンコールクリーン(Stephen Cole Kleene)が1950年代に正義した正規言語(Regular Language)と関係がありまして、正規表現の文法は1980年代にパール(Perl)言語から使い始まりました。

    主に、検索や置換の作業に使われ、皆が使うほとんどのプログラミング言語の中でサポートされている文法です。

    例えば、次の文章の中で特定した条件を検索するとき正規表現の力を借りることができます。

    The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.

    • ‘too’ 文字列を検索する -> /too/
      The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.
    • 大、小文字を構わなく ‘t’ 文字を検索するとき -> /t/-gi
      The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.
    • ‘d’ から始まる単語及び文字のすべてを検索するとき -> /[d]\w+/-gi
      The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.
    • ‘ea’を含む単語を検索するとき -> /[a-z]*ea[a-z]*/-i
      The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it

    正規表現の文法テストは次のページが助かります。

    regexr.com

    青いバーExpressionの下のインプットには表現を入れ書き、その下のボックスには検索対象になるテキストを入れればオッケーです。

    まず、表現の意味について少し勉強してからJavascriptで楽に使う方法を確認してみます。


    1. 正規表現の記号

    • / . / → すべての文字
    • / + / → 一つ以上の文字
    • / ? / → 0または一つの文字
    • / ^ / → 該当の文字を除く
    • / / → 範囲指定
    • / * / → 0または一つ以上の文字
    • / [ ] / → グループセット
    • / { } / → 繰り返しの回数指定
    • / \ / → エスケープ
    • / \d / → すべての数字
    • / \D / → 数字ではない文字
    • / \w / → アルファベット、数字、アンダーバー
    • / \W / → アルファベット、数字、アンダーバーではない文字
    • / \s / → 空白文字
    • / \S / → 空白ではない文字
    • / \n / → 改行

    基本的に正規表現を構成する記号は上記であり、この記号さえ覚えれば正規表現の基本的な仕組みは十分理解できると思います。

    それではサンプルを参考しながら正規表現を分析していきましょう。


    2. 記号の意味

    正規表現で一番基礎になる記号であるので覚えておくと役に立ち部分です。

    dは数字、 wは英文字、 sは空白、 nは改行の意味であり、各文字の大文字は NOT(反対)を示します。

    • 数字が一回以上繰り返す文字検索 ? / [\d]+ /
    • 数字ではない文字を検索(空白含む) ? / [\D] /
    • 括弧(かっこ)が含まれている文字、数字検索 ? / \([\w]+\) /
    • 英文字、数字、アンダーバーではない文字検索 ? / [\W]+ /
    • 空白検索 ? / \s /

    上で紹介したregexr.comで検索対象になるテキストをいれてパータンを直接に作成してみるとすぐ正規表現になれると思います。


    大体エスケープというのは何ですかね。

    キーボードの一番左一番上のキー(ESCと書かれているもの)がエスケープの略字です。エスケープの意味は逃れるのです。

    こちらでは約束から逃れることだと認識すればいいと思いです。

    例えば、正規表現で点(. dot)はすべての文字の意味にしようと約束した特別な文字ですね。

    でもたまには’それ約束以外’に点をピリオド意味の点で使いたいときがありますね。

    この時エスケープを使います。

    エスケープを使わない限り、文字は約束した機能として動きます。

    下の例で確認しましょう。

    • すべての文字を意味。 a, b, c, d, ?, !, @, , などすべての文字の中一つ ? / . /
    • エスケープを前につけるとただピリオド記号だけの意味 ? / \. /
    • 一つ以上の文字の意味 ? / + /
    • エスケープを前につけるとただプラス記号だけの意味 ? / \+ /

    エスケープはよく使われる必須な機能であるので、そのままの文字にはならないのでエスケープが必要な特別な文字(. ? + *など)を覚えておく必要があります。

    その文字の一部を下で紹介します。


    上で紹介した特別な記号は特別な意味を持ちます。代表的な使い方は下の通りです。

    • 小文字a~z或は大文字A~Z中一致する英文字検索 ? / [a-zA-Z] /
    • color或はcolourを検索(‘u’があってもなくてもいい) ? / colou?r /
    • ‘a’を含む単語検索 ? / [\S]*a[a-zA-Z]* /
    • a-z或は空白(space)ではない文字検索 ? / [^a-z ] /
    • 英文字から始め必ず数字または特殊記号を含む文字列を検索 ? / [a-zA-Z]+[\d!@#\$%\^*]+[\w]* /

    中括弧は繰り返しの回数を指定し、これを使うと詳しい検索パータンの設定が可能です。

    中括弧の中、一つの数字は全体の繰り返し回数の意味であり、二つの数字は頭と末の範囲を指定する意味です。

    例え、{3}は3回繰り返しの意味であり、{1, 3}は範囲区間1から3の意味です。

    {1, }のような表現も可能であり、これは+記号と同様な意味, つまり一つ以上の意味であります。

    • Aが3回繰り返す文字を検索 ? / [A]{3} /
    • 3桁以上の数字を検索(3번以上繰り返し) ? / [\d]{3,} /
    • Aが二回から三回まで繰り返す文字を検索(繰り返す範囲指定) ? / [A]{2,3} /

    繰り返し回数だけを指定すれば、意図しない結果が出ることがあるので、部分式(subexpression)と全後方一致検索を一緒に使うともっと効果的なパータンが可能です。


    角かっこの中に記号を書き、検索パータンを指定します。直接に記号を書き込んだり、範囲指定記号の’-‘を使ってパータンを指定します。

    • 指定する文字(a 或は A 或は b 或は B 或は c 文字)一つを検索 ? [aAbBc]
    • aから eまで(a,b,c,d,e)の範囲内一つの文字を検索 ? [a-e]
    • 除外文字’^’があるので a-z 範囲に入らない文字(記号)を一つ検索 ? [^a-z]
    • 明記した記号の一つを検索 ? [?!@#$%^&*()_]
    • c或はCから始め, a-zの中一つで終わる単語検索 ? [cC][a-z]

    [ ]を使うと一つだけの文字を検索するので一つ以上の文字を検索したいときには+記号(一つ以上の文字、0は不可)または*(0または一つ以上の文字、0も可能)記号を付ける必要があります。

    • 一つ以上のa-z文字を検索(必ず一つ以上の条件) ? [a-z]+
    • 0個以上のA-Z文字を検索(なくてもいい) ? [A-Z]*

    特定構成で成り立つ文字列の検索に効果的であり、例えばメールアドレスの文字列があります。

    メールアドレス形式のabcd@xyz.comを検索するためには次のようなパータンを使うことができます。

    /[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z]+/

    では、パータンを分析してみます。

    先、メールのIDになる部分は英文字と数字が入るので、[a-zA-Z0-9]で始め一つ以上を意味する+記号を付けます。

    その次、@が続きますので@を入れ, ホストのアドレスも一つ以上の英文字と数字を指定します。

    .com形のアドレスなのでピリオドをそのまま使うためエスケープを使いまた一つ以上の英文字を入れてパータンを生成します。

    もしIDの中に点が入るかホストアドレスが.co.jpなどの形になるときにはそれに対する応用が必要です。



    3. まとめ

    正規表現の第一印象はまるで外界言語みたいな姿で広く使われる既存の言語とは違う様子をしてますね。

    軽く近づけられなくいやな気持がするときもありますが、少しだけでも調べてみたら意外と簡単な規則でパワフル機能を持っていいやつだなと思われる時が来るかもですね。

    上で紹介した部分は代表的な機能を紹介するため簡単なパータンたちなので、上のパータンは不完全なパータンであります。もの正しいパータンを作るためにはもっと深く勉強する必要がありますね。

    ご質問がありましたら、自由にコメントください!

    あざーす!

    AWS EC2 – From Launch New Instance To Install Everything We Need

    Simple Explanation Of Setting up AWS EC2(Ubuntu18.04)

    1. Launch New Instance In AWS

    On a EC2 Management Console page, launch instances and choose Ubuntu Server 18.04 LTS with adequate instance type.

    I chose t2 micro Type and launched.

    On the next page, click Edit security groups and open port 22, 80, 443 for the next step.

    Before launch the instance, you should select an existing key pair or create a new one.

    If you don’t have any, create a new one and download key pair.

    You should keep that key pair safe and don’t let be exposed to anyone.

    We need an elastic IP address(Non-change address) for our accessibility.

    Elastic IP lasts forever even if you stop the instance unless you release the IP address.

    EC2 -> Network & Security -> Elastic IPs -> Allocate Elastic IP address.

    Associate Elastic IP address and Choose an instance to stick them together.

    Half way there.

    Now you have your own instance and elastic IP address.

    Keep going.

    2. Connect To The Server Using SSH Client

    You can use any SSH Client whatever you want.

    This time I chose XShell7 that is free for Home/School.

    Put the IP address in Host textbox.

    Go to Authentication, write User Name ‘ubuntu’ and check Method Public Key.

    Click Connect.

    Browse and select the key pair that we downloaded.

    If you get this message, now you are in.

    3. Install Nodejs On Ubuntu Server

    $ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
    
    $ sudo apt-get install -y nodejs

    Execute line by line and when it’s done, we can check by ‘node -v’ command.

    If node version(v14.18.2 or something) is printed, installation is done.

    4. Install MongoDB On Ubuntu Server

    $ wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -

    If you see ‘OK‘ return with above command, you are ready for the next step.

    $ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list

    If you see ‘echo “deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse” | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list‘, move forward.

    $ sudo apt-get update
    $ sudo apt-get install -y mongodb-org

    If you feel like something goes on a busy process, just wait.

    When it’s done, check an installation with this command.

    ‘mongo -version’

    Start mongodb service with this command.

    $ sudo service mongod start

    When successfully started, no message output.

    $ mongo
    
    > use admin
    
    > db.createUser({ user:'id', pwd:'pwd', roles:[{"role":"userAdminAnyDatabase","db":"admin"},{"role":"readWriteAnyDatabase","db":"admin"}]})
    
    exit

    Have to change some codes for accessibility and security.

    $ sudo vi /etc/mongod.conf

    binIp : 127.0.0.1 -> bindIp: ::, 0.0.0.0

    #security -> refer to above capture. no space before ‘enabled’ makes error.

    save it!(‘wq’ command)

    If you want to give a access try, use Compass with 27017 port opened.

    5. Deploy(git clone)

    Use Git, clone your project to your instance and install dependencies.

    $ git clone https://github.com/id/repo
    
    $ cd repo
    $ npm install

    6. Run Server With PM2

    Install pm2 and run your own server.

    pm2 makes your server keep running if you close the shell.

    $ sudo npm install pm2 -g
    
    $ sudo pm2 start index.js //in my case with arguement -> sudo pm2 start src/index.js --node-args="-r esm"

    Now, your server won’t stop unless you stop the PM2.

    You can check the PM2 status with below command.

    $ sudo pm2 list

    7. Install Nginx On Ubuntu Server

    Nginx has additional functions that Nodejs do not have.

    Simply in two ways, security and load balancing.

    $ sudo apt-get install nginx

    We opened port 80 for Nginx access.

    When Nginx works, clients come in through Nginx door and Nginx leads them to internal port.

    $ sudo service nginx start

    When Nginx started, access it with your ip address.

    Like http://3.34.65.190

    Nginx welcomes you if you are on right process.

    Now, Change some codes as below with vi editor to complete Nginx work.

    $ cd /etc/nginx/sites-enabled
    
    sudo vi default

    Comment out try_files $uri $uri/ =404; and add

        proxy_pass http://yourIP:port/;
        proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header X-Nginx-Proxy true;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_pass takes clients to internal port that you set on Nodejs.

    In my case, http://3.34.65.190:4000/;

    Save it.

    Next step is set a size limitation.

    Nginx’s default file size setting is 1MB.

    But if your page handles bigger than 1 MB files upload or download, this setting is necessary.

    $ sudo vi /etc/nginx/nginx.conf
    client_max_body_size 10M(limit size that you want);

    Now, restart Nginx.

    sudo service nginx restart

    Now you can access you page that you made.

    8. SSL certificate with Let’s Encrypt(http ->https)

    Using Route53 service, get a own domain and manage DNS.

    Redirect to your IP address and when you have your own domain, you can get a SSL certification with Let’s Encrypt for free.

    $ sudo add-apt-repository ppa:certbot/certbot
    
    $ sudo apt install python-certbot-nginx
    
    $ sudo certbot --nginx -d yourdomain.com

    Follow the direction, and then your web can get a SSL certification and https protocol is available.

    The direction is simple.

    1. enter your email address

    2. Agree

    3. Yes(or No)

    4. choose No.2 (redirect http to https option)

    And that’s it.

    Important thing for the last step is opening the port 443.

    Port 443 is a port for https.

    Restart Nginx and access with your domain address.

    Automatically https will welcome you.

    Every 90 days, certification renewal is required and below is the command.

    $ sudo certbot renew --dry-run

    AWS : aws.amazon.com

    Nodejs에서 배치(Batch) 기능 사용하기(node-schedule)

    예정된 시간에 작업을 수행하는 node-schedule

    별도의 SQL문을 사용해 배치(Batch) 기능을 사용하던 것과 비교하면 정말 편하게 프로그래밍이 가능하도록 도와주는 라이브러리입니다.

    배치 기능을 사용할 수 있는 대표 라이브러리는 크게 3가지(Agenda, node-cron, node-schedule)이며, 인기는 다음과 같습니다.

    1. Agenda (2021/12/22 기준 주간 다운로드 수 56,319)
    2. node-cron(2021/12/22 기준 주간 다운로드 수 219,168)
    3. node-schedule(2021/12/22 기준 주간 다운로드 수 507,675)

    필요한 기능이 동일하다면 사용자가 많은 쪽이 관련 정보도 얻기 쉬우므로 node-schedule을 사용해보겠습니다.

    npm install node-schedule
    

    설치 후 해당 라이브러리를 import합니다.

    import schedule from 'node-schedule';

    그리고 서버를 가동하면 바로 실행될 수 있도록 index.js에 실행 함수를 넣어주면 됩니다.

    실행될 조건(시간 또는 반복 주기)을 넣어주면 해당 조건에 맞춰 함수를 실행합니다.

    const regularExec = schedule.scheduleJob('0 0 12 * * *', ()=>{ // 매일 낮 12시 정각마다 실행
    
        sendCheckDataEmail();
    
    })

    위 함수는 매일 낮 12시마다 실행됩니다.

    scheduleJob의 첫 번째 파라미터의 값은 다음과 같습니다.

    *는 all과 값은 의미이며, 각 파라미터의 사이에는 빈칸을 넣어줍니다.

    초를 넣는 부분인 second 에 *를 넣으면 모든 초마다 실행하라는 의미가 됩니다.

    따라서 minute에 5, second에 *을 넣으면 5분00초부터 5분59초까지 함수가 총 60번 실행됩니다.

    주기를 설정하는 방법도 있는데요.

    second에 */5로 표기하면 초 단위를 5초 단위로 쪼갭니다.

    따라서 5초에 한 번씩 실행하라는 의미가 됩니다.

    취소는 cancel 메소드를 사용하면 됩니다.

    regularExec.cancel();

    유의할 점은 서버가 실행 중일 때만 해당 스케쥴러가 작동하며, 멀티프로세스를 가동하는 경우 중복으로 실행되지 않도록 별도의 설정을 해주어야 합니다.

    그럼 서버가 열심히 일하도록 스케쥴러 기능을 요긴하게 사용해 주세요!

    Nginx와 AWS S3, 왜 큰 용량은 업로드가 안돼?(413 Request Entity Too Large, React, Koa)

    Nginx 업로드 용량 제한 설정이 필요한 이유

    React, Koa를 사용하고 Nginx를 거쳐 파일 업로드 진행하는 프로세스에서 프론트와 백엔드에서 각각 파일 크기를 체크한 뒤 AWS S3에 저장을 진행하도록 하였으나 다음과 같은 에러가 발생하는 경우가 있습니다.

    이미 파일 크기 체크를 진행하고 업로드한 파일이 용량 문제로 에러가 발생한다니 이건 뭐지 싶지만 답은 Nginx에 있습니다.

    Nginx는 큰 용량의 파일을 대량으로 업로드하는 서버 공격을 막고자 기본 전송 용량 설정이 1MB로 되어 있습니다. 따라서 1MB 이하의 파일을 한번 업로드해보면 바로 해결의 실마리를 찾을 수 있습니다.

    위와 같이 1MB 이하의 파일은 아주 잘 올라갑니다.

    설정을 위해 커맨드에서 아래와 입력합니다.

    # sudo vi /etc/nginx/nginx.conf

    nginx.conf 내부 http 부분에서 client_max_body_size로 설정을 진행합니다.

    기본값은 1MB이며, client_max_body_size는 기본적으로 명시되어 있지 않으므로 별도로 입력이 필요합니다.

    아래와 같이 http{ } 내부에 client_max_body_size와 원하는 용량을 함께 기입해주고 Nginx를 재시작합니다.

    50MB로 설정해두고, Nginx를 리셋해 보겠습니다.

    # sudo service nginx reload

    다시 업로드해보면 이제는 1MB 이상의 파일도 문제 없이 업로드 되는 것을 확인할 수 있습니다.


    참고자료 : https://www.cyberciti.biz/faq/linux-unix-bsd-nginx-413-request-entity-too-large/

    엑셀과 인코딩(UTF-8)의 싸움, 이젠 끝내기로 해(feat.몽고MongoDB와 날짜 처리)

    엑셀 인코딩 문제를 해결하고, mongoDB에 깔끔하게 저장하는 방법

    주로 csv 형식의 파일을 열거나 하나의 프로그램에서 다른 형식의 문서를 불러오면 아래와 같은 문자를 만나는 경우가 있습니다.

    �����������Ǹ�

    .<-9xH#,;}<:@O,A& 8q,;

    이는 문자 인코딩에서 발생하는 문제로, 영어로 썼는데 프랑스어로 해석하는 것과 비슷하다고 보시면 될 것 같습니다.

    인코딩 문제는 주로 비알파펫(非 ALPHABET) 언어를 사용하는 곳에서 자주 발생합니다.

    컴퓨터에서 처음 문자가 사용될 때는 한 문자 당 1바이트를 사용하는 알파벳만 지원되었으므로 이 때는 문자 인코딩이고 뭐고 할 게 없었습니다.

    그러나 차츰 컴퓨터의 사용 영역이 넓어지고 컴퓨터에서 처리할 수 있는 데이터도 늘어나자 다른 언어를 지원하기 위한 방법이 연구되었고, 그 결과 다양한 문자 인코딩이 탄생하였습니다.

    한글과 관련한 인코딩만 찾아봐도 아래와 같이 다양합니다.


    ASCII(American Standard Code for Information Interchange)

    -7bit로 구성되며, 128개의 영문자를 표현

    ANSI(American National Standard Institute)

    -8bit로 구성되며, 256개의 문자를 표현

    EUC-KR(Extended Unix Code – Korea)

    -16bit로 구성되며, 글자 하나하나에 부여된 코드를 사용. 중국어, 일본어, 한국어 등의 표현에 사용

    CP-949(Code Page 949)

    – Windows의 코드 조합으로 EUC-KR의 확장

    UTF-8(Universal Coded Character Transformation Format 8 bit)

    – 가변 길이 문자 인코딩으로 1~4바이트까지 사용. 우리가 원하는 그것.


    위와 같이 다양한 방식을 사용해 문자를 표현하고 있습니다.

    하지만 우리를 화나게 하는 것은 엑셀에서 csv로 내보낸 파일을 다른 프로그램(또는 DB)에서 불러오려고 하면 ‘???????’ 라고 표현하는 그것일 것입니다.

    원인을 살펴보면, 해당 문제를 겪는 대부분은 Windows + 엑셀의 조합일텐데요.

    Windows는 기본적으로 CP-949로 인코딩을 하지만 읽는 프로그램은 UTF-8을 사용하다 보니 주로 발생하는 문제입니다.

    따라서 인코딩 시 UTF-8로 내보내기만 하면 문제는 해결되지만 Windows는 쉽게 UTF-8로 바꿔주려고 하지 않습니다…

    그래서 엑셀로 내보내는 csv 파일을 UTF-8로 변환하는 방법에 대해 알아보겠습니다.

    위와 같은 데이터를 가진 엑셀 친구를 UTF-8 형식으로 만들어 보겠습니다.

    먼저 저 친구를 그냥 csv로 내보내기를 하면 Windows에서 지정한 인코딩 형식으로 내보내기가 됩니다.

    확인해볼까요?

    엑셀 2010을 사용해 테스트를 진행해보겠습니다.

    다른 설정 없이 위와 같이 CSV 형식으로 다른 이름으로 저장을 하고 mongoDB에서 가져오기를 하면 다음과 같이

    ‘알아듣게 얘기하라’는 식의 반응을 보입니다…

    그럼 이제 엑셀에서 인코딩 형식 지정하여 내보내기를 해보겠습니다.

    저장 시 위와 같이 [도구-웹 옵션]으로 들어가면

    이렇게 친절하게 [인코딩] 탭에서 인코딩 형식의 지정이 가능합니다…..만

    파일명을 test(set).csv로 저장해보았습니다.

    하지만 mongoDB에서 위 파일을 불러오면

    mongoDB가 왜! 뭐! 라고 하는 것 같습니다.

    엑셀에서 인코딩 형식을 지정해도 제대로 반영이 되지 않는 것 같습니다.

    물론 최신 엑셀에는 ‘csv 내보내기(UTF-8)’과 같은 방식의 확장자 유형의 선택이 생겼으나 현재는 엑셀 최신 버전이 없어 서 테스트가 불가하므로… 다음.

    여기서는 다른 방식으로 인코딩 형식을 변경해 보도록 하겠습니다.

    엑셀로 저장한 csv를 메모장으로 불러옵니다(엑셀 파일이 아닌 csv 파일입니다).

    메모장에서 ‘다른이름으로 저장’을 선택하여 아래와 같이 인코딩을 UTF-8로 변경해줍니다.

    csv 파일 형식은 유지해야 하므로 파일 형식은 모든 파일(*.*)로 변경해주고 파일 이름의 확장자에는 .csv를 유지합니다.

    그리고 다시 한번 mongoDB에서 조우를 해보겠습니다.

    더이상 반항하지 않습니다.

    하여, IMPORT를 눌러보면!

    문맹은 벗어났으나….

    이제는 날짜를 못 알아먹네요.

    날짜도 입맛에 맞게 맞춰주겠습니다.

    먼저 날짜를 모두 선택하고 ‘.’으로 구분된 기호를 ‘/’로 변경해줍니다.

    CTRL + H를 사용합니다.

    변경 후 해당 칼럼(또는 해당 셀)을 날짜 형식으로 변경해줍니다.

    DB에 저장될 타입을 Date로 변경해줍니다.

    그리고 마지막으로 기회를 한번만 더 주겠습니다.

    그리고 IMPORT!

    더 이상 반항을 하지 않는 착한 데이터를 표현합니다.

    위 날짜 데이터는 toLocaleDateString()과 같은 자바스크립트 함수로 깔끔하게 정리해주면 이쁘게 출력이 가능합니다.

    그럼 더 이상 엑셀과 인코딩으로 스트레스 받지 않기를 바랍니다.

    peace!

    자바스크립트, 문자열 함수 마음대로 다루기(Javascript works with string)

    Javascript String Methods : slice(), substring(), includes(), startsWith(), trim(), replace()…….

    프론트엔드(React, Vue, Angular)와 백엔드(Node.js)가 모두 자바스크립트를 사용하는 시대에 들어서니 자바스크립트의 기초가 몇 배는 더 중요해진 것 같습니다.

    자바스크립트의 문법 중 문자열(String) 관련 함수는 참 쓸 일이 많으면서도 가볍게 여겨져 쉽게 외워지지 않는 슬픈 함수 중 하나인 것 같습니다.?

    문자열 관련 함수는 한 번 외워두면 반복 학습할 일이 많으므로 첫 단추만 잘 꿰면 될 것 같습니다.

    그럼 문자열 관련하여 사용 빈도가 높은 함수인 slice(), substring(), includes(), startsWith(), trim(), replace(), indexOf(), test() 함수에 대해 알아보겠습니다.


    slice 함수는 위치(인덱스)를 매개변수로 전달하여 원하는 문자열을 추출합니다.

    시작 위치(필수)와 종료 위치(옵션)를 전달하며, 시작 위치만 전달하는 경우 시작 위치부터 문자열 끝까지 추출합니다.

    0은 순방향으로 첫 번째(앞에서 1번 째), 음수인 -1은 역방향으로 첫 번째(뒤에서 1번 째)를 나타냅니다.

    const myWord = 'primavera';
    
    myWord.slice(0,5);   // 'prima'
    myWord.slice(-4);    // 'vera'
    myWord.slice(3);     // 'mavera'
    
    myWord.slice(3,1);    // '' -> slice함수는 시작인덱스가 종료인덱스보다 크면 빈 값을 반환

    substring 함수도 slice와 마찬가지로 위치(인덱스)를 매개변수로 전달하여 원하는 문자열을 추출합니다.

    기본적인 작동 방식은 같으나 slice와 달리 시작인덱스가 종료인덱스보다 큰 경우에는 자동으로 두 값의 위치를 변경하여 함수를 실행합니다.

    또한 substring은 매개변수에 음수를 넣으면 이 값을 0으로 인식합니다.

    따라서 (3, -1)을 전달하게 되면 (3, 0)으로 인식합니다. (3, 0)은 시작 인덱스가 더 크므로 위치를 변환하여 (0, 3)의 값을 계산한 결과를 반환합니다.

    함수명이 비슷한 substr의 경우 ‘위치’와 ‘추출할 문자의 수’를 파라미터로 전달하는 함수입니다.

    const myWord = 'invierno';
    
    myWord.substring(3);     // 'ierno'
    myWord.substring(1,3);   // 'nv'
    
    myWord.substring(3,1);   // 'nv' -> 시작이 종료인덱스보다 크면 자동으로 위치 변경 후 함수를 실행
    
    myWord.substring(3,-1);  // 'inv' -> 음수는 0, 시작인덱스와 종료인덱스는 위치 변경 후 계산
    
    myWord.substring(-4);    // 'invierno' -> 음수는 0, 시작인덱스만 전달하여 0부터 끝까지 계산
    
    myWord.substr(1,3);      // 'nvi' -> 시작인덱스 1부터 문자 3개를 추출
    

    includes 함수는 지정한 문자열의 포함 여부를 확인합니다.

    매개변수로 문자열(필수)과 위치인덱스(옵션)를 전달하며, 반환값은 true 또는 false 입니다.

    문자열 내 지정 문자열 확인은 물론 배열 내 빈 값을 확인하는 용도로도 사용할 수 있습니다.

    const myWord = 'alegria';
    
    myWord.includes('le');       // true
    myWord.includes('i');        // true
    myWord.includes('rio');      // false
    
    const myArray = ['dream','','king'];
    myArray.includes('');       // true   -> myArray[1]이 빈 값이므로 true. 배열 내 빈 값을 찾는 용도
    myArray.includes('dream');  // true   -> myArray[0]의 값과 일치
    myArray.includes('drea');   // false  -> 배열 내 값과 정확하게 일치하는 경우에만 true를 반환
    

    startsWith 함수도 문자열의 포함 여부를 확인하는 함수라고 볼 수 있습니다.

    startsWith와 함께 문자열만 전달하면 0 인덱스부터 시작하여 해당 문자열의 존재 여부를 확인하여 BOOLEAN 값을 반환합니다.

    마찬가지로 endsWith는 끝나는 문자열을 비교합니다.

    const mySentence = 'cafe con leche';
    
    mySentence.startsWith('cafe');     // true
    mySentence.startsWith('fe');       // false
    mySentence.startsWith('fe',2);     // true
    
    mySentence.endsWith('eche');      // true
    

    trim 함수는 문자열 양 끝의 공백을 제거하는 함수입니다.

    문자열 변환 과정이나 실수로 보이지 않는 공백을 삽입하게 되면 문자열 비교 시 겉으로는 동일하지만 결과는

    false를 반환하므로 이 trim 함수를 사용하면 문제를 해결할 수 있습니다.

    문자열 양 끝의 공백, 탭, 줄바꿈 문자(/n)를 제거하며, 문자열 양 끝이 아닌 부분에는 효과가 없습니다.

    const mySentence = '  la casa de papel   ';
    
    mySentence.trim();        // 'la casa de papel'
    
    const mySentence = ' el amor \n';
    
    mySentence.trim();       // 'el amor'

    replace 함수는 문자열에서 변경할 기존문자를 찾아 변경문자로 변경합니다.

    문자열에서 매개변수로 전달한 기존문자가 여러 개 존재하는 경우 첫 번째로 탐색한 문자열만 변경합니다.

    예를 들어, ‘my_name_is_Ron’에서 ‘_’문자를 모두 공백으로 변경하기 위해 replace(‘_’,’ ‘) 함수를 사용해도 결과는 ‘my name_is_Ron’이 반환됩니다.

    따라서 문자열에서 해당하는 문자를 모두 변경하고 싶은 경우에는 정규표현식을 사용하면 됩니다.

    정규표현식 관련 포스트

    const mySentence = 'my name is:Ron';
    
    mySentence.replace(':',' ');        //'my name is Ron'
    
    const mySentence = 'my_name_is_Ron';
    
    mySentence.replace('_',' ');      // 'my name_is_Ron'
    
    //정규표현식 사용해서 모든 문자 변경하기
    mySentence.replace(/_/g, ' ');    // 'my name is Ron'

    indexOf 함수는 전달하는 문자의 위치를 반환합니다.

    이 기능은 원하는 문자열의 앞 또는 뒤에서 문자열을 자를 때 유용하게 사용할 수 있습니다.

    예를 들어, ‘Z001-03’이라는 문자열에서 뒤의 ’03’만 추출하고 싶은 경우 indexOf로 ‘-‘ 문자열의 위치를 찾고 해당 위치의 +1 위치부터 끝까지 문자열을 잘라내면 원하는 값을 가져올 수 있습니다.

    만약 같은 문자가 여러 개 존재하는 경우 첫 번째 문자의 위치를 반환하며, 두 번째 매개변수에 시작 위치를 전달하면 시작 위치부터 검색을 시작합니다(시작 위치를 전달하더라도 반환 값은 전체 문자열에서 몇 번째인지를 전달합니다).

    뒤에서부터 검색을 시작하는 함수는 lastIndexOf이며, 뒤에서부터 첫 번째로 나오는 문자의 위치를 반환합니다(반환 값은 해당 문자가 앞에서부터 몇 번째인지를 반환합니다).

    전달하는 문자가 존재하지 않으면 -1을 반환합니다.

    const mySentence = 'Z001-03';
    
    mySentence.indexOf('-');     // 4
    
    mySentence.substring(mySentence.indexOf('-')+1);    // '03'
    
    mySentence.indexOf('D');    // -1
    
    const mySentence = 'Z001-03-02';
    
    mySentence.indexOf('-');    // 4
    mySentence.indexOf('-', 5);   // 7
    
    mySentence.lastIndexOf('-')   // 7
    

    test 함수는 정규표현식과 함께 사용하여 매개변수로 전달하는 문자열의 유효성을 확인합니다.

    비밀번호에 알파벳, 특수문자 등 포함여부 확인이나 생년월일 형식에 알파벳 등 불필요한 문자의 포함 여부를 효과적으로 확인할 수 있습니다.

    const mySentence = /a/;
    const myWord = 'baby';
    
    mySentence.test(myWord);   // true
    
    /\d/.test('cookie');       // false \d는 숫자(0~9)를 나타내는 정규표현식
    /\d/.test('cookie1');      // true
    
    const typedError = /[ㄱ-ㅎㅏ-ㅣ]/gi;
    const inputData = '김ㅊ치와 나물';
    
    typedError.test(inputData);    // true 

    이 외에도 다양한 함수들이 많고 또 여러 요구에 맞춰 새롭고 편리한 함수가 계속 나오기 때문에 끊임없는 관심과 업데이트 관련하여 모니터링이 필요할 것 같습니다.