[도서]타입스크립트 마스터 2/e

나단 로젠탈 저/김유성 역
에이콘출판사 | 2018년 03월

내용     편집/구성     구매하기

서두

자바스크립트를 공부하고, 실제로 사용하려고 했지만, 너무나 어려웠다. 가장 어렵다고 생각한 부분이 "자동완성"을 제대로 지원하지 않는것.

Type이 정확하지 않기 때문에, 내가 parameter로 전달해야 하는것도 명확하지 않았고, 모든것을 다 알고(혹은 외우고) 호출해야 하는 일이 어려웠다.

그래서 타입스크립트를 공부해 보기로 결심.

에이콘 출판사의 "타입스크립트 마스터 2/e - 예제로 배우는 타입스크립트"를 구매 했다.

출판사에 있는 정오표에 표시된 것 말고도 잘못 된 곳이 보여, 이곳에 정리해 두고자 한다. 지금 발견한건 딸랑 하나라.. 나중에 더 추가 될 수 있을지 모르겠다.

책을 다 읽었다. 당근 완벽하게 모든 내용을 이해한건 아니다. ㅋㅋ 아래 내용중 내가 잘 모르는 상태로 "잘못됐다"라고 이야기 하는것도 있으니, 이 글을 읽는 사람이 잘 가려서 읽기를 바란다.

책 후기

  • TypeScript의 문법은 거의 java와 비슷하다. 좀 다른게 있다면.

    • 변수나 함수의 type을 정의 할 때, 변수명 뒤 쓰는 형태 public id : string;
    • interface 정의에 field도 정의할 수 있음 interface A { id:string }
    • field에 접근할 때, get set 키워드를 통해서 hooking 할 수 있음 get id() { return this._id; }
    • 읽기 전용 속성은 final 대신, readonly readonly name: string;
    • 여러개의 type을 받고 싶을때는 Object 대신 any var a : any = "aa"
    • 여러개의 정해진 type(Union)을 받고 싶을때는 Object 대신 | var a : string|number;
    • 함수의 파라미터에서 같은 타입의, 다른 갯수에 대한 오버로딩시 모두 각각 정의하는 대신 ? 사용 funnction a( b: string, c?: string, d?: string) { ... }
    • 함수의 파라미터에서 타입이 다른 오버로딩시 모두 각각 정의하는 대신 아래 문법 사용

        function a ( b: string, c: string) : string;
        function a ( b: number, c: number) : number;
        function a ( b: any, c: any) : any {
            // code
        }
      
    • 상속 받은 클래스의 생성자에서는 반드시 super()를 수동으로 불러줘야 한다. Java에서는 super()가 자동으로 호출 되지만, 타입스크립트는 그렇지 않음. 자동으로 호출해 주자는 건의(?)가 많았지만, JavaScript의 super-set이라는 등의 이유로 안된듯 하다.

정오표 및 이해하기 어려운 곳 설명

3장 인터페이스, 클래스, 상속

216 페이지

  • Simple Class는 id, name의 속성과 -> Simple Class는 id 속성과
    • Simple Class에는 name 속성이 없다.

156 페이지

  • myClosure; -> myClosure();
    • 예제 소스에서 의도한것은 myClosure라는 함수가 실행되는것을 의도한 것이다(p157페이지의 상단 설명). 그러므로 함수 실행을 위해서 마지막에 () 를 붙여 주어야 한다.

159 페이지

  • 제일 아래의 예제 처음에 아래의 코드 추가

    enum PersonCategory {
        Audlt,
        Infant,
        Child
    }
    
    interface IPerson {
        Category: PersonCategory;
        canSignContracts(): boolean;
        printDetails(): void;
    }
    
  • 아마도 PersonCategory에 관한 enum과, IPerson이라는 interface 관련 코드가 아예 빠진것 같다. p160 내용이나, 그 뒤의 예제 결과등을 참고하면, 위의 코드가 있어야 될 듯 하다.

174 페이지

  • 제일 아래의 예제 코드에서 static staticName: string; -> static name: string;
    • 다음페이지에 나오는 출력 결과물과, 설명을 보면 코드상의 속성 이름이 staticName이 아니라 name이 되어야 한다.

