Coding (164)

01
15

우리의 프로젝트도 빙글빙글 돌려 봅시다.

1. 문제의 발단

포트폴리오를 역시나 만들고 있는 중에, 프로젝트나 설명 부분에 옆으로 넘어가는 디자인을 만들면 가독성도 좋고 디자인도 뛰어 날 것이라고 생각했다. '라이브러리를 사용하자!'라는 생각은 있었다만, 아직 익숙하지 않은 타입 스크립트와 생각보다 css를 적용하는 부분이 헷갈렸다. 그래서 복습하고자 이 글을 작성하고 있다.

2. Carousel VS Slider

이 친구는 이미지 슬라이드가 아닙니다. 케러솔 입니다.
얘가 슬라이더 입니다.

  • 구글링을 하다가 알게 된 사실이다. 생각해 보니 슬라이더는 저렇게 음량등을 조절할 때 사용하는 것이었다!
  • 저렇게 사진이나 내용들이 넘어가는 것은 'Carousel'이다. 한국말로는 회전목마.  

2. 사전 작업은 어떻게 합니까?

  • 우리가 install 해야 할 것은 총 3개
  • npm install --save @types/react-slick
  • npm install --save react-slick 
  • npm install --save slick-carousel
  • 위의 3가지를 모두 install 해야 한다. 그래야 올바르고 쉽고 간편하게 기능하게 만들 수 있다.
  • 그리고 사용할 tsx 파일위에 또 3가지 내용을 import 한다.
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
  • css 파일을 따로 불러줘야 한다. 아니면 옆으로 넘길 수 있는 화살표나 지금 어떤 내용을 보고 있는지를 표시하는 점(Dots)이 안 나온다.

3. 일단 코드 쳐 보기

import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";

function Carousel() {
	const settings = {
    	dots: true,
        infinite: true,
        speed: 500,
        slidesToShow: 1,
        slidesToScroll: 1,
    }
    // 사용할 Carousel의 기본 세팅을 해준다. props로 받아 와야 하기 때문에 객체에 넣어서 받아온다.
    // 더 많은 설정이 있지만, 그것은 직접 코드를 뜯어 보면 쉽게 알 수 있다.
    // 위의 설정은 홈페이지에 나와있는 기본 설정을 한번에 보여줄 갯수만 1개로 바꾼 것이다.
    
    <section className="page-carousel">
    	<Slider {...settings}>
        	<div>거창한 내용</div>
            <div>대단한 내용</div>
            <div>멋있는 내용</div>
            <div>예쁜 내용</div>
            <div>무언가 엄청난 내용</div>
        </Slider>
    </section>
}

export default Carousel;
  • 이렇게 하면 기본적인 케러솔을 볼 수 있다. 위의 예시 그림과 비슷하게 만들어질 것이다. 기본적인 css는 적용되어 있고, 기능 또한 적용되어 있다.

4. 커스텀하기

  • 이대로 쓰면 모두가 똑같은 디자인과 UI를 가지게 될 수 있으므로, 조금 바꿔본다.

화살표 커스텀

  • 화살표는 이미지 혹은 아이콘 뭐든지 가능하다. 아에 컴포넌트로 만들어 넣을 수 있다.
  • 그러므로 tsx 파일인 NextArrow.tsx 파일을 만들었다.
import React from "react";

interface NextArrowProps {
    onClick?: React.MouseEventHandler<HTMLDivElement>;
}
// 타입스크립트를 사용하기 때문에 onClick 이벤트를 props로 받아준다.
// className을 받아줄 수 도 있다. 그리고 부모 컴포넌트에서 설정해 줘도 된다.

export default function NextArrow({ onClick }: NextArrowProps) {
    return <div className="next-arrow" onClick={onClick}>누르면 넘어감</div>;
}
  • html 태그를 img로 바꿔서 이미지를 넣을 수 도 있다. css를 설정하면 마음대로 사용할 수 있다.
  • 하지만 css가 조금 곤란하다. 원래 있던 slick 자체 테마에 있던 위치 설정을 해놓은 css들을 일단 모두 써 놓고, 이후에 조금씩 바꿔 가는 방향으로 작업해야 원하는 위치에 화살표를 위치시킬 수 있다.
