728x90

안녕하세요. 정말 오랜만에 포스팅합니다.

전기차 보조금 초간편 조회

https://ev.bot-more.com

 

 

전기차 시대가 천천히 다가오고있네요.

예상보다는 느리게 오지만 전기차 시대가 온다는대는 모두 이견이 없는듯 합니다.

 

정부에서도 전기차 시대에 발맞춰 보급을 확대하고자,

전기차 보조금 정책을 시행하고 있는대요.

 

적게는 백만원에서 크게는 천만원이 훌쩍 넘는 전기차 보조금.

제대로 모르고 가면 마치 딜러가 할인해주는듯

홀리는 말에 넘어가기 쉽상입니다..!!

 

이렇게 큰 금액인 전기차 보조금을 어떻게 조회해야 하는지,

많은 실수요자 분들이 어려워하고 계십니다.

저도 정말 불편했고요.

 

이건 뭐 전기차를 사라는건지 말라는건지.

https://ev.or.kr/nportal/buySupprt/initSubsidyPaymentCheckAction.do

 

무공해차 통합누리집

기준년도 2019 2020 2021 2022 2023 2024 조회

ev.or.kr

 

유일한 전기차 보조금 조회 가능 방법이 이 무공해차 누리집을 통해서 찾는건데요.

내 지역, 내가 원하는 차를 비교하기가 너무너무 불편하더라고요.

 

그래서 그냥 제가 전기차 보조금 조회 챗봇을 만들었습니다.

 

모델명 대충 입력하고,

지역명 대충 입력하면 원하는 보조금 조회가 가능합니다..!!

 

차량의 정확한 이름을 모르더라도 조회 가능하니 편하게 이용해보세요

 

728x90
반응형
728x90

In Typescript, the exclamtion is sometimes used in last of the characters.

For example,

const people = { name: 'kim' };

if (people.name!) {
  ...
}

what is meaning?

In TypeScript, the exclamation mark (!) is used to assert that a value is not null or undefined. It is called the non-null assertion operator. However, it is typically used when you are certain that the value will not be null or undefined, and it should be used with caution.

728x90
반응형

'개발, 코딩 > typescript' 카테고리의 다른 글

typescript, 제네릭에대해 알아보자  (0) 2022.11.10
optional과 undefined의 차이  (0) 2022.10.26
typescript, 타입 소개  (0) 2022.10.26
728x90

동일한 정규식에 동일한 값을 넘겼음에도

반복해서 true, false를 번갈아 반환했다.

대체 왜!!!

 

이유

정규식에 g 옵션이 있으면, test() 메소드는 정규 표현식의 lastIndex를 업데이트하게 된다.

test() 메소드와 exec() 메소드는 내부적으로 lastIndex부터 문자열을 검사하게 되는데,

test() 메소드는 true를 반환했던 lastIndex부터 계속해서 검사하게 된다.

 

그리고 lastIndex는 false를 반환하기 전 까지 초기화가 안되는 특징이 있다.

 

따라서, 체크때마다 true / false를 반복해서 반환하는 이슈가 발생

728x90
반응형
728x90
// < 18
type TagPrpos = {
  name: string,
};

const Tag: React.FC<TagProps> = ({ name }) => (
  <div>
    <div>{ name }</div>
    { children }
  </div>
);
// > 18
type TagPrpos = {
  name: string,
  children: react.ReactNode
};

const Tag: React.FC<TagProps> = ({ name, children }) => (
  <div>
    <div>{ name }</div>
    { children }
  </div>
);

 

children 요소를 명시적으로 선언해줘야한다.

< 18에서는 children이 optional로 선언되어있었던 반면,

18에서는 optional 선언도 제거되었기 때문이다.

728x90
반응형
728x90

class변수를 어떤 방식으로 선언할지 고민해보게되는 계기가 있었다.

class변수에는 총 세가지가 있다
1. static 변수
2. instance 변수
3. local 변수

각각의 특성에 대해 알아보고 언제 어떻게 선언하는게 프로그램에 도움이 되는지 고민해보자.

1. static변수

class HumanLifeCycle {
  static morningRoutine = 'coffee';
  ...
}