203 페이지 (오타아님)

  • 유창한 구문으로 함수에 프라미스를 -> 플루언트 구문으로 함수에 프라미스를
    • Fluent의 번역을 "유창한"이라고 했다. 그래서 오히려 이해하기 어렵다. fluent 에 대한 개념은 여러 라이브러리의 사용에서 나오므로, 그냥 "플루언트"라고 그대로 적는게 어떨까 싶다. "데코레이트"도 그대로 사용했으니깐. 324페이지에도 "유창한"이라고 적혀 있으니, 이후에 나오는건 모두 걍 fluent라고 생각하면 된다.

226 페이지

  • containsErros 메서드와 ErrorHelper.trace 메서드를 -> ErrorHelper.containsErrors 메서드와 ErrorHelper.trace 메서드를
    • ErrorHelper는 containsError와 trace 메소드를 모두 가지고 있는데, 한쪽에만 ErrorHelper의 메소드인것 처럼 적어 두었다.

261 페이지

  • 정의에 모델 속성을 할당하려면 model: NoteModel 구문이나 -> 정의에 모델 속성을 할당하려면 model = NoteModel 구문이나
    • 260페이지의 마지막에서 이미 model: NoteModel은 오류가 발생한다고 적혀 있다. 그러므로 261페이지의 내용은 model = NoteModel 이 되어야 한다.

274, 463 페이지 (오타아님)

  • MVC는 모델-뷰-컨트롤러의 두 문자 집합으로 -> MVC는 모델-뷰-컨트롤러의 앞 글자의 집합으로
  • 객체지향 모범 사례의 두 문자를 모은 SOLID 디자인 -> 객체지향 모범 사례의 앞 글자를 모은 SOLID 디자인
    • 두 문자는 머리 두(頭)를 이야기 한 것으로 보인다. 그러므로 읽기 쉽게 "앞 글자" 라고 적어두는게 더 읽기 좋겠다.

323 페이지

  • Jasmine uses a simple format for writing tests. Consider the following TypeScript code: -> 삭제
    • 이미 위에 한글로 해석이 되어 있는데, 코드 쪽으로 설명이 내려와 있다. 그러므로 삭제

334 페이지, 335 페이지

  • doCallback 함수 -> doCallBack 함수
    • 예제에서는 "B"지만, 설명에서는 어떤 때는 "B", 어떤 때는 "b"로 사용한다. 그러니 잘 읽어내도록 하자. 심지어, 334페이지 아래쪽에는 let doCallback 으로 변수를 하나 만들어서 쓰고 있어서 더 혼동이 될 수 있다. 예제를 만들때 요런 점도 좀 고려해서 만들었으면 좋았을 텐데...

341 페이지, 342 페이지

  • jasminjquery -> jasmin-jquery
    • 라이브러리 이름이니 정확하게 "-"를 포함해서 적어야 한다.

363 페이지

  • Id: 0, DisplayName: "none"}}); -> { Id: 0, DisplayName: "none"}});
    • SelectedItem의 값으로 Id와 DisplayName을 넣는 Struture를 넣어야 하는것으로 보인다. 그렇게 되려면 "{"를 제일 앞에 추가해 줘서 객체(?) 형태로 만들어야 한다.

09장 타입스크립트 호환 프레임워크 테스트 는 생략함

  • TypeScript 자체를 공부하기 위해서 책을 보는것이라. 지금 당장은 테스트용 프레임워크를 열심히 볼 필요는 없다고 판단. ㅋ. 그래서 걍 이 부분은 읽지도 않고 패스함.ㅋ.

417 페이지

  • mod1.print(); -> m1mod1.print();
    • 첫번째 예제에서 let m1mod1 으로 정의해서 쓰고 있기 때문에, 다음줄에 있는 코드는 당연히 m1mod1.print(); 가 되어야 한다.

426 페이지 (오타아님)

  • 글 내용을 보면, "main.js파일에서는..." 이런 내용이 나오는데, 어디에도 그 main.js 파일을 찾을 수 없다. 그냥 작가가 있다고 생각하고 이야기 한 것인지 모르겠다. 그래서 책 내용을 읽을때, 독자도 상상력을 가지고 읽으면 될 것 같다.

