[React, React-native] Flow로 타입체크하기!

Duckuism
Duckuism

--

Flow 공식 문서 따라하며 사용법 익히기

들어가며

여러분, 안녕하세요? 오랜만에 돌아왔습니다. react, react-native 뉴비인 저는 회사 프로젝트 구조를 파악하기 위해 노력하고 있는데요. 그 과정에서 여러 가지 필수 라이브러리들을 공부해야했습니다. 아직도 공부하고 있고요. 제가 공부하는 김에, 영문으로 된 공식 문서를 국문으로 정리해놓으면 어떨까하는 생각이 들었습니다. 아마 다른 필수 라이브러리들도 자주 올리게 될 것 같아요. 저처럼 초보 개발자 분들에게 도움이 되길 바랍니다.

Flow와의 첫 만남

한 라이브러리의 예제 코드를 보던 중, 이런 코드를 보았습니다.

응? 제가 알던 자바스크립트의 코드와는 사뭇 달랐는데요. 타입 형태가 앞에 기술된 것처럼 보였습니다. 이런 스크립트 언어라면 타입스크립트밖에 아는 게 없는데, 이 소스가 존재하는 파일은 분명히 자바스크립트파일이었습니다. 자바스크립트 파일에서 타입스크립트를 사용할 수는 없을텐데, 왜 이런 코드가 있고 정상적으로 동작하는지 의문이었습니다. 조금 찾아보니 이 코드의 정체는 ‘Flow’ 라는 라이브러리였습니다. 그럼 이제 Flow에 대해 알아볼까요?

Flow란?

Flow 공식 사이트에 접속하면 이런 문구를 볼 수 있습니다.

Flow is a static type checker for javascript.

Flow는 자바스크립트에서 쓰이는 ‘정적 타입 체커’입니다. ‘정적’이란 말은 체크하는 그 순간의 코드 상태를 체크한다는 뜻이고, ‘타입 체커’는 말 그대로 코드의 타입을 체크해준다는 말입니다.

자바스크립트의 타입은 상당히 유동적으로 사용할 수 있다보니, 타입을 체크하고 예외를 처리하는 데에 생각보다 많은 시간을 사용할 때가 있습니다. Flow는 이런 과정을 대신해줌으로써 코드 생산성을 올려주는 도구입니다. 직접 사용해본적이 없으시면 사용하는 방법이 조금 생소할 수도 있는데요. 어떻게 사용하는 지 공식 문서를 따라가면서 알아보도록 하겠습니다. 헷갈리는 요소들을 없애기 위해 공식 문서의 목차와 동일하게 진행하겠습니다.

Flow 사용 방법 알아보기

공식 문서에 나와있는 사용 방법 설명은 다음과 같은 목차로 진행됩니다. 목차를 따라가며 천천히 살펴보도록 하죠!

  • Getting Started
  • Installation
  • Usage

1. Getting Started

Flow는 타입명으로 적혀져 있는 주석 모두에 대해 에러 체크를 진행합니다. 우리는 타입명을 적음으로서 Flow에게 우리 코드가 동작하는 방식을 알려주고, Flow는 우리가 적은 타입명을 통해 코드를 검사하며 우리의 코드가 제대로 작동하는 지 검사합니다. 예제를 살펴볼까요?

예제 코드 1)

// @flow
function square(n: number): number {
return n * n;
}

square("2"); // Error! -> square 함수가 받는 매개변수의 타입은 number로 정해져 있는데, 여기서는 문자열을 받고 있죠? 그러므로 타입 체크 에러 발생!

위의 예제 코드를 보니 조금 감이 오시나요? 우리는 square 함수의 매개변수에도 number라는 타입을 지정했고, suqare 함수에도 number라는 타입을 지정했습니다. 즉, square함수는 number 타입의 매개변수를 받아서 number 타입의 결과를 반환하는 함수라는 뜻이죠. 이 법칙에 어긋나는 코드가 있다면 Flow는 에러를 발생시키게 됩니다.

이 뿐만 아니라, Flow는 자바스크립트 자체에 대한 오류도 검사해줍니다. 아래 예제를 살펴볼까요?

예제 코드 2)

// @flow
function square(n) {
return n * n; // Error! -> square 함수는 숫자 연산을 실행해야 하는데, 매개변수인 n이 문자열이라면 연산을 수행할 수 없겠죠? 그러니까 타입 체크 에러 발생!
}

square("2");

어때요? 저희는 타입명을 기술하지도 않았는데, flow가 자동으로 연산 오류를 잡아주는 것을 볼 수 있습니다. 신기하죠?

만약 저희가 코드에서 flow를 통해 타입 검사를 하고 싶지 않다면, 간단하게 @flow 키워드를 삭제해주면 됩니다.

2. Installation