위에서 보이는 static키워드를 이용한 선언 방식이 static변수이다. 변수를 static으로 선언하게 되면 해당 클래스러 몇개의 인스턴스를 생성하던지 상관없이 메모리상 하나의 변수만 참조하게된다. 따라서, 메모리를 절약할수 있다는 장점이 있다.
그렇다고 늘 static으로 선언해서는 안된다. 단 하나의 변수라는 개념인 만큼 여러 인스턴스에서 하나의 값을 공유하게 되기 때문에 각 인스턴스가 독립적으로 변수를 다뤄야 한다면 static을 써서는 안된다.
static이란 이름에 걸맞게 정적이고(변동이 없고) 클래스 인스턴스 간 글로벌하게 쓰이는 경우에 static변수를 쓰도록 하면 어떨까?

2. instance변수

class HumanLifeCycle {
  constructor() {
    this.pattern = {
      morning: '',
      afternoon: '',
    };
  }
}

위 코드에서 보이는 this.pattern이 instance변수에 해당한다. new연산자를 통해 인스턴스를 생성할때 마다 메모리에 해당 변수에 대한 공간을 할당한다. 즉, 인스턴스간 독립적인 변수를 갖게된다.
static이 클래스 레벨에서 변수를 공유하는것과 달리 인스턴스 레벨에서 변수를 다룬다는 차이가 있다. 메모리에 예민한 프로그램이 아니라면 직관적인 instance변수를 주로 즐겨쓰지만 최고의 프로그래머가 되려면 최적화에 대해 더 고민해볼 필요가 있을것 같다.

3. local변수
클래스 내 메소드에서 선언한 변수에 해당한다. 메소드 내에서 잠시 값을 담아두기 위해 쓰이곤 한다.

728x90
반응형
728x90

1. tsc 컴파일시 디렉토리 생성 기준
-> 최상위에 위치한 ts파일

2. 컴파일된 js파일이 위치할 폴더 지정
-> outDir

3. 컴파일할 폴더의 루트경로 설정 (해당 설정을하면 경로외에 위치한 ts파일이 있을때 컴파일 에러를 발생 시킨다. 협업시 잘못된 디렉토리 구조 생성을 방지할 수 있다.)
-> rootDir

4. 컴파일 대상에서 특정 파일 제외
-> exclude (배열에 경로+파일명으로 지정, *사용가능)

5. 컴파일 대상 제한 (징정된 파일만 컴파일함)
-> include (배열에 경로+파일명으로 지정, *사용가능)

6. 업데이트 된 ts파일만 컴파일 (true로 하면 디스크 공간을 더 많이 차지한다는 이슈..? 가 존재)
-> incremental

7. 컴파일 수준 정의 (보통 es5/6), 낮은 버전을 쓸수록 더 더러운 코드가 많이 발생하기 때문에 적정 수준의 버전 선택이 중요함
-> target

8. 모듈 정보를 어떤 것으로 할지 설정 (node 환경이면 보통 commonjs, 브라우저 환경이면 ecmascript에 맞는것으로)
-> module

9. module에서 필요한 library만 설정하려면
-> lib (배열에 지정, dom 등이 위치할 수 있음)

10. 프로젝트에 js를 쓸것을 허용
-> allowjs

11. js파일에서 문제가 있다면 경고를 띄움
-> checkjs

12. react관련 jsx를 쓰려면
-> jsx

13. 내 코드를 라이브러리로 공유, 타인에게 제공할 계획이라면..?
-> declaration

14. 다수의 컴파일된 js파일을 하나의 파일로 만드려면
-> outfile

15. incremental과 함께 이전 빌드 정보를 기억해, 다음 빌드 속도를 향상시키려면
-> composite

16. incremental을 사용할때 이전 빌드 정보를 저장할 파일 경로를 지정하려면
-> tsBuildInfoFile

16. 코드상에 comment를 모두 제거하려면
-> removeComment

17. 컴파일 에러체크만 하고 js로의 컴파일로 변경은 하고싶지 않을때
-> noEmit

18. 각각의 파일을 다른 모듈로 변환하고자 할때
-> isolatedModules

