전체 글 (165)

06
10

- 예시

_.chunk(['a', 'b', 'c', 'd'], 2);
// => [['a', 'b'], ['c', 'd']]
 
_.chunk(['a', 'b', 'c', 'd'], 3);
// => [['a', 'b', 'c'], ['d']]

_.chunk(['a', 'b', 'c', 'd', 'e', 'f'], 2);
// => [['a', 'b'], ['c', 'd'], ['e', 'f']]

_.chunk(['a', 'b', 'c', 'd', 'e', 'f', 'g'], 3);
// =>  [['a', 'b', 'c'], ['d', 'e', 'f'], ['g']]

- 구현

const chunk = (arr, size) => {
  const result = [];
  
  // arr 원본을 수정하지 않기 위해, slice로 복사한다.
  const copyArr = arr.slice();

  // 배열을 돌면서,
  copyArr.map(() => {
    // splice로 size만큼 원본 배열을 빼면서,
    const temp = copyArr.splice(0, size)
    // 임시로 만든 result배열로 넣어서 이중배열 구조를 만든다.
    result.push(temp)
  })
  
  // splice로 배열을 빼버리면서 map으로 탐색 하고 있으므로, 
  // copyArr를 전부 돌고 나서, 남은 요소들을을 result와 합쳐서 return한다.
  return result.concat([copyArr]);
}

- 소감

  • 오랜만이니까 제일 앞에 거 해야지 하다가 혈압 올라서 요단강 래프팅 투어 갈 뻔했다. 무시하지 말자...
  • 생각보다 어렵다... 마지막 남은 것 처리는 어떻게 하지? 혹은, reduce로 한 번에 처리할 순 없을까?, 제귀로 처리할까? 와 같은 별거 아닌 고민들로 시간을 많이 날렸다.
  • 습관적으로 알고리즘을 보면 제귀함수부터 쓰려고 한다. 효율적인 방법도 아니고, 코드 가독성도 그리 좋지 못하니 배열을 순회하는 함수를 조금 더 사용하면 좋을 것 같다.
  • slice로 배열을 카피해서 사용하는 것이 아무래도 조금 불편하다. reduce로 한 번에 처리하고 싶다...!
COMMENT
 
06
10

무엇을 상상하든 그 이상을 보게되는 Javascript

1. lodash?

  • 데이터 처리를 위해 다양한 함수를 가지고 있는 라이브러리이다.
  • 배열을 반복시키거나, 객체 형태의 데이터를 정렬하거나 하는 등의 작업을 쉽게 할 수 있다.

2. 예시

예시1 : gropBy(array | object, 규칙)

groupBy([6.1, 4.2, 6.3], Math.floor);
// => { '4': [4.2], '6': [6.1, 6.3] }
 
groupBy(['one', 'two', 'three'], 'length');
// => { '3': ['one', 'two'], '5': ['three'] }

예시 2 : join(array, '사이에 넣어줄 string')

join(['a', 'b', 'c'], '~');
// => 'a~b~c'
  • 이와 같은 다양한 함수들이 존재한다. 그래서 처리하기 괴로운 데이터 형태로 백엔드에서 넘겨받는다고 하더라도 찰떡같이 잘 바꿔 사용하면 된다.

3. 단점

  • 용량이 커서 사용하지 않는 경우가 있다고 한다...! (친구 개발자 프로젝트에서는 사용할 때 그런 이슈가 있었다고 하는데, 잘 모르겠다. 함수 덩어리들이 용량이 커봐야 그리 크지 않을 것 같다.)
  • 나중에 알고리즘 문제 풀때 답답하다. 데이터를 받으면 lodash 함수부터 생각난다. (요즘에는 면접 때도 Ai 한테 물어보고 하는 경우도 있다고 하니 뭐 비슷한 경우가 아닐까? 오히려 이쪽이 더 낫지 않나...? 하는 개인적인 생각)

4. 그래서 어떻게 사용할 것인가?

  • 물론 프로젝트에서는 이렇게 저렇게 잘 사용하면 된다. 하지만...?