429 페이지

  • 항목 이름은 'jasmineboot'로 -> 항목 이름은 'jasmine-boot'로
    • 소스코드에서는 물론이고, 직전의 설명에서도 'jasmine-boot'로 설명 되고 있다.

432 페이지

  • 다음 AMD 오류인 filenot-found 오류일 수 있다. -> 다음 AMD 오류인 file-not-found 오류일 수 있다.
    • 이전 설명에서도 file-not-found 와 같이 중간에 모두 - 을 넣어 두었다.

436 페이지 (오타아님)

  • 중간에 보면 http-server를 실행하고 결과를 보여주는 설명이 있는데, http-server를 설치하는 방법은 설명도 안 해 줬다. ( 설마.. 9장에서 해 줬나? ). http-server를 설치하려면 console(cmd)창에서 아래의 명령을 입력해 주면 된다.
  • npm install http-server -g
  • 그 이후 http-server를 실행시키면 된다.

448 페이지, 451 페이지, 565 페이지 등 (오타이님)

  • {{{body}}}

    • handlebars 템플릿은 일반적으로 {{ }} 처럼, 이중 괄호를 2개만 쓴다. 그런데 예제에서는 {{{ }}} 에 대한 설명 없이 body만 {{{body}}}로 사용중이다.
    • handlerbars는 {{ }} 를 사용하게 되면, 단순 String으로 치환하는것 이외에, HTML Tag와 관련되는것들을 모두 화면에 출력할 수 있도록 치환해 준다. 예를 들어 title이 "제목은 귀여워 >_<" 와 같다면, "제목은 귀여워 &gt;_&lt;" 와 같이 치환한다.
    • 하지만 {{{ }}} 를 사용하면 치환하지 않고, 그대로 String이 들어가게 된다. 여기에서는 {{{body}}} 영역에 각종 HTML 코드(<p> 나 <br>등)가 들어가야 페이지 HTML 페이지 구성을 할 수 있기 때문에 {{{ }}}를 사용한 것이다.


오늘 도착할지 안 할지도 몰랐는데 -_-
갑자기 덜컥 -_- 책상이 와 버렸다. -_-

그래서 -_- 그냥 의자도..
오늘 밖에 나가서 사 버렸다. -_-

책상이 왔는데, 의지가 없으면 쓰나 -_-?
오프라인에서 사면 가격이 비싸긴 하지만 -_-
그래도.. 하는 김에 확! 해야 되지 않겠나?

이것 저것 찔끔찔끔하면 아무것도 안될거라는 생각에.
그냥 확 사 버렸다. -_-


핸폰으로 찍은거라 화질이 엉망이다.
동영상은 다음에 올렸다. 딴것은 아이디를 만들어야 해서...
( 그리고 -_- 다음 주식을 9주 샀다. ㅋㅋ 사람들은 UCC 세상에 많이 들어가야 한다.ㅋㅋㅋ )

책상은 배송비포함 26,000 원.
의자는 38,000 원 -_-
( 4만 5천원짜리 현금으로 한다고 4만원, 거기다가 다시 2,000원 깍았다. )
( 의자 -_- 졸라비싸 -_-;; 쩝 -_-; 인터넷이면 1만원 아낄 수 있을것 같았는뎅.. )

도합 6만 4천원이다.

이걸로 일주일만 공부해도.. 쓴 돈 보다 더 많은 이득을 볼 수 있을거라 생각한다.