19. 엄격한 확인을 굳이굳이 특별한 이유로 받기 싫다면
-> strict false

728x90
반응형
728x90

제네릭
보기에도 이상하고 워딩도 애매서
단어만 들었을땐 거부감이 좀 든다

하지만, any를 남발하지 않으려면
제네릭은 반드시 알아야만 할것으로 생각된다.

분명 많은 개발자들이 any를 쓰는 그 순간까지
아 이거 그런거 없나..
하고 생각했을텐대
알고보면 바로 그게 제네릭이다
(나만 그랬나..?)

제네릭에대해 바로 알아보자.
제네릭을 정의 하자면 "아직은 정해지지 않았지만 쓰는 사람이 쓰는 타입에 따라 유동성있게 정해지는 타입임"을 의미한다.

일단, 제네릭 없이 각 기계장치에 엔진을 간단 붙여본다.

interface Vehicle {
  run() => void;
}

class Car implements Vehicle {
  run(runTime: number) {
    console.log('4 wheels drive...', runTime);
  }
  
  changeWheel(wheelNumber: number) {
    if (wheelNumber > 4)
      throw new Error('You have only 4 wheels...');
      
    console.log('changed whleel');
  }
}

class Airplane implements Vehicle {
  run(runTime: number) {
    console.log('2 wings drive...', runTime);
  }
  
  fixWing(wingPosition: 'left' | 'right') {
    console.log('fix..!');
  }
}

function doPreRun(vehicle: Vehicle): Vehicle {
  vehicle.run(30);
  return vehicle;
}

const genesis = new Car();
genesis.changeWheel(3); // ok

doPreRun(genesis);
genesis.changeWheel(4); // failed error

위 코드에서 보다시피
예열이 되어 반환된 인스턴스는
본인의 정체성을 잃고 interface의 구현만 갖는다.
doPreRun함수가 Vehicle 인스턴스를 리턴하기 때문이다.

이러한 상황을 피하고 보다 유동성있고 추상화하여 작성하고 싶다?
이럴때 바로 제네릭이 필요하다
제네릭을 이용해 코드를 작성해본다.

function doPreRun<T>(vehicle: T): T {
  vehicle.run(30);
  return vehicle;
}

const genesis = new Car();
genesis.changeWheel(3); // ok

doPreRun(genesis);
genesis.changeWheel(4); // ok

T라는 캐릭터를 썻는데 어려워할 필요없다.
임의의 T(Type)이라는 것이니까
다른 표현으로 V(Value), K(Key) 등이 많이 쓰인다고한다.


조금만 더 나아가보자.
지금은 T라는 타입이 너무 광번위 하여
다른 개발자가 Vehicle이 아닌 인스턴스를 넘길 위험이 존재해 보인다.

function doPreRun<T extends Vehicle>(vehicle: T): T {
  vehicle.run(30);
  return vehicle;
}

const genesis = new Car();
genesis.changeWheel(3); // ok

doPreRun(genesis);
genesis.changeWheel(4); // ok

이렇게
Vehicle을 확장(상속)하여 구현한 타입만을
허용하도록 수정할 수 있다.

제네릭을 더욱 유용하게 쓰기위해
constrains라는 것에 대해 알아볼것이다.
constrains는 제네릭에 조건을 거는것이다

const obj1 = {
  name: 'mocar',
  age: 31,
};

const obj2 = {
  hasPen: true,
  hasNote: false,
};

const obj3 = {
  cash: 3000,
  debt: 1000000,
};

const getValue<T, K extends keyof T> = (obj: T, key: K): T[K] => {
  return obj[key];
}

어떤가
알고보면 그렇게 어렵지않고
매우 유용한것이다.

728x90
반응형

'개발, 코딩 > typescript' 카테고리의 다른 글

Typescript, "people.name!" - what is meaning?  (0) 2023.06.05
optional과 undefined의 차이  (0) 2022.10.26
typescript, 타입 소개  (0) 2022.10.26
728x90

함수형 프로그래밍, 방어적 프로그래밍 등

다양한 영역에 걸쳐서

순수함수를 작성할 것을 강조한다.

 

순수함수란 무엇인가?