직접 lodash 함수를 구현해 본다면...?
  • 실무에서 쓰기 좋은 함수들의 모음 -> 만약, 실무에서 쓰지 못 하는 프로젝트를 만난다면? -> 직접 구현!
  • 실무에서 적용시키기 어렵고 복잡한 알고리즘 문제들보다 더 활용도가 높을 것이다!라는 결론이다.

5. 연습하는 법

  1. https://lodash.com/docs 로 접속한다.
  2. 스크롤을 랜덤으로 쭉 내린다 (순서대로 하는 것은 추천하지 않는다. 데이터 형태별로 순차로 적혀있어서 배열과 객체를 섞어서 하는 게 더 헷갈리고 도움이 된다.)
  3. 아무 함수나 찝고 함수를 하나 만들고, 예시와 똑같이 동작하도록 만든다.
  4. 시간이 남거나 기회가 된다면 실무처럼 똑같은 환경이라고 생각하고 만든다. 예를 들어, for 문을 사용하지 않는다거나, map을 reduce로 바꾸어 최적화시킨다거나, if문이 중첩 될 경우 삼항연산자로 바꾼다거나 하는 등으로 말이다.
COMMENT
 
06
06

전형적인 릴리즈 15분 27초 전 모습.jpge

1. 왜 필요한가?

  • 눈으로 다 확인할 수 있는 프론트 기능들이지만, 모든 부분을 완벽하게 테스트하기는 쉽지 않다.
  • 그렇게 모든 상황을 다 테스트 하더라도, 시간이 너무 오래 걸린다.
  • 프로젝트의 사이즈가 커지면 커질수록, 협업을 하게 되는데, 동료 개발자가 작업했던 부분을 작업하게 되는 경우가 종종 생긴다. 이때, 의도되지 않은 버그가 있다면 그대로 배포될지도 모른다. 이때, 테스트를 통해 검사할 수 있다. => 실무에서는 이전버전에서 이미 배포된 기능의 코드를 이번 버전에서 고칠 경우가 생기는데 이미 이전 버전에서 Qa가 끝난 부분이기 때문에 자세히 보지 않는 경우가 있다. 이럴 경우 치명적인 버그가 배포될 경우가 생기기 쉽다.
  • 가장 중요한 것은, 릴리즈 당일, 팀원들과 가족 같은 분위기를 형성하게 될 수 있는 상황을 미연에 방지한다.

2. 유닛 테스트

  • 작은 단위(컴포넌트 정도)의 기능동작을 확인하는 테스트
    • 컴포넌트가 잘 렌더링 되는가?
    • 함수는 올바르게 동작하는가?
    • state를 올바르게 사용하고, 올바르게 setState 하는가?

3. 통합 테스트

  • 프로젝트가 전체적으로 올바르게 동작하는지를 확인하는 테스트
    • 수많은 컴포넌트들이 서로 잘 동작하며 각각의 역할을 올바르게 하여 정상적으로 동작하는가?
    • DOM 이벤트가 올바르게 화면을 변화시켜 주는가?

4. Jest

자바스크립트 코드 테스트 자동화 Tool 중 대표적인 Jest

  • 가장 단순한 테스트 툴, 기본적인 설정을 해 줄 필요가 없어서 간단하다.
  • 스냅샷 기능을 지원하여, 오브젝트가 변경되면 에러를 보여줄 수 있다. -> 렌더링 된 컴포넌트의 변경도 체크할 수 있다.
  • 테스트 코드는 작업물과 완전히 분리되어 있다.
  • API도 -coverage 옵션을 사용해 커버리지를 확인할 수 있도록 되어 있어, 매우 단순하다.

5. 실전 테스트

  • 먼저 프로젝트를 생성한다. (cra을 해도 테스트해 보기는 괜찮다! 다 깔려있다! 만약, yarn init 했다면 babel도 설치해 주자 yarn add --dev babel-jest @babel/core @babel/preset-env)
  • 생성한 프로젝트에 yarn add -D jest
  • package.json에 script에 test 명령어를 넣어준다.
{
  "name": "jest-test",
  "version": "1.0.0",
  "main": "index.ts",
  "license": "MIT",
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "jest": "^29.5.0"
  }
}
  • index.js에 함수를 만들어 준다. 나는 NaN을 판별해 주는 함수를 만들 것이다.