.next-arrow {
    right: -25px;
    font-size: 20px;
    line-height: 0;
    position: absolute;
    top: 50%;
    display: block;
    width: 20px;
    height: 20px;
    padding: 0;
    transform: translate(0, -50%);
    cursor: pointer;
    color: transparent;
    border: none;
    outline: none;
    background: transparent;
    transition: 200ms ease-in-out;

    &:before {
        line-height: 1;
        opacity: 0.75;
        -webkit-font-smoothing: antialiased;
    }
}
  • 위의 코드가 거의 기본 코드일 것이다(조금 다를 수 있다. 뭔가 이상하다면 크롬 개발자 도구를 이용해 원래 태마에서 화살표의 css를 그대로 복사해서 붙여 넣고 작업하면 된다). 태그와 설정들을 마친 후에 css 작업할 때 붙여놓고 보면서 원하는 위치를 잡는다.
  • 그리고 부모 컴포넌트인 Carousel로 다시가서 세팅을 바꿔준다.
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import NextArrow from "../components/NextArrow";

function Carousel() {
	const settings {
    	dots: true,
        infinite: true,
        speed: 500,
        slidesToShow: 1,
        slidesToScroll: 1,
        nextArrow: <NextArrow />
    }
    // nextArrow에 불러온 <NextArrow />를 설정해 준다. 그러면 바뀐 화살표를 볼 수 있다.
    
    <section className="page-carousel">
    	<Slider {...settings}>
        	<div>거창한 내용</div>
            <div>대단한 내용</div>
            <div>멋있는 내용</div>
            <div>예쁜 내용</div>
            <div>무언가 엄청난 내용</div>
        </Slider>
    </section>
}

export default Carousel;

Dots 커스텀

  • dots는 className을 다르게 설정해서 적용할 수 있다. 화살표처럼은 컴포넌트 자체로는 안 되는 것 같다.
  • 하지만 css는 화살표와 마찬가지로 기본 설정을 똑같이 뺏겨와서 설정한 후에 조절해야 한다.
  • 일단, 부모 컴포넌트인 Carousel.tsx를 설정한다.
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import NextArrow from "../components/NextArrow";

function Carousel() {
	const settings {
    	dots: true,
        infinite: true,
        speed: 500,
        slidesToShow: 1,
        slidesToScroll: 1,
        nextArrow: <NextArrow />,
        dotsClass: "custom-dots"
    }
    // dotsClass에 클레스를 설정해 준다. 그러면 바뀐 Dots를 볼 수 있다.
    
    <section className="page-carousel">
    	<Slider {...settings}>
        	<div>거창한 내용</div>
            <div>대단한 내용</div>
            <div>멋있는 내용</div>
            <div>예쁜 내용</div>
            <div>무언가 엄청난 내용</div>
        </Slider>
    </section>
}

export default Carousel;
  • 그리고 css를 바꾸자.
.custom-dots {
    position: absolute;
    bottom: -15px;
    display: block;
    width: 100%;
    padding: 0;
    margin: 0;
    list-style: none;
    text-align: center;
}

.custom-dots li {
    position: relative;
    display: inline-block;
    width: 40px;
    height: 20px;
    margin: 0 5px;
    padding: 0;
    cursor: pointer;
}

.custom-dots li button {
    font-size: 0;
    line-height: 0;
    display: block;
    width: 40px;
    height: 20px;
    padding: 5px;
    cursor: pointer;
    color: transparent;
    border: 0;
    outline: none;
    background: transparent;
}

