[Map Function] 배열의 원소마다 함수를 각각 실행시켜주자

2020. 5. 19. 22:07컴퓨터언어/React JS

728x90
반응형

React는 한 페이지를 구성하는 요소들을 잘게 쪼개어 모듈화하기 때문에, 레고처럼 조립과 분해로 유지보수가 쉬운 장점이 있다.

 

그렇기 때문에, 나의 웹사이트에서 "자주" 쓰이는 디자인을 .jsx로 한데 모아 정의해놓고, props를 이용하여 그때그때 표시되는 정보만 갈아끼우면 정말 최고의 효율성을 가져다준다.

 

여기서 "자주" 쓴다는 것은,

CSS의 .클래스마냥 <나의 커스텀 태그 />를 여기저기서 끌어다쓸 수 있다는 것인데,

한번 생각해보자.

 

우리가 항상 접하는 웹페이지는 게시판 목록이나 피드를 보면 알 수 있듯이, 틀은 다 똑같고 안에 내용만 바뀌는 형태가 압도적으로 많다.

그렇다면 각 글이나 사진이 <Feed /> 같은 형태로 무수히 반복된다는 뜻이다.

 

이 많은 태그들을 일일이 수작업하지 않고, 그 전체 수만큼 알아서 반복문 돌려주는 것이 바로 .map() 함수이다.

 

.map() 함수는 배열 자료형에 붙어서 사용되며, 배열의 모든 원소를 훑으면서 () 안에 내가 부여한 함수를 하나씩 적용해준다.

MongoDB 같은 데이터베이스를 사용하든, 크롤링을 하든, 내가 따로 데이터를 별도 파일에 저장하든, 가장 보편적인 자료구조는 배열이기에 .map() 함수는 우리의 수고를 덜어준다.

 


최상위 루트에 App.jsx가 있고, 페이지를 구성하는 요소로 Heading, Card, Footer가 있다고 가정해보자.

// App.jsx
import React from "react";

import Heading from "./Heading";
import Card from "./Card";
import Footer from "./Footer";

function App () {
  return (
    <div>
      <Heading />
      <Card userId="" email="" img="" />
      <Footer />
    </div>
  )
}

export default App;

여기서 Card 태그는 커스텀 태그로, 회원들의 프로필이 뜬다고 해보자.

그렇다면 각 회원마다 다른 ID, email, 프로필사진을 보여주어야 한다.

 

만약 회원이 1000명이라면, props가 좋은 기능이라고 해도 너무 고달플 것이다.

// App.jsx
import React from "react";

import Heading from "./Heading";
import Card from "./Card";
import Footer from "./Footer";

function App () {
  return (
    <div>
      <Heading />
      <Card userId="" email="" img="" />
      <Card userId="" email="" img="" />
      <Card userId="" email="" img="" />
      <Card userId="" email="" img="" />
      <Card userId="" email="" img="" />
      ........
      ........
      <Footer />
    </div>
  )
}

export default App;

 

하지만 회원정보가 객체가 들어있는 배열이라면, .map() 함수를 이용하면 아래와 같이 쉽게 해결할 수 있다.

// App.jsx
import React from "react";

import Heading from "./Heading";
import Card from "./Card";
import Footer from "./Footer";

import userDatum from "./userdatum";

function createCard(userData) {
  return (
    <Card userId={userData.id} email={userData.email} img={userData.img} />
  );
}

function App () {
  return (
    <div>
      <Heading />
      { userDatum.map(createCard) }
      <Footer />
    </div>
  )
}

export default App;

 

위에서 userDatum은 아래와 같이 데이터베이스(또는 커스텀 파일)에는 모든 회원들의 정보가 모여 [] 배열에 저장되어 있다고 가정한 것이다.

배열 안에는 각 회원마다 id, email, img 정보를 가지고 있고, 이 정보들이 {} 객체로 묶여 있다.

// userdatum.js

const userDatum = [
  {
    id: "qwerty123",
    email: "qwerty@abc.com",
    img: "www.img.com/123"
  },
  {
    id: "asd456",
    email: "asd@email.com",
    img: "www.img.com/789"
  },
  {
    id: "football2020",
    email: "fb20@fc.com",
    img: "www.img.com/990"
  },
];

export default userDatum;

 


거의 다 왔다! 하지만 추가할 것이 하나 더 있다.

React는 항상 DOM 트리를 주시하면서 "변화가 있는" 부분만을 렌더링한다.

그런데 우리가 .map() 함수를 사용하면, 배열 내 모든 원소를 훑고 지나가면서 props에 데이터까지 계속 대입해나가게 되고, 이 과정이야말로 DOM에 무지막지한 "변화"를 만들어버리는 것이다.

이때 React는 .map()으로 새로 생겨나는 수많은 태그들(그리고 그 안의 하위 내용들)에 휘둘리지 않고 이들을 잘 관리하기 위해, 그 하위 내용 중 변하지 않으면서 중복되지 않는 key를 요구한다.

*key 속성은 해당 .map()에서 태어난 태그에서만 사용되기로 약속된 속성 키워드로, 우리가 커스텀으로 지정하는 prop처럼 하위 태그에서 사용할 수 없다.

 

따라서 위의 <Card /> 태그 안에 key 속성을 추가해주면 된다.

key 값은 데이터베이스 내에 들어있는 _id를 사용하든지 아니면 .map()함수에 인덱스를 포함시키든지 방법은 여러가지 있지만, 가장 좋은 것은 애초에 각 회원정보마다 id값도 함께 부여해주는 것이다.


이처럼 .map() 함수를 이용하면 그 배열을 구성하는 객체들의 각 property에 .(dot)으로 쉽게 접근할 수 있고, 이를 props과 융합하면 더 확장성이 좋은 코드를 만들어낼 수 있다.

728x90
반응형