210404 Vanilla JavaScript TDD Practice

Vanilla JavaScript TDD

210405 Update

이번 포스팅에서는 TDD방식으로 Vanilla JavaScript를 사용해서 개발을 하는 방법에 대해서 실습한 내용을 기반으로 블로그 포스팅을 해보려고 한다.

처음에는 이 TDD방식이 익숙하지 않아서 느릴지 모르지만 이런 과정이 견고한 Logic을 만들게 되고, 결국에는 개발속도가 빨라지는 결과를 낳게 된다고 한다.
여기서 포인트는 익숙해지는 것! 개발자 커뮤니티에서 어떤 개발자 분이 말씀하셨는데 "개발의 가장 좋은 실력향상 방법은 반복"이라고 하셨다. 누군가로부터 무언가 새로운 것을 배웠을 당시에 이해를 한 것처럼 착각하고 마치 내 것이 된거마냥 생각하는 사람들이 많은 것 같다. 이러한 개인적인 반복학습 없이 한 두 번 더 본다고 절대 내 것이 되었다고 볼 수 없다.

내가 이렇게 블로그에 배웠던 내용을 정리하고, 필기했던 노트를 첨부하는 이유는 반복학습을 위해서다.
이 TDD 방식 또한 처음에 적용할때 시간이 오래 걸린다고 생각하지 말고 스스로 생각하고 반복을 하면서 내 것으로 만들도록 노력을 해야겠다.

본론

개선전 코드
아래의 코드에는 문제가 많다. Increase button에는 여러 관심사들이 혼재되어 있다. 단순히 화면에 버튼을 출력하지 않고, click event가 binding되어있다.
또한 JavaScript 코드를 보면 count라는 변수를 전역 스코프에 작성을 하였다. 이는 변수이름이 충돌할 위험을 증가시킨다.
그리고 카운트 수를 출력할 span 태그의 id를 hard coded한 방식으로 작성을 해서 DOM element를 가져오고 있다. 만약에 markup이 변경된다면 변경된 id에 맞춰서 작성한 id를 JavaScript 코드에서 수정해줘야 한다.

아래의 간단해보이는 코드에는 위와같은 복합적인 문제들이 혼재되어있다.

Read more

210404 JavaScript module pattern


이번 포스팅에서는 JavaScript에서 문제해결 패턴으로 가장 많이 사용되는 module pattern에 대해서 포스팅을 하려고 한다.
이 module pattern은 JavaScript의 코드 관리 기법 중 하나로 함수로 데이터를 감추고, 모듈 API를 담고 있는 객체를 반환하는 형태로 코드를 작성하며, JavaScript의 특성상 객체를 핸들링하기 위한 방법론 중 하나이다.
JavaScript의 모듈 패턴은 유효범위를 지정하는 언어와 같이 private, public 등의 캡슐화를 사용하는 방법이라고 볼 수 있다.
그리고 module pattern에는 두 가지 패턴이 있는데 임의 모듈 패턴즉시 실행 함수(IIFE) 모듈 패턴(Singleton instance)이 있다.

아래 임의 모듈 패턴과 즉시 실행함수 모듈 패턴(IIFE)를 보면 가장 첫 줄에 namespace pattern이 사용이 되었는데 이는 자바스크립트에서 함수 또는 변수 객체를 다룰때 중복된 이름의 사용으로 인한 문제를 방지하기 위한 것이다.
global영역에 객체 고유의 영역을 지정하고 변수와 함수의 할당을 해당 namespace의 하위로 두게 해서 중복된 이름으로 인한 오류를 예방하는 방법이다.
(즉 모듈패턴이란 이 namespace pattern에 언어적 유효범위를 추가해놓은 것이라고 이해하면 된다)

namespace 패턴

1
2
3
4
5
6
7
var App = App || {}; // declare namespace
App.getName = function () {
return 'hyungilee';
};
App.hello = function () {
return 'hello';
};

임의 모듈 패턴 : 임의 함수를 호출하여 생성하는 모듈

여러 객체가 필요한 경우에 사용되는 패턴 방식이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// namespace 만들기
var App = App || {};
// namespace에 함수를 추가. 의존성있는 God function을 주입
// Person이라는 module(함수)를 넣어준다.
App.Person = function (God) {
// God module이 name을 생성하는 역할을 한다.
// God module을 통해 생성한 name값을 변수에 초기화한다.
var name = God.makeName();

// API 노출 (getter, setter 함수를 가지는 객체를 반환)
return {
getName: function () {
return name;
},
setName: function (newName) {
name = newName;
}
};
};

const person = App.Person(God);
person.getName();
Read more

210217 Jest의 test, it, describe


이번 포스팅에서는 Jest에서 테스트 코드를 작성할때 사용하는 test와 it 키워드의 사용과 여러 개의 테스트 케이스를 묶을때 사용하는 describe 키워드에 대해서 정리를 해보겠다.

test와 it 키워드의 사용

이전 포스팅에서 test라는 키워드를 사용해서 테스트 케이스를 작성해보았다. 이 키워드를 대체해서 it이라는 키워드도 사용될 수 있는데 작동 방식은 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// test keyword를 사용한 테스트 코드 작성
const { test, expect } = require('@jest/globals');
const sum = require('../sum');

// 작성한 테스트코드가 무엇을 하는지에 대해서 첫번째 parameter로 작성해준다.
test('properly adds two numbers', () => {
// expected result
expect(sum(1, 2)).toBe(3);
});

// it keyword를 사용한 테스트 코드 작성
it('properly adds two numbers', () => {
expect(sum(1, 2)).toBe(3);
});
Read more

210208 Jest의 다양한 matcher


Jest Matcher

이전에 사용했던 toBe() matcher는 숫자나 문자와 같은 기본 타입(Primitive Type)의 데이터를 비교할때 사용했다. 그럼 그 외에 다른 matcher에는 어떤 것들이 있는지 알아보고 실습을 해보도록 하겠다.

Jest의 다양한 matcher

  • toEqual() : primitive type의 변수나 객체를 비교할때 사용된다.
    객체는 참조변수이기 때문에 값은 같더라도 참조하는 주소가 다르다.

  • toStrictEqual() : 객체를 좀 더 엄격하게 검사할때 사용된다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // makeUser()를 toEqual()로 검사를 하게 되면 passed
    // toStrictEqual()를 toEqual()로 검사를 하게 되면 failed
    const fn = {
    add: (a, b) => a + b,
    makeUser: (name, age) => ({ name, age, gender: undefined }),
    throwErr: () => {
    throw new Error('xx');
    }
    };
Read more

210208 Jest의 개념과 기본사용


Jest

Jest는 Facebook에 의해서 개발된 JavaScript 테스트 프레임워크이며, 대규모 Web application의 테스트를 좀 더 심플하게 할 수 있도록 도와준다.

Jest framework의 사용

간단한 JavaScript 코드를 Jest framework를 사용해서 테스트 해보도록 하자.

실습 내용

실습 Repository : https://github.com/LeeHyungi0622/javascript-jest-test-practice-repo

  1. 프로젝트의 branch 기본 구성은 master branch로 구성한다.

  2. README.md 파일의 documentation작업을 제외한 모든 작업은 별도의 branch를 새로 끊어서 작업을 시작한다.


Read more