const total = sum(2, 8);

function sum(a, b) {
  return a + b;
}

여기 sum이라는 함수처럼

부수효과가 없는 함수 

즉, 어떤 함수에 동일한 인자를 주었을 때 항상 같은 값을 리턴하는 함수

 

부수효과?

그것의 의미는 바로,

외부의 상태를 변경하는 것

또는 함수로 들어온 인자의 상태를 직접 변경하는 것

을 의미한다.

 

순수함수가 아닌 경우의 sum

const total = sum(2, 8);
let favoriteNumber = 4;

function bugSum(a, b) {
 const sum = a + b;
 favoriteNumber = sum;
 return sum + favoriteNubmer;
}

 

위와 같이 함수를 작성하면

언제 프로그래밍에 버그를 만들어낼지 모른다.

나 혼자 개발한다면

혼자 잘 주의해서 개발하면 괜찮지만

 

다른 개발자가

내 코드를 받아서 사용할때

부수효과를 만들수 있는 favoriteNumber를

직접 조작하는 경우 등

에러요인이 만들어 질 가능성이 존재한다.

 

순수함수를 작성하도록 노력하자!

728x90
반응형

'개발, 코딩' 카테고리의 다른 글

객체지향 프로그래밍 핵심 개념  (0) 2022.10.27
git 기본기_백과사전(2)  (0) 2022.10.26
git 기본기_백과사전 (1)  (0) 2022.10.24
git 협업하기 - 실무편  (0) 2022.10.23
Webpack 구성 이해하기  (0) 2022.10.04
728x90

명령형, 절차지향적 프로그래밍

앱을 구현하기위한 데이터와 함수로 구성됨
정의된 순서대로 함수가 구동하는 프로그래밍
구현을 위해서는 모든 코드를 이해해야하여
유지보수가 어렵고 에러찾기가 어렵다.


객체지향 프로그래밍

서로 관련있는 데이터와 함수를
여러가지 오브젝트(객체)로 구성하여
프로그래밍 해나가는 것.
문제가 생기면 관련된 오브젝트만 확인하면 되고,
기능을 추가한다면 새로운 오브젝트를 만들면 되어
유지보수가 쉬워진다.


오브젝트(객체)

데이터와 함수로 구성됨
하나의 객체로써 명사로 이름을 짓는다.
오브젝트 내 데이터는 fields/properties라고 부른다.
오브젝트 내 함수는 메소드라고 부른다.


클래스와 오브젝트

클래스는 오브젝트를 만드는 일종의 템플릿
템플릿(클래스)를 이용해 만든 객체가 오브젝트
이러한 객체를 클래스의 인스턴스라고 부른다.


객체지향 프로그래밍의 원칙

캡슐화 / 추상화 / 상속 / 다형성 이 4가지를
객체지향 프로그래밍의 4원칙 이라고 부른다.


캡슐화

여러 기능들 중 서로 연관성있는 기능들을
묶는것을 "캡슐화"

eg)
감기약 캡슐에 다양한 성분의 약이 있지만
캡슐로 감싸두고, 안에 무엇이 있는지 모르고 그냥 먹는것과 같음

eg)
우리가 고양이 내부의 상태를 직접 바꿀수 없다.
고양이와 놀아줌으로써 내부 상태를 바꿀수는 있다.

이렇듯 안에 있는 것은 직접 건드리지 않고,
외부에 공개된 기능을 통해 내부의 값을 변경하는 것
그리고 어떤것을 외부에 공개하고 공개 안할지 결정하는것

이러한 일련의 행위를 "캡슐화" 라고함
키워드: public / private / protected

멤버변수의 기본 상태: public
외부에 공개하고 싶지 않을때: private
외부에서는 접근 할수없지만 상속한 자식 클래스에서는 접근할수있게 해주는것: protected

추상화

내부의 복잡한 기능을 다 이해하지 않더라도
외부에서 내부가 어떻게 구현됐는지는 상관않고
외부에서 보이는 인터페이스 만으로 이용할 수 있는 것 다시 말하면,
우리가 자동차의 원리를 몰라도 엑셀과 브레이크만 알면 운전할수 있듯이 외부에서는 내부에 어떻게 구현됐는지 신경쓰지않고 인터페이스만을 통해 함수를 이용할 수 있도록 하는 것