공식 문서에서 package manager와 compiler 종류를 선택하면 그에 맞는 설치 방법이 나옵니다. 저는 package manager는 yarn, compiler는 Babel을 선택하여 진행하도록 하겠습니다.

여기서 잠깐! 이 페이지의 package manager는 node package manager를 말하는 것인데요. 자바스크립트를 실행시켜주는 node.js 환경에서 사용할 수 있는 라이브러리들을 관리하는 툴입니다. 또한 compiler는 우리가 작성한 자바스크립트 ES6 이상의 문법으로 작성된 코드들을 ES5 문법으로 변경해주는 도구라고 생각하시면 이해가 쉽습니다.

2–1. Setup compiler

첫 번째 순서는 컴파일러 설정을 하는 것인데요. 저희가 사용할 컴파일러는 Babel입니다. Babel은 Flow를 지원하는 자바스크립트 코드 컴파일러입니다. Babel은 Flow를 적용하기 위해 우리가 사용한 타입명 부분을 제거한 후 반환해줍니다.

먼저 아래 명령어를 통해 필요한 패키지들을 설치해줍니다.

yarn add --dev babel-cli babel-preset-flow

그리고 프로젝트의 Babel의 설정 내용을 담고 있는 .bablerc 파일을 수정합니다. 이 파일은 보통 프로젝트 폴더 최상위에 위치하고 있습니다. 아래와 같이 presets에 flow라고 적어줍니다.

{
"presets": ["flow"]
}

우리의 모든 소스 파일이 src폴더 안에 있다고 가정한다면, 아래 명령어를 실행하면 src 폴더의 모든 소스내용을 compile한 결과가 lib폴더에 저장됩니다.

yarn run babel src/ -- -d lib/

위의 과정을 좀 더 간편하게 하기 위해 package.json 파일에 명령어를 저장해놓고 사용하는 것을 추천합니다. (공식문서의 예시일 뿐이므로 자유롭게 커스텀해서 사용하시면 됩니다.)

{
"name": "my-project",
"main": "lib/index.js",
"scripts": {
"build": "babel src/ -d lib/",
"prepublish": "yarn run build"
}
}

2–2. Setup flow

이번에는 flow 설정을 해보겠습니다. 2–1번에서와 마찬가지로 package 매니저를 이용해서 devDependency에 flow-bin 라이브러리를 설치해주세요!

yarn add --dev flow-bin

그리고 flow를 실행하면 됩니다.

yarn run flow

이 때, yarn run flow init 을 통해 flow 설정 파일을 생성할 필요가 있을 수도 있습니다. 처음에 에러가 나시면 yarn run flow init 을 통해 .flowconfig 파일을 생성하신 후 yarn run flow 를 입력해보세요.

그럼 아래와 같이 Flow 실행 결과가 콘솔에 출력됩니다.

yarn run v0.15.1
$ flow
No errors!
✨ Done in 0.17s.

3. Usage

자, 이제 Flow를 설치하고 사용할 준비가 모두 완료되었는데요. 가장 중요한 것은 어떻게 사용하느냐겠죠? 전혀 어렵지 않습니다. 렛쯔고!

일단 Flow가 설치되었다면 기본적인 레벨에서 Flow를 사용하는 일반적인 순서는 다음과 같습니다.

공식문서에는 위의 순서와 똑같이 목차가 구성되어 있는데요. 각각의 목차를 자세히 살펴보도록 하겠습니다.

3–1. Initialize Your Project

프로젝트에서 Flow를 사용하기 위해 필요한 명령어는 하나 밖에 없습니다.

flow init

이 명령어를 실행하면 프로젝트 최상위에 .flowconfig 파일이 생성되는데요. 이 파일은 Flow 에게 오류 검사를 시작할 위치를 알려줍니다. .flowconfig 파일은 빈 상태로 존재하는 경우도 많지만, 원한다면 다양한 옵션으로 flow 설정을 변경할 수 있으니 관심있으시면 이곳을 살펴보세요!

3–2. Run the Flow Background Process

만약 컴퓨터 공학의 지식이 없다면 이 부분이 조금 이해가 어려울 수도 있는데요. 쉽게 설명해보겠습니다. 컴퓨터가 해야하는 명령을 모아놓은 것이 thread이고, 이 thread들이 모여서 하나의 process를 이룹니다. 즉, process는 굉장히 많은 명령어 집합이라고 할 수 있어요. process를 실행한다는 얘기는 수 많은 명령어를 실행하도록 하는 것과 같은 거죠.

그렇다면 background는 무슨 뜻일까요? 배경에 깔려있다? 직역하면 조금 이해하기 어렵죠? 쉽게 말해서 cpu에서 계속 실행되고 있다고 생각하면 됩니다. 특정 프로세스를 시작하면, 한 번 실행되고 중지되는 것이 아니라 계속 실행되고 있는 거죠.