좌우명 중에 하나.
공부하는것, 사람 만나는 것에는 시간과 돈을 아끼지 말라.
  1. 如水 2007.07.01 00:00 신고

    좋쿠만

  2. 옷장수 2007.07.01 11:50 신고

    오... 좋아보이는걸요.. 축하^^

  3. sungsunc 2007.07.01 22:04 신고

    오~

    착한 가격에~ 좋은 물건 사셨는데요~ ^^

    • Chan 2007.07.02 00:55 신고

      물건 살때, 3만원 이상이면.. 전부다 착한 가격이 아니라고 생각하는 1人

  4. 유겸애비 2007.07.02 01:58 신고

    좋은데요. 멋지삼

    • Chan 2007.07.02 02:34 신고

      오늘 한시간 공부했으니. 이제 6시간만 더 공부하면 본전은 뽑을것 같네요 ^_^

  5. 박서은 2007.07.02 18:26 신고

    책상 멋지네. 내가 좋아하는 스타일~

  6. 토끼 2007.07.05 08:20 신고

    나보다 비싸게 샀군!

    책상 16000원
    의자 24000원

    합계 4만원 +ㅁ+

일을 하다가 발견한 문제이다.

특정한 동작을 하는것이 있었는데..
이 놈이 유독스럽게 Mac 에서만 무진장 오래 걸린다는 문제 였다.

윈도우에서는 단 1초도 안되어서 끝나는 작업이었지만,
Mac 에서만 22초가 소요되고 있었다.

문제가 어디서 발생하는지는 찾았는데,
왜 Mac 에서만 유독 느린지 이유를 밝혀 내지는 못했다.


여하튼, 문제는 ArrayList의 removeAll 메소드에 있었다.
removeAll 메소드에 대해서 좀 살펴 보자.



ArrayList 의 상속 관계를 보면 아래와 같다.

사용자 삽입 이미지



여기서 removeAll 이라는 메소드는 Collection 에서 interface를 제공하고 있으며,
실제 그 구현은 AbstractCollection 에 아래와 같이 되어 있다.

사용자 삽입 이미지


보다시피 현재의 컬렉션에서 param 으로 들어온 컬렉션에 있는 item들을 모두 지우기 위해서
iterator 를 구하고, next를 하나꺼내와서
param으로 들어온 c 에 이미 들어 있는지 확인을 하고,
들어 있다면 지워주는 형태로 되어 있다.


여기서 다시 "c에 이미 들어 있는지 확인하는 c.contains( .. ) 의 코드는
indexOf(Object)가 0 보다 큰지 확인하게 된다.
이때 ArrayList의 indexOf(Object) 는 아래와 같이 구현되어 있다.

사용자 삽입 이미지

열심히 이미 가지고 있는 배열에서 루프를 돌면서 같은 놈이 있는지 확인을 한다.
물론 이 놈들이 Object 형태를 비교해야 하기 때문에 equals() 메소드를 사용하여서
비교를 한다.


그렇다면 내가 원래 있던 20개의 Collection 에서
10개의 데이터를 removeAll 한다고 해 보자.

1. AbstractCollection의 removeAll을 호출한다.
2. 20개에 대해서 iterator 를 구해서 20번 루프를 돌아야 한다.
2.1. 현재 선택되어 있는 아이템이 10개에 포함되어 있는지 확인해야 한다.
2.2. 이것을 확인하기 위해서는 indexOf() 를 수행해야 한다.
2.3. indexOf 내부에서는 10개에 대해서 루프를 돌아야 한다.
2.4. Object 비교이기 때문에 equals 를 수행하기 위해서 내부적인 연산을 해야 한다.


중요한것은 전체 배열에 대해서 이중 for loop 를 돌아서 처리 한다는것이다.




그렇다면 이 loop를 좀 더 덜 돌릴 수 있는 방향이 없을까?
항상 cpu 와 memory 사이에는 trade-off 가 있다.
물론 지금 이야기 하고자 하는 방법은 memory 측면에서는 손해 볼 수 있다.




내가 그래서 선택한 방법은 HashMap을 사용하는 방법이다.
안타깝게도 HashMap 에서는 removeAll 같은 메소드를 제공해주지 않기 때문에.
직접 for 루프를 돌아 가면서 데이터를 지워주어야 하는 귀찮은 점은 있다.

HashMap의 remove(Object) 코드는 아래와 같이 구성되어 있다.

사용자 삽입 이미지


remove(Object)를 수행하게 되면 removeEntryForKey(Object)를 수행하게 된다.

이때 removeEntryForKey(Object) 에서는
param으로 들어온 key에 대해서 hashCode() 를 구하고,
전체 배열 중에서 구해진 hash와 같은 값을 가지는 위치만을 비교 하게 된다.