export const checkNaN = (value) => {
  return !Object.is(value, NaN) ? "참" : "거짓";
};
  • 그리고, index.test.js파일을 test 폴더에 만들어서, jest가 검사할 수 있도록 한다.
  • 그리고 몇 가지 검사를 한다. 방법은 test('로그', 콜백함수)의 형태로 작성한다. 아래는 예시이다.
import { checkNaN } from "../index";

test("1번 : 1은 NaN이 아니다!", () => expect(checkNaN(1)).toBe("참"));
test("2번 : 3 + 6은 NaN이 아니다!", () => expect(checkNaN(3 + 6)).toBe("참"));
test("4번 : 10 / abc은 NaN이 아니다!", () => expect(checkNaN(10 / "abc")).toBe("거짓"));
  • 결과를 보기 위해 yarn test를 입력하면?

야호! 100점

6. toBe

  • 위에서 사용한 toBe 함수는 완전히 같은 요소인지를 검사한다.
  • Object일 경우 같은 메모리 참조가 아니기 때문에 toBe로 검사할 수 없다.
  • 비슷한 toBe시리즈 함수로는 toBeTruthy, toBeFalsy, toBeNull이 있다. 사용법은 똑같으니 생략

7. toEqual

  • Object형태까지 구분이 가능하다.
const getFriend = (name, age) => {
  return {
    name,
    age,
  };
};

test("내 친구의 이름은 hendrix, 나이는 20이야.", () => expect(getFriend("hendrix", 20)).toBe({ name: "hendrix", age: 20 }));
  • 간단하게 친구 정보를 불러오는 함수이다.

땡! 심지어 deep equality하게 검사해야 통과한다고, toStrictEqual을 사용하란다. 친절 그잡채

test("내 친구의 이름은 hendrix, 나이는 20이야.", () => expect(getFriend("hendrix", 20)).toStrictEqual({ name: "hendrix", age: 20 }));

코드를 수정한 이후 성공!

  • 여기서 toEqual과 toStrictEqual의 차이는 toStrictEqual가 더 엄격하게 undefined도 허용하지 않는 함수이다. 

8. 여담

  • 부트캠프를 진행하면서 보았던 문제 형식의 스프린트는 이런 식으로 만드는 구나를 깨달았다. (그럼 계산을 위한 코드도 어딘가에 공식처럼 적혀 있다는 것인데... 그거 뜯어보면 전부 간단하게 해결할 수 있다는 것인데... 그걸 찾는다면 이미 개발 실력이 늘어날 듯하다)
  • 한 발자국 더 나아가면, 저런 테스트 코드를 캡슐화하여 잘 숨겨놓고, 더 어렵게, 그리고 더 엄격하게 검사하는 코드도 넣으면 참 좋은 스프린트를 만들 수 있지 않을까?라는 생각도 들지만 이미 부트캠프를 나온 지 1년 6개월은 넘어서 의미가 없다 흑흑,
  • 실무에서는 테스트 코드를 작성할 수 있을까?라고 한다면 스타트업의 경우 거의 불가능... 하지 않을까 싶다. 규모가 그리 크지 않고, 프론트 개발팀 구성원이 몇 명 없는 경우, 항상 개발시간에 쫓겨가다 보면, 데드라인 맞추기도 급급해서 테스트 코드까지 작성할 시간이 항상 부족하다. 조금만 여유가 있다면, 오히려 Qa 시간도 줄이고, 탄탄한 코드로 이후 유지보수가 뛰어나다는 생각을 운영진도 해 줬으면...!이라고 생각만 하고 있다 흑흑.
  • 하지만 짬날 때마다 테스트 코드를 작성해 놓으면 충분히 도움이 될 것이다. 지금 업무로 진행하는 프로젝트의 특성(기획이 한 번에 픽스되어 나오지 않고, 조금씩 쌓이고 쌓이고 하는 구조) 덕분에 같은 작업자들끼리 기능적으로 꼬이는 부분이 있었는데, 테스트 코드가 있다면 충분히 커버될 것이라고 생각했다.