즉, Flow background process를 실행시키는 것은 Flow가 타입체크를 하기 위한 수 많은 명령어를 cpu에서 계속 실행시키도록 하는 것입니다.

그냥 Flow를 실행한다고만 생각하셔도 사용하는데는 전혀 문제가 없습니다.

Flow의 가장 중요한 이점은 빠르게 코드를 체크할 수 있는 능력입니다. 일단 프로젝트가 Flow를 사용할 수 있다면, 우리는 아래 명령어를 통해 빠른 속도로 코드를 체크할 수 있도록 Flow를 실행하기만 하면 됩니다.

flow status

이 명령어는 위에서 설명한 Flow backgroud process를 실행합니다. Flow가 모든 Flow 파일들을 체크하도록 하고, 한 번 체크한 이후에도 코드가 바뀔 때마다 변화를 감지 한 후 에러 체크를 할 수 있게 되는 것이죠.

Flow background process는 오직 하나만 실행됩니다. flow status 를 여러번 입력해도 새로운 Flow background process가 실행되지 않고 기존에 실행되고 있는 프로세스를 사용합니다.

Flow background process를 종료하려면 flow stop 명령어를 입력하면 됩니다.

3–3. Prepare Your Code for Flow

Flow background process는 flow의 검사 대상이 되는 파일들을 검사합니다. 그런데 우리는 어떻게 Flow background precess에게 해당 파일이 Flow가 검사해야하는 파일들이라고 알려줄 수 있을까요? 그 비밀은 바로 @flow 키워드 입니다. 자바스크립트 파일 최상단에 주석으로 이렇게 @flow 키워드를 입력하면, 이 키워드를 통해 Flow background process가 에러 체크를 해야하는 파일을 인식하고 검사하는 것이죠.

// @flow

이 표시는 일반 자바스크립트에서는 주석으로 처리되지만, Flow background process는 이 표시가 있는 파일들을 모아서 검사합니다.

만약 이 기호가 없다면 flow check --all 명령어를 입력하지 않는한 검사가 되지 않을거에요.

3–4. Write Flow Code

이제 Flow에서 원하는 대로 타입을 명시하여 코드를 작성하면 됩니다. 맨 위에 // @flow 처럼 주석을 달고, 매개변수와 함수이름 다음에 콜론(:)을 이용해서 타입을 명시해주면 됩니다.

// @flow

function foo(x: ?number): string {
if (x) {
return x;
}
return "default string";
}

함수의 반환타입은 함수 끝에 추가된다는 것을 명심하세요.

number앞에 물음표는 maybe types이라는 방법으로써, null과 void를 허용하는 flow의 타입 선언 방법입니다. 만약 물음표가 타입 앞이 아니라 x?: number 와 같이 매개변수 뒤에 쓰였다면 optional object properties라고 해서 null은 허용하지 않고 void만 허용하는 선언 방법입니다.

자, 그런데 위의 예시코드는 에러가 있는 것 같습니다. foo함수의 매개변수는 숫자가 들어가야 하는데, foo 함수의 반환 타입이 number가 아니라 string이죠? 과연 Flow가 이 에러를 잡아낼 수 있는 지 검사해볼까요?

3–5. Check Your Code

자, 위의 예제 코드를 검사해보곘습니다.

# equivalent to `flow status` (flow나 flow status나 똑같다네요!)
flow

위의 명령어가 실행되면 Flow background process는 모든 Flow 대상 파일을 검사하기 시작합니다. 위의 코드의 검사 결과는 다음과 같네요.

test.js:5
5: return x;
^ number. This type is incompatible with the expected return type of
3: function foo(x: ?number): string {
^^^^^^ string

에러가 났습니다! 반환 타입이 number라면서 string을 반환해야한다고 하고 있네요. 우리는 매개변수의 타입을 string으로 바꾸던지, 함수의 반환 타입을 number로 바꾸던지, 함수의 내용을 바꿔서 형변환을 하던지 해야할 것입니다.

자 어떠신가요? 우리가 순수 자바스크립트로 코드를 작성할 때 놓칠 수 있는 많은 오류들을 Flow가 대신 해줄 것이라는 생각이 드시나요? 막상 살펴보니 사용방법도 그리 어렵지 않습니다. 저도 타입스크립트를 쓰지 않는다면 앞으로 계속 사용하게 될 것 같네요.

오늘은 자바스크립트 프로젝트 대부분에서 사용하는 주요 라이브러리인 Flow의 사용 방법에 대해 알아보았습니다. 다음에는 더 유익한 내용으로 돌아오도록 하겠습니다.

긴 글 읽어 주셔서 감사합니다! 🙏🏻

글을 마치며

만약 위의 내용에 대해 이해가 되지 않는 부분이 있으시거나 수정해야할 부분을 발견하셨다면 주저없이 댓글 남겨주시거나 아래 이메일로 피드백주시면 감사하겠습니다.

--

--