추상화 전

type Animal = 'dog', 'cat', 'pig';
type PetSkill = 'give me hand', 'sit down', 'high five';

class Pet {
  private skills: PetSkill;
  
  cosntructor(public kind: Animal, public name: string) {
  }
  
  training(skill: PetSkill) {
    this.edu();
    this.charming();
    this.skills.push(skill);
  }
  
  charming() {
    ...
  }
  
  edu() {
    ...
  }
}



추상화 방법1 - 정보은닉

type Animal = 'dog', 'cat', 'pig';
type PetSkill = 'give me hand', 'sit down', 'high five';

class Pet {
  private skills: PetSkill;
  
  cosntructor(public kind: Animal, public name: string) {
  }
  
  training(skill: PetSkill) {
    this.edu();
    this.charming();
    this.skills.push(skill);
  }
  
  private charming() {
    ...
  }
  
  private edu() {
    ...
  }
}

const myPuppy = new Pet('dog', 'meongu');
myPuppy.training('give me hand');



추상화 방법2 - interface

type Animal = 'dog', 'cat', 'pig';
type PetSkill = 'give me hand', 'sit down', 'high five';

interface Pet {
  training(skill: PetSkill): void;
}

class FriendPet {
  private skills: PetSkill;
  
  cosntructor(public kind: Animal, public name: string) {
  }
  
  training(skill: PetSkill) {
    this.edu();
    this.charming();
    this.skills.push(skill);
  }
  
  charming() {
    ...
  }
  
  edu() {
    ...
  }
}

const myPuppy: Pet= new FriendPet('dog', 'meongu');
myPuppy.training('give me hand');



상속

상속을 이용하면 잘 정의해둔 클래스를 재사용하여 부모 클래스의 function, properties를 상속하여 새로운 클래스를 쉽게 만들어 낼 수있다.


다형성

상속을 받은 자식 클래스들은 자신이 무엇인지와 관계없이 부모 클래스의 function을 공통적으로 호출할 수 있다.

static

모든 인스턴스가 동일하게 가지는 멤버변수가 있다면 static을 붙여주자. 그러면 class레벨로 멤버변수가 변경되어, 매번 인스턴스를 만들때마다 메모리를 차지하지 않는다.

get/set

getter, setter를 활용하면
클래스 사용자는 멤버변수를 다루듯이
age를 쓸수있으면서, 내부적으로는 예외처리까지 할수있다.
이러한 큰 장점이 있어 많은 개발자들이 애용하고있다.
(어떤 개발자는 getter/setter가 몇몇 경우에 직관적이지 못하다 등의 이유로 쓰지 않는것을 권장하기도 한다.)

class Person {
  private nationalAge: number;
  constructor(private firstname: string, public lastname: string) {
  }
  
  get fullname(): string {
    return `${this.firstname}${this.lastname}`;
  }
  
  get age(): number {
    return age;
  }
  
  set age(num: number) {
    if (!num || typeof num !== number) {
      throw new Error('숫자를 넘기셔야지요!');
    }
    
    this.nationalAge = num;
  }
}

728x90
반응형

'개발, 코딩' 카테고리의 다른 글

순수함수 (pure function)  (0) 2022.11.06
git 기본기_백과사전(2)  (0) 2022.10.26
git 기본기_백과사전 (1)  (0) 2022.10.24
git 협업하기 - 실무편  (0) 2022.10.23
Webpack 구성 이해하기  (0) 2022.10.04
728x90

1. optional

function getName(first: string, last?: string): string {
  return first + last;
}

getName('lee'); // ok
getName('lee', undefined); // ok
getName('lee', 'webster'); // ok

 

2. undefined

function getName(first: string, last: string | undefined): string {
  return first + last;
}

getName('lee'); // error
getName('lee', undefined); // ok
getName('lee', 'webster'); // ok

 

위의 예시로 보아 알수있듯이

optional을 쓰지않고 undefined 를 쓰게되면

명시적으로 undefined로 선언해주어야만 한다.

728x90
반응형