.custom-dots li button:before {
    font-family: "slick";
    font-size: 2rem;
    line-height: 20px;
    position: absolute;
    top: 10px;
    left: 20px;
    width: 20px;
    height: 20px;
    content: "*";
    text-align: center;
    opacity: 0.9;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.custom-dots li.slick-active button:before {
    opacity: 1;
    color: #ffffff;
    content: "*";
}
  • 이것이 원래 dots의 css일 것이다. (근데, 진짜 확실하지 않다. 이미 너무 많은 것을 바꿔버렸다. 개발자 도구를 이용해 꼭 기본 css 세팅이 된 내용을 복사해서 가지고 와서 붙여놓고 바꿔보자)
  • 여기까지 하면 바뀐 내용들을 볼 수 있을 것이다.
COMMENT
 
01
14

아니, 안돼, 돌아가. 안 바꿔줘

1. 문제의 발단

매일 포트폴리오를 만들고 있다가 메뉴 토글을 만드려고 오픈 핸들러 함수를 자식 컴포넌트로 내리려고 하는 순간, 영문모를 에러들을 만났다. 여러 번 프로젝트를 만들면서 매번 하던 작업이라 실수한 줄 알았지만 아무리 봐도 틀린 건 없고... 에러 메시지를 보니 타입 스크립트가 뭔가 이상하다고 알려주는 것 같아서 구글링 하고 찾아본 결과 답을 찾을 수 있었다.

2. 무엇이 문제인가요?

  • 가장 중요한 포인트는 'props를 받는 자식 컴포넌트가 부모에게 받을 props의 형태를 결정 할 수 있다'는 것이다!
  • 그래서 더 정확한 데이터 만을 넘겨 줄 수  있다.

3. 어떻게 사용할까요?

  • 일단 원래 하듯이 props를 내려주는 부모부터 살펴본다. 상위에서 Menu 컴포넌트로 헨들러 함수를 내려 줄 것이다.
// 먼저 useState를 이용해 상태를 만들고 블리언 타입으로 설정한 후 초기값을 주었다. react와 조금 다르지만,
// 그리 복잡하지 않고 타입을 생략해도 작동하는 것은 문제없다.
const [isOpenMenu, setIsOpenMenu] = useState<boolean>(false);
const openMenuHandler = () => {
        setIsOpenMenu(!isOpenMenu);
};

// react에서 하듯이 이렇게 넘겨준다. 넘겨만 주면 에러가 날 것이다. 받는 쪽을 보자.
return (
	<div>
    	<Menu openMenuHandler={openMenuHandler}/>
	</div>
)
  • 이제 진짜 본론인 어떻게 받는가? 이다.
// React 지우면 안된다. 바벨을 만약 쓴다면 필요하다고 한다.
// FC로 function component를 사용 할 수 있게 만든다.
import React, { FC } from "react";

// interface를 이용해 받을 props의 타입을 결정해준다.
interface Props {
	openMenuHandler(): void;
}

// 나머지는 같다.
const Menu: FC<Props> = ({ openMenuHandler }) => {
	return (
    	<div>
        	<div onClick={() => openMenuHandler()}>Open</div>
        </div>
    )
}

export default Menu;
  • 이렇게 받는 쪽에서 타입을 정해줘야 받을 수 있다. 다른 데이터 타입도 같다.

4. 추가로 알아보는 type

  • 그렇다면, 다른 타입은 어떻게 정해줘야 할까?
  • 일단 any로 설정하고 props를 내려본다. 그러면 마우스를 대보면 정확한 타입이 뜨고, 이후 그 타입으로 바꿔주면 된다.
  • 사용할 수 있는 타입에는 우리가 기본적으로 쓰는 타입들(ex: Number, Boolean 등)이 있고
  • return 값이 없는 위의 예시와 같은 함수들은 void이다.
COMMENT
 
01
13

animation: 오타를 찾는 흔들리는 나의 눈빛 1s ease-in-out infinite

1. 문제의 발단

CSS로도 라이브러리를 쓰지 않더라도 간단하게 애니메이션을 표현할 수 있다. flex-box를 어느 정도 사용하게 되고 나니, 이제 자연스럽게 애니메이션을 이용해 css를 활용해보려는 욕심이 났다. 그래서 움직임과 관련한 속성들을 전부 정리해 보려고 한다.

2. transform

  • 위치 값이나 크기 등을 변환시킬 수 있다.
  • scale(크기), skew(기울어짐), rotate(회전), translate(위치 이동), perspective(3D), matrix(perspective를 제외하고 앞의 모든 속성을 다 적용시킴)의 속성들을 사용할 수 있다.
  • 각 속성들은 단위와 함께 적어서 변화를 줄 수 있다. 그리고 속성 뒤에 X, Y를 붙이면 축에 따른 변화도 가능하다.

3.  transition

  • 얼마나 오랜 시간 동안 애니메이션을 재생시킬 것인가를 정한다.
  • 그래서 뒤에 시간이 온다. (ex: 2s, 2000ms 등 )
  • ease(기본값, 천천히 시작해서 빨라졌다가 다시 느리게 끝), ease-in(시작이 느림), ease-out(끝이 느림), ease-in-out(느리게 시작해서 느리게 끝), linear(전부 동일한 속도)의 속성들도 사용할 수 있다. 이후 시간 단위도 붙여도 된다. 그 시간 안에서 지정한 방식의 속도를 가진다.

4. @keyframes

  • 애니메이션을 새부적으로 시간의 지남에 따라 만들어 줄 수 있다.
.box{
	animation: Ghost 1s ease-all infinite;
    // 설정한 애니메이션을 animation 속성으로 적용시킨다.
}

@keyframes Ghost {
    0% {
        opacity: 0;
    }
    30% {
        opacity: 1;
    }
    60% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}
  • 위의 속성을 넣으면 처음 시작할 때에는 안 보이며, 30% 진행 후 생겼다가 60%만큼까지 유지되면서 마지막에는 다시 천천히 사라지게 될 것이다.
기준이 되는 선이 어디인지 혹은, 부드러운 움직임 등을 구현해 직접 사용하는 것이 가장 빠른 적응 방법이다. 코드만 봐서는 잘 모른다. 스크롤 유도 아이콘이나 BOX를 이용한 움직임으로 연습하면 될 것 같다.
COMMENT
 
01
12

그래서 우리는 큰 초 하나에 10살로 치고 생일 파티를 하기도 하죠. 이것도 UX를 위한겁니다!

1. 정보 구조?

  • '프레임워크'라고 할 수 있다. 사용자가 디자인적인 측면이 아니라 사용에 편리하도록 보여줄 정보들의 위치 등을 정하는 것이다.
  • 사용자의 니즈를 파악하고 쉽고 편하게 누구나 이해할 수 있는 용어를 사용하며, 진행의 플로우를 잘 제공한다. 마치 상품을 판매하는 사람이 상품을 매력적으로 소개하는 것 과 같다.
  • 이때, 우리는 유저가 어떻게 이 서비스를 사용할까? 를 회원가입부터 회원 탈퇴까지 모든 과정을 유저의 입장에서 생각하면서 만들게 된다.

2. 접근법

  • 유저에게 어떤 정보를 어떤 부분에서 보여줘야 더 편하게 서비스를 이용할 수 있을까를 고민한다.
  • 정렬하는 방식이나 시점, 분류방식 등을 이용 할 수 있다.
  • 디자인 레이어 
    표현층(presentation layer) : UI  디자인, 편집 디자인, 특정 컴포넌트
    기능, 인풋과 아웃풋 : 인터랙션 디자인, UI 패턴
    데어터와 내용 : 정보 설계, 내비게이션 패턴
  • 이처럼, 보이는 부분과 데이터를 보여주는 부분을 나눠서 생각한다. 가장 아래에 있는 레이어가 가장 중요한 부분을 차지하고, 아래를 탄탄히 쌓아서 올려나가야 한다.

3. 콘텐츠를 분류하는 법

  • 정보를 필터링하거나 검색결과등을 보여줄 때 데이터를 분류하는 기준으로 쓸만한 것 들이다.
  1. 위치(Location)
    • 국가, 도시 등의 지리적 위치를 이용한다.
    • 사용자에게 자신의 위치를 알려줘야 한다.
  2. 가나다순(Alphabetical)
    • 매우 보편적인 정렬.
    • 어디든지 사용할 수 있어서 편하고 보기 좋다.
  3. 시간(Time)
    • SNS의 피드 등이 해당한다. 가장 최근에 생성된 피드가 가장 최상단으로 올라오게 된다.
    • 이처럼 오름차순, 내림차순으로 정렬이 가능하다.
  4. 카테고리(Category) or 필터(Facet)
    • 콘텐츠를 주제별로 묶은 카테고리를 만들어 이용할 수 있다.
    • 같은 주제로 묶인 항목들이기 때문에 정보를 더 깔끔하게 찾아볼 수 있다.
  5. 위계(Hierarchy)
    • 큰 범주가 그 아래 더 작은 범주를 포함하고 있을 경우 이용할 수 있다.
    • 예를 들어, '아시아의 국가'로 선택하면, '한국', '일본', '중국'등으로 나타낼 수 있다.
    • 따로 주제의 한계는 없다. 어떤 범주가 되었든, 큰 범주가 더 작은 범주를 포함하고 있다면 모두 사용할 수 있다.
  6. 숫자(Number)
    • 가나다순과 비슷하게 숫자로 이루어진 목록이 있을 때 사용 가능하다.
    • 숫자로 이루어져 있으며, 의미가 있는 숫자 데이터의 경우 사용하면 사용하기 가장 편하다.
COMMENT