COMMENT
 
05
31

이제 없이 코딩하라고 하면 마치 왼손만 쓰면서 밥을 먹는것 같은 느낌이 듭니다. 그만큼 강합니다.

1. tailwind css?

  • https://tailwindcss.com/
  • 기가 막힌 css-in-js를 가능하게 하는 라이브러리이다.
  • bootstrap과 비슷하게 미리 정해진 속성을 className안에 부여해서 css파일을 따로 두지 않아도 인라인으로 코드를 짤 수 있다.
  • 일반적인 css와 쓰는 방법이 조금 다르지만, 빠르게 적응할 수 있고 다양한 설정도 가능해 매우 편하다. 
	.container {
		height: 16px;
        width: 16px;
        border: 1px solid;
        border-radius: 16px
	}
  • css로 작성하면 이렇게 되지만,
<div className='w-4 h-4 border-1 rounded-2xl'/>
  • tailwind는 이렇게 한 줄이 끝이다.

2. 장점 (feat. 왜 나는 환장하는가?)

  • tsx파일과 css파일을 오고 가고 할 필요 없이 한 번에 적어서 시간절약에 탁월하다.
export const box = `flex flex-col items-center w-6 h-6 border-1 border-white bg-red-200`

<div>
	<span className={box}>안녕</span>
    <span className={box}>잘가</span>
</div>
  • className을 고민하지 않아도 된다. 반복해서 사용해야 하는 스타일 일 경우 string으로 스타일 자체를 설정해서 여기저기 파일에서 import 해서 사용할 수 도 있다. 위의 코드처럼 사용하며, 추가로 다른 스타일을 넣어 줄 수도 있다.
  • 자체 스타일 가이드를 제공하여 동일한 사이즈와 컬러로 통일시켜서 디자인 할 수 있다.

3. 단점

  • 가독성이 나쁘다.
    • 스타일 자체를 변수로 잘 선언해서 재사용한다면 어느정도 커버가 가능하다.
    • config 파일을 고쳐서 일정한 커스텀한 스타일을 추가로 넣어줄 수도 있다. ex) text-14 text-white => text(14 white)
  • 어디에 어떤 속성을 넣었는지 혹은, 관심사 분리가 떨어져 유지보수가 곤란한 경우가 생긴다.
    • 작업자들 간의 사용을 문서화하고, 잘 협의한다면 크게 문제가 되지 않는다. (사실 config 파일을 잘 살펴보면 모두 일정한 규칙이 있을 것이므로 크게 어렵진 않다. 그리고 디자이너와 협업하는 경우라면 스타일 가이드를 만들어 주기 때문에 그 스타일 대로 공용 컴포넌트 등을 작업해 놓으면 통일시켜서 사용할 수 있다)

4. 한발짝 더 나가기 (feat. twind)

tailwind + emotion + styled componets, 진국의 짬뽕탕

  • https://twind.dev/
  • tailwind처럼 css-in-js와 컴포넌트화 및 추가 스타일 설정등 거의 무적의 css 라이브러리 끝판왕이다.
  • 이미 이전에 tailwind와 emotion을 사용한 적이 있는 나의 경우 러닝 커브는 없었다. 다양한 라이브러리를 알 고 있으면 알고 있을수록 유리하다.
import { tw, css, apply } from '@/twind';

const tempBox = apply`w-4 h-4 border-1 border-white bg-red-100`;

const App = () => {
	return (
    	<>
			<div className={tw`w-4 h-4 border-1 border-white bg-red-100`}>하이?</div>
            <div className={tw(tempBox)}>하이?</div>
            <div className={tw(tempBox, css`
            	${apply`w-10`}
                posision: absolute;
                top: 0;
                left: 50%;
            `)}>반가워</div>
        </>
    )
}
  • 위와 같이 혼용해서 사용가능하다. 가독성 및 재사용이 개선될 수 있다.
COMMENT
 
1 2 3 4 5 6 7 ··· 42