그렇다면 HaspMap 에서 데이터를 지우는 순서를 보자.

1. removeAll이 없기 때문에 어쩔 수 없이 외부에서 for를 돌려서 remove 를 여러번 시켜 준다.
2. hashCode() 값을 구하고, hash 같은 배열 부분만을 검색한다.
3. equals()를 호출하여 비교하면서 처리 한다.

여기서도 사용자가 for를 외부에서 돌려 주고,
내부에서도 while loop를 도는 2중 loop 구조이기는 하지만,
hash 가 같은것만 돈다는것이 핵심이다.


이 결과는 equals()과 hashCode()를 구현하는 방식에 따라서 다른 결과를 도출할 수도 있다.



약 400개의 데이터에 대한 작업이었는데
ArrayList.removeAll()에서는 22 초가 걸렸었고,
HashMap.remove() + for 로 수정한 뒤에는 0.5 초대의 시간이 걸렸다.


이 결과는 Mac 에서만 유용할 수도 있다. 실제 윈도우에서도 약간 더 빨리 동작하기는 했다.
시간 날때  똑같은 코드가 왜 Mac 에서만 이렇게 느리게 동작하는가에 대한 조사를 해 보아야 겠다.


대학교 자료구조 수업 시간에 자주 등장하는 내용이지만,
실제로 이렇게 -_- 겁나게 차이를 느껴 보기는 처음이었다. -_-;


대학교때 공부 잘했던 사람들이 나와서도 잘 사는 이유가 있나 보다. ㅋㅋ
  1. 유야 2007.06.10 00:30 신고

    역시 난 제대로 디버깅한거였어!!!!
    Font의 canDiaplay도 무쟈게 느리더만 -_-

    • Chan 2007.06.10 01:18 신고

      대단해. ㅋㅋ.
      근데 -_- 왜 느릴까 -_-? 쩝쩝쩝..

  2. 옷장수 2007.06.10 12:55 신고

    Font의 canDisplay()가 느린이유는 char를 glyph으로 변환하는 과정을 거치기 때문이 아닐런지..

    • Chan 2007.06.10 21:27 신고

      ㅇㅎㅎ ;; 뭔 말인지 몰겠따.. ㅎㅎ ;;;

  3. 유겸애비 2007.06.11 11:40 신고

    이거 맥하고 상관이 없는글이자나욧!!
    글구 canDisplay()는 글립으로 만들지 않고 그냥 폰트에 어떤 문자가 정의되어있는지를 보는것일듯 싶네요

    • Chan 2007.06.11 18:17 신고

      수정했습니다. ㅋㅋ;;
      그리고 ;; 또 어려운 말들을 하시는군요.;; ㅎㅎ ;;

    • 옷장수 2007.06.12 09:39 신고

      오랜만에 보는거라서 소스를 봤었는데 canDisplay가 호출되면 CharToGlyphMapper라는 놈을 찾아서 여기에서 glyph이 보여질 수 있는지를 체크하던데요.

  4. 유겸애비 2007.06.12 19:16 신고

    Re:옷장수// Font란 char to glyph의 map이라고 추상화 시킬수 있는데 key가 정의되어있난 보는거지 char에서 glyph으로 변환을 시키는건 아닐껍니다.

    • Chan 2007.06.12 23:36 신고

      심도 있는 댓글이군요~ ㅋ
      찾아봐야 겠당~ ㅋㅋ

    • 옷장수 2007.06.14 14:03 신고

      음.. char를 glyph으로 변환한다는게.. char 값을 glyph의 index 값으로 변환한다는 의미였는데요.

http://phpschool.com/bbs2/inc_view.html?id=11732&code=tnt2

<link rel=alternate media=print href="http://junyoung.info/aaa.doc">
<a href="javascript:window.print()">프린트</a>


지금 현제 제 서버에 파일을 올려 놓았으니...
그냥 복사 하셔서 실행하시면 될겁니다 ^^
참고로 http:// 이거 꼭 쓰셔야 합니다. 상대경로는 되지 않습니다...

+ Recent posts