10-1. PostList 생성 및 Masonry 테스팅

디자인 구상

이번 섹션에서는 본격적으로 포스트 카드를 디자인 하기전에, Masonry 레이아웃을 테스팅을 해보도록 하겠습니다.

우선, react-masonry-component 를 설치합니다.

그 다음엔, 포스트 카드의 틀을 만들겠습니다.

masonry 를 사용할때는, 사이즈 조정이 중요한데요, 각 화면에서 어떻게 보여줄 지 먼저 알아보겠습니다.

  • 데스크탑: 한 줄에 3개를 보여줌
  • 태블릿: 한 줄에 2개를 보여줌
  • 모바일: 한 줄에 1개를 보여줌

그리고, 각 카드끼리는 16px 의 여백이 있습니다. 여백의 경우엔 상하 여백은 margin-bottom 으로 설정하며, 좌우 여백은 masonry 에서 gutter 라는 값으로 설정을 해줍니다.

데스크탑일때는,

[] [] []

이런식으로 카드와 카드 사이 여백이 두번 들어가게 되기 때문에 전체 너비에서 (16px * 2) 를 뺸 다음에 3으로 나눈 값: width: calc((100% - 32px) / 3); 이 너비가 되며,

태블릿의 경우엔,

[] []

이와 같이 카드와 카드 사이 여백이 한번 있으므로 전체 너비에서 16px 를 빼고 2로 나눈 값인 width: calc((100% - 16px) / 2); 가 너비가 됩니다.

마지막으로 모바일의 경우엔 한 줄에 하나만 보여주기 때문에 100% 로 하면 됩니다.

Post 컴포넌트 만들기

그러면, 위의 정보에 따라서 카드 사이즈를 설정하여 컴포넌트를 생성해보겠습니다.

우리가 앞으로 만들 PostList, 그리고 이와 관련된 컴포넌트는 components/Shared 디렉토리에 저장하도록 하겠습니다. 그 이유는, 홈에서도 사용이 되고, 유저 페이지에서도 사용이 되기 때문입니다.

src/components/Shared/PostList/Post.js

import React from 'react';
import styled from 'styled-components';
import oc from 'open-color';
import PropTypes from 'prop-types';

import { media, shadow } from 'lib/styleUtils';

const Wrapper = styled.div`
    width: calc((100% - 32px) / 3);
    ${media.desktop`
        width: calc((100% - 16px) / 2);
    `}
    ${media.tablet`
        width: 100%;
    `}
    height: 400px;
    margin-bottom: 1rem;
    background: white;
    ${shadow(1)}
`;

const Post = () => (
    <Wrapper>

    </Wrapper>
);

export default Post;

포스트의 내용은 일단 비워두고 나중에 구현하도록 하겠습니다.

PostList 컴포넌트 만들기

이제 여러개의 Post 를 감싸줄 PostList 를 만들겠습니다. 이 컴포넌트에서는 position: relative 속성을 주는것이 중요합니다. 그 이유는 Post 컴포넌트의 사이즈가 이 컴포넌트의 너비와 비례하여 만들어지기 때문입니다.

PostList 내부에서, Masonry 컴포넌트를 불러와서 사용을 하게 되는데, 이 때 optionsgutter 값을 설정하여 좌우 여백을 설정합니다.

그리고, 해당 컴포넌트의 자식 컴포넌트들로 정렬할 컴포넌트인 Post 컴포넌트를 여러개 렌더링을 해주면 Masonry 가 레이아웃을 처리해줍니다.

일단은, 아직 데이터를 불러오지 않았기 때문에, 여러개의 <Post/> 를 하드코딩하여 작성하도록 하겠습니다.

src/components/Shared/PostList/PostList.js

import React from 'react';
import styled from 'styled-components';
import Masonry from 'react-masonry-component';
import Post from './Post';

const Wrapper = styled.div`
    position: relative;
    margin-top: 1rem;
`;

const PostList = () => (
    <Wrapper>
        <Masonry options={{gutter: 16}}>
            <Post/>
            <Post/>
            <Post/>
            <Post/>
            <Post/>
            <Post/>
            <Post/>
            <Post/>
            <Post/>
            <Post/>
            <Post/>
        </Masonry>
    </Wrapper>
);

export default PostList;

이 다음엔 PostList 컴포넌트를 기본으로 내보내주는 인덱스파일을 작성합니다.

src/components/Shared/PostList/index.js

export { default } from './PostList';

이제 PostListContainer 컴포넌트를 생성해서 PostList 를 렌더링하고, 해당 컴포넌트를 Home 에서 보여주겠습니다.

src/containers/Shared/PostList/PostListContainer.js

import React, { Component } from 'react';
import PostList from 'components/Shared/PostList';

class PostListContainer extends Component {
    render() {
        return (
            <PostList/>
        );
    }
}

export default PostListContainer;

이 파일도 인덱스를 만들어줍니다.

src/components/Shared/PostList/index.js

export { default as PostListContainer } from './PostListContainer';

src/pages/Home.js

import React, { Component } from 'react';
import PageWrapper from 'components/Base/PageWrapper';
import { WritePostContainer } from 'containers/Home';
import { PostListContainer } from 'containers/Shared/PostList';

class Home extends Component {
    render() {
        return (
            <PageWrapper>
                <WritePostContainer/>
                <PostListContainer/>
            </PageWrapper>
        );
    }
}

export default Home;

이렇게 PostList 를 보여주었을때 다음과 같이 나타나면 정상입니다:

이 때 문제점이 한가지 발생하는데, 헤더에 z-index 값을 주지 않아서 카드가 헤더를 가리는 현상이 나타나게 됩니다. 헤더의 Positioner 부분에 z-index 값을 설정하세요.

src/components/Base/Header/Heaader.js - Positioner

const Positioner = styled.div`
    display: flex;
    flex-direction: column;
    position: fixed;
    width: 100%;
    top: 0px;
    ${shadow(1)}
    z-index: 20;
`;

results matching ""

    No results matching ""