비밀번호 테이블

  • "user" 부분을 따옴표 없이 했을 때 에러가 난다면 따옴표를 붙이고 해보는 것도 좋다.
  • 외래키는 부모테이블의 기본키로만 연결할 수 있고 아닐 경우 외래키 설정이 안 된다. 그 기본키의 컬럼타입과도 같아야한다.
  • ON DELETE CASCADE ON UPDATE CASCADE : 만약 이 조건을 지정하지 않으면 제약 검증을 실패할 경우 삭제 또는 수정이 되지 않는다. 부모 테이블에서 row 를 삭제/수정할 경우 연결된 자식 테이블의 row 가 함께 삭제/수정된다. 연결된 데이터를 한 번에 삭제/수정할 수 있어 데이터의 관리가 편리해지고 일관성을 유지할 수 있다.
CREATE TABLE password (
    password_id SERIAL PRIMARY KEY,
    user_no INTEGER UNIQUE NOT NULL,
    salt VARCHAR(128),
    CONSTRAINT password_fk FOREIGN KEY(user_no) REFERENCES "user"(user_no) ON DELETE CASCADE ON UPDATE CASCADE
);

 

테이블 수정하기 (ALTER)

  • 컬럼 타입 수정하기

ALTER TABLE profile ALTER COLUMN user_no TYPE INTEGER USING user_no::integer;

  • 컬럼 명 수정하기

ALTER TABLE table_name RENAME COLUMN column_name TO new_column_name;

  • 컬럼 추가하기

ALTER TABLE user ADD COLUMN user_name INTEGER NOT NULL UNIQUE;

  • 제약조건 추가하기
  • 외래키

ALTER TABLE child_table ADD CONSTRAINT constraint_name FOREIGN KEY (fk_columns) REFERENCES "parent_table" (parent_key_columns);

  • 기본키

ALTER TABLE 테이블명 ADD CONSTRAINT 제약조건명 PRIMARY KEY(컬럼명);

  • NULL ? NOT NULL ?

ALTER TABLE table_name ALTER COLUMN column_name [SET NOT NULL| DROP NOT NULL];

  • 테이블명 수정하기

ALTER TABLE table_name RENAME TO new_table_name;

 

출처

https://velog.io/@eensungkim/ON-DELETE-CASCADE-feat.-row-%ED%95%9C-%EB%B2%88%EC%97%90-%EC%A7%80%EC%9A%B0%EB%8A%94-%EB%B0%A9%EB%B2%95-TIL-78%EC%9D%BC%EC%B0%A8

http://www.gisdeveloper.co.kr/?p=11993

https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-alter-table/

PostgreSQL을 사용하여 비밀번호를 안전하게 저장하는 방법

1. PostgreSQL에서 pgcrypto확장 기능에는 비밀번호 해싱에 필요한 내장 확장 기능이 있습니다.

확장 프로그램을 활성화하십시오:

CREATE EXTENSION pgcrypto;

2. 데이터 삽입

INSERT INTO user_account (user_name, password_hash) 
VALUES ('user1', crypt('user1_password', gen_salt('md5'))) ;

설명)

get_salt(type) : type에 따라서 해시를 한다.

  • des- 데이터 암호화 표준(DES) 알고리즘용
  • xdes- 확장 DES 알고리즘의 경우
  • md5- MD5 메시지 다이제스트 알고리즘용
  • bf- Blowfish 알고리즘의 경우

crypt('비밀번호',해시함수) : '비밀번호'를 해시함수로 해싱해서 바꾼다.

 

비밀번호 확인하기

SELECT (password_hash = crypt('user1의 비밀번호 입력', password_hash)) 
AS password_match 
FROM user_account 
WHERE user_name = 'user1' ;

설명)

crypt('user1의 비밀번호 입력', password_hash) 

  • 비밀번호가 맞을 경우

  • 비밀번호가 틀릴 경우

 

  • 'user1의 비밀번호 입력'와 password_hash는 같은 해시값을 만든다.
    • 1번과 4번 같은 문자열에 대한 같은 타입의 해시인데도 값이 다르다.
    • 3번 이전에 2번을 했는데도 1번 해시값으로 검사했을 때 같다고 나온다.
    • 1번과 2번에서 다른 타입의 해시 알고리즘을 사용하여 다른 값이 나온다.
nodedb=# SELECT crypt('supersecurepassword', gen_salt('bf')) ;
                            crypt
--------------------------------------------------------------
 $2a$06$.OSDtWHWtAtNAnnIH/vz3.RfysAOn2DF.YU/fBFBqdXPPxvE/O2M.
(1개 행)


nodedb=# SELECT crypt('supersecurepassword', gen_salt('xdes')) ;
        crypt
----------------------
 _J9..V0Fk2jtgJXri9Cs
(1개 행)


nodedb=# SELECT crypt('supersecurepassword', '$2a$06$.OSDtWHWtAtNAnnIH/vz3.RfysAOn2DF.YU/fBFBqdXPPxvE/O2M.');
                            crypt
--------------------------------------------------------------
 $2a$06$.OSDtWHWtAtNAnnIH/vz3.RfysAOn2DF.YU/fBFBqdXPPxvE/O2M.
(1개 행)

nodedb=# SELECT crypt('supersecurepassword', gen_salt('bf')) ;
                          crypt
-------------------------------------------------------------
$2a$06$n9ZD0NkhjKL0tEOXjsAtoOBcZIHs9yxlxdZEqa7slBluyCMDd27/q

 

비밀번호 수정하기

UPDATE user_account 
SET password_hash = crypt('수정한 비밀번호 입력', gen_salt('md5')) 
WHERE user_name = 'user1' ;

 

'개발 > PostgreSQL' 카테고리의 다른 글

PostgreSQL 기초2  (0) 2023.08.02
PostgreSQL 기초 1  (0) 2023.07.28
[PostgreSQL] 1. 데이터베이스 회원가입과 로그인 테이블 만들기  (0) 2023.07.27

출처

https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-create-table/


새 테이블 만들기

CREATE TABLE [IF NOT EXISTS] table_name (
   column1 datatype(length) column_contraint,
   column2 datatype(length) column_contraint,
   table_constraints
);

[IF NOT EXISTS] 기존 테이블에 같은 이름의 테이블이 있으면 알림을 해주는 역할

 

제약조건

  • NOT NULL  – 열의 값이 NULL이 될 수 없도록 합니다.
  • UNIQUE – 동일한 테이블 내의 행 전체에서 고유한 열의 값을 보장합니다.
  • PRIMARY KEY – 기본 키 열은 테이블의 행을 고유하게 식별합니다. 테이블에는 기본 키가 하나만 있을 수 있습니다. 기본 키 제약 조건을 사용하면 테이블의 기본 키를 정의할 수 있습니다.
  • CHECK  CHECK제약 조건은 데이터가 부울 표현식을 충족해야 함을 보장합니다.
  • FOREIGN KEY – 테이블의 열 또는 열 그룹의 값이 다른 테이블의 열 또는 열 그룹에 있는지 확인합니다. 기본 키와 달리 테이블에는 많은 외래 키가 있을 수 있습니다.

테이블 만들기

CREATE TABLE user (
	user_no serial PRIMARY KEY,
	user_name VARCHAR ( 50 ) UNIQUE NOT NULL,
);

CREATE TABLE profile (
	profile_id serial PRIMARY KEY,
	user_no INTEGER UNIQUE NOT NULL,
	join_date DATE NOT NULL,
);

 

데이터베이스 부분 정리

 

1. postgreSQL 설치하기

https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

 

2. 회원가입과 로그인에 필요한 데이터베이스 테이블

https://rastalion.me/%ED%9A%8C%EC%9B%90-%EA%B0%80%EC%9E%85-%EB%B0%8F-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EC%9D%84-%EC%9C%84%ED%95%9C-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%84%A4%EA%B3%84/

위 링크에 나온 자료들을 참고하여 정리

3. 데이터베이스 접속하기

같이 설치된 SQL Shell (psql) 들어가서

enter -> enter -> enter -> enter -> 설치할 때 설정한 암호, enter

4. 새로운 데이터 베이스 생성

postgres=# create database nodedb;
postgres=# \c nodedb

5. 테이블 생성하기

https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-create-table/

 

 

 

'개발 > PostgreSQL' 카테고리의 다른 글

PostgreSQL 기초2  (0) 2023.08.02
[PostgreSQL] 2. 비밀번호 테이블 만들기  (0) 2023.08.02
PostgreSQL 기초 1  (0) 2023.07.28

백엔드 : express

프론트엔드 : react typescript, bootstrap

데이터베이스 : ??

 

프론트엔드 부분부터 설명!

 

1. 리액트 설치

npm install -g create-react-app

2. 리액트 + 타입스크립트 프로젝트 만들기

npx create-react-app [프로젝트 이름] --template typescript
cd [프로젝트 이름]

3. bootstrap 설치하기

npm install react-bootstrap bootstrap --save

 

4. src 폴더 정리 (정리가 안 되어 있기 때문에 정리해줌)

5. 회원가입 컴포넌트 만들기

  • components 폴더에 SignUp.tsx 파일 만들기
import React from 'react';

interface SignUpssProps {
  mark?: string;
};

const SignUps: React.FC<SignUpssProps> = ({ mark }) => {

    return (
        <div>
           
        </div>
    );
};

export default SignUps;
  • App.tsx에 컴포넌트 추가
    • interface에 옵션 형식 변수를 사용하면 prop 값을 넘겨주지 않아도 된다.
import React from 'react';
import './styles/App.css';
import SignUps from './component/SignUp'

function App() {
  return (
    <div className="App">
      <SignUps />
    </div>
  );
}

export default App;
  • 부트스트랩을 이용하여 회원가입 폼 작성
    • onchage를 사용하여 입력값이 바뀌었을 때 state변수를 바꿔준다.
  return (
        <div>
            <Form>
                <div className="mb-3">회원가입</div>
                <Form.Group as={Row} className="mb-3" controlId="formHorizontalEmail">
                    <Form.Label column sm={2}>
                        Email
                    </Form.Label>&nbsp;&nbsp;
                    <Form.Control type="email" placeholder="email" onChange={(e) => {setEmail(e.target.value)}}/>
                </Form.Group>

                <Form.Group as={Row} className="mb-3" controlId="formHorizontalEmail">
                    <Form.Label column sm={2}>
                        Name
                    </Form.Label>&nbsp;&nbsp;
                    <Form.Control type="name" placeholder="name" onChange={(e) => {setName(e.target.value)}}/>
                </Form.Group>

                <Form.Group as={Row} className="mb-3" controlId="formHorizontalEmail">
                    <Form.Label column sm={2}>
                        Password
                    </Form.Label>&nbsp;&nbsp;
                    <Form.Control type="password" placeholder="password" onChange={(e) => {setPassword(e.target.value)}}/>
                </Form.Group>

                <Form.Group as={Row} className="mb-3" controlId="formHorizontalEmail">
                    <Form.Label column sm={2}>
                        Confirm Password
                    </Form.Label>&nbsp;&nbsp;
                    <Form.Control type="password" placeholder="password" onChange={(e) => {setPasswordConfirm(e.target.value)}}/>
                </Form.Group>
               
                <Form.Group as={Row} className="mb-3" controlId="formHorizontalCheck">
                    <Col sm={{ span: 10, offset: 2 }}>
                        <Form.Check label="Remember me" onChange={(e) => {setCheck(e.target.checked)}}/>
                    </Col>
                </Form.Group>

                <Form.Group as={Row} className="mb-3">
                    <Col sm={{ span: 10, offset: 2 }}>
                        <Button
                        type="button"
                        onClick={submit}
                        >
                            Sign Up
                        </Button>
                    </Col>
                </Form.Group>
            </Form>
        </div>
    );
  • 필요한 state 변수 정의
  •  useState?
    • React Hook : 특별한 함수
    • state를 함수 컴포넌트 안에서 사용할 수 있게 해준다
    • useState는 클래스 컴포넌트의 this.state가 제공하는 기능과 똑같다. 일반적으로 일반 변수는 함수가 끝날 때 사라지지만, state 변수는 React에 의해 사라지지 않습니다.
import React, { useState } from 'react';
...
 
const SignUps: React.FC<SignUpssProps> = ({ mark }) => {
    const [email, setEmail] = useState("");
    const [name, setName] = useState("");
    const [password, setPassword] = useState("");
    const [passwordConfirm, setPasswordConfirm] = useState("");
    const [check, setCheck] = useState(false);
...
  • 간단하게 입력값이 채워져있는지 체크해준다
    const submit = () : void => {
        if ((email === "" ||
            name === "" ||
            password === "" ||
            passwordConfirm === "") ||
            check === false) {
            alert('check')
            return;
        }
        console.log(email, name, password, passwordConfirm, check);
    }

클래스

  • 클래스의 속성 및 메서드의 타입을 정의한다.
class Person {
    ssn: string;
    firstName: string;
    lastName: string;

    constructor(ssn: string, firstName: string, lastName: string) {
        this.ssn = ssn;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName(): string {
        return `${this.firstName} ${this.lastName}`;
    }
}

 

접근제한자 = 접근제어자 = Access Modifiers

private

  • 클래스 외부에서 private 속성 및 메서드에 접근하면 접근이 불가 에러가 난다.
 class Person {
    private ssn: string;
    private firstName: string;
    private lastName: string;

    constructor(ssn: string, firstName: string, lastName: string) {
        this.ssn = ssn;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName(): string {
        return `${this.firstName} ${this.lastName}`;
    }
}
 
let person = new Person('153-07-3130', 'John', 'Doe');
console.log(person.ssn); // only accessible within class

 

public

  • public 한정자를 사용하면 모든 위치에서 클래스 속성 및 메서드에 액세스할 수 있습니다. 
  • 속성 및 메서드에 대한 액세스 한정자를 지정하지 않으면 기본적으로 public 한정자를 사용합니다.

 

protected

  • protected는 동일한 클래스 및 하위 클래스 내에서 액세스를 허용합니다.

readonly

  • 속성을 불변으로 표시하려면 readonly 키워드를 사용합니다.
  • readonly 속성은 재할당이 안 된다.
  • 생성자에 인자로 readonly 속성을 정의하면 초기화를 따로 하지 않아도 된다.
class Person {
    constructor(readonly birthDate: Date) {
        this.birthDate = birthDate;
    }
}

let p = new Person(new Date());
console.log(p.birthDate);

p.birthDate = new Date(); // Cannot assign to 'birthDate' because it is a read-only property.

class Person2 {
    constructor(readonly birthDate: Date) { // 초기화를 따로 하지 않아도 됨
    }
}

let p2 = new Person2(new Date());
console.log(p2.birthDate);

readonly vs const

  readonly const
사용 클래스 속성 변수
초기화 같은 클래스의 선언 또는 생성자에서 선언문에서

 

상속

자식 클래스의 생성자는 'super()' 호출을 포함해야 한다.

부모 클래스의 메서드에 바로 접근 가능하다.

class Person {
    constructor(private firstName: string, private lastName: string) {
    }
    getFullName(): string {
        return `${this.firstName} ${this.lastName}`;
    }
    describe(): string {
        return `This is ${this.firstName} ${this.lastName}.`;
    }
}

let p = new Person('a','b');
console.log(p.getFullName());

class Employee extends Person {
    constructor(firstName: string, lastName: string, private jobTitle: string) {
      super(firstName,lastName);
    }
}

let e = new Employee('a','b','c');
console.log(p.describe());

 

메서드 재정의

  • super.methodInParentClass()
class Employee extends Person {
    constructor(
        firstName: string,
        lastName: string,
        private jobTitle: string) {

        super(firstName, lastName);
    }

    describe(): string {
        return super.describe() + ` I'm a ${this.jobTitle}.`;
    }
}

let employee = new Employee('John', 'Doe', 'Web Developer');
console.log(employee.describe()); // This is John Doe. I'm a Web Developer.

 

 

출처

https://yamoo9.gitbook.io/typescript

https://www.typescripttutorial.net/typescript-tutorial/typescript-interface/

https://joshua1988.github.io/ts/guide/interfaces.html

'개발 > Javascript(Typescript)' 카테고리의 다른 글

[디자인 패턴] 팩토리 패턴  (0) 2023.08.09
[디자인 패턴] 싱글톤  (0) 2023.08.08
타입스크립트 3 - 인터페이스  (0) 2023.07.20
타입스크립트 2 - 함수  (0) 2023.07.17
자바스크립트 this  (0) 2023.07.14

인터페이스

  • 인터페이스를 인자로 받아 사용할 때 항상 인터페이스의 속성 갯수와 인자로 받는 객체의 속성 갯수를 일치시키지 않아도 된다. 다시 말해, 인터페이스에 정의된 속성, 타입의 조건만 만족한다면 객체의 속성 갯수가 더 많아도 상관 없다는 의미입니다.
  • 인터페이스에 선언된 속성 순서를 지키지 않아도 됩니다.

옵션 속성

interface personAge {
  age: number;
  name: string;
}

function logAge(obj: personAge) {
  console.log(obj.age);
  console.log(obj.name);
}
let person = { age: 28 , hop: 89};
logAge(person); // ERROR: Argument of type '{ age: number; hop: number; }' is not assignable to parameter of type 'personAge'.   Property 'name' is missing in type '{ age: number; hop: number; }' but required in type 'personAge'.

만약에 name이 옵션 속성을 가지고 있다면?

interface personAge {
  age: number;
  name?: string;
}

logAge() 함수가 에러나지 않고

28

undefined

를 출력한다.

// Example
interface Person {
    firstName: string;
    middleName?: string;
    lastName: string;
}

function getFullName(person: Person) {
    if (person.middleName) {
        return `${person.firstName} ${person.middleName} ${person.lastName}`;
    }
    return `${person.firstName} ${person.lastName}`;
}

readonly 속성

  • 읽기 전용 속성은 인터페이스로 객체를 처음 생성할 때만 값을 할당하고 그 이후에는 변경할 수 없는 속성을 의미합니다.
interface CraftBeer {
    readonly brand: string;
}

let myBeer: CraftBeer = {
    brand: 'Belgian Monk'
};

myBeer.brand = 'Korean Carpenter'; // error: Cannot assign to 'brand' because it is a read-only property.

 

함수 타입

  • 인터페이스에 함수를 정의하고 변수에 이 인터페이스를 할당하면 함수를 만들 때 매개변수와 반환값의 타입을 정의하지 않아도 된다.
  • 매개변수의 이름이 달라도 가능하며 순서대로 매치가 된다.
interface login {
    (username: string, passwrod: string, id?: string): boolean;
  }
 
  let loginUser: login;
  loginUser = function(name, pw, id) {
    console.log('로그인 했습니다: '+ name);
    return true;
  }
 
  let loginUser2 = function(n: any,p: any,i: any): boolean {
      console.log(n,p,i);
      return true;
  }
 
  console.log(loginUser('a','b'));
  console.log(loginUser2('a','b','c'));

 

클래스 

  • 인터페이스는 클래스와 비슷한데, 클래스와 달리 정의만 할 뿐 실제 구현되지 않습니다. 즉, 어떠한 객체를 생성 했을 때 가져야 할 속성 또는 메서드를 정의한다고 보면 됩니다. (추상 클래스와 유사해보입니다)
  • Y9Button 클래스 안에서 ButtonInterface 인터페이스에 정의한 onClick()과 onInit()을 구현하지 않으면 에러가 난다.
interface ButtonInterface {
onInit():void;
onClick():void;
}

// 클래스 Y9Button 인터페이스 Button 확장
class Y9Button implements ButtonInterface {

width:number;
height:number;

constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
};

onClick() {
    console.log('click');
};

onInit() {
    console.log('init');
};

}

let button = new Y9Button(1,2);
button.onInit(); // "init"

 

인터페이스 확장

interface B {
    b(): void
}

interface C {
    c(): void
}

interface D extends B, C {
    d(): void
}

 

하이브리드 타입

interface CraftBeer {
    (beer: string): string;
    brand: string;
    brew(): void;
  }
 
  function myBeer(): CraftBeer {
    let my = (function(beer: string) {}) as CraftBeer;
    my.brand = 'Beer Kitchen';
    my.brew = function() {};
    return my;
  }
 
  let brewedBeer = myBeer();
  brewedBeer('My First Beer');
  brewedBeer.brand = 'Pangyo Craft';
  brewedBeer.brew();

 

출처 

https://yamoo9.gitbook.io/typescript

https://www.typescripttutorial.net/typescript-tutorial/typescript-interface/

https://joshua1988.github.io/ts/guide/interfaces.html

 

 

 

'개발 > Javascript(Typescript)' 카테고리의 다른 글

[디자인 패턴] 싱글톤  (0) 2023.08.08
타입스크립트 4 - 클래스  (0) 2023.07.21
타입스크립트 2 - 함수  (0) 2023.07.17
자바스크립트 this  (0) 2023.07.14
타입스크립트 1 - 기본 타입  (1) 2023.07.13

* 타입스크립트 플레이그라운드로 온라인에서 실행해볼 수 있다.

 

Optional Parameters

optional parameter가 undefined가 아닌지 확인한 후에 사용한다.

let printSomething1 = (a: number, b?: number): void => {
    if(typeof b !== undefined) console.log(a+b);
    else console.log(a);
};

printSomething1(1,2); // 3
printSomething1(1); // 1

Default Parameters

function applyDiscount1(price: number, discount: number = 0.05): number {
    return price * (1 - discount);
}
 
function applyDiscount2(price: any, discount = 0.05): number {
    return price * (1 - discount);
}

console.log(applyDiscount1(100)); // 95
console.log(applyDiscount2(100)); // 95

Rest Parameters

...numbers던 numbers던 배열을 전달하면 함수 내에서 배열로 사용할 수 있지만 함수를 호출할 때 매개변수를 쓰는 방식이 다르다.

function getTotal(first: number, ...numbers: number[]): void {
    let total = 0;
    numbers.forEach((num) => total += num);
    console.log(first + total);
}

const numbers : number[] = [1,2,3];

//getTotal(10,[1,2,3]); // Argument of type 'number[]' is not assignable to parameter of type 'number'.
getTotal(10,1,2,3); // 16
getTotal(10, ...numbers); // 16

function getTotal2(first: number, numbers: number[]): void {
    let total = 0;
    numbers.forEach((num) => total += num);
    console.log(first + total);
}

//getTotal2(10,...numbers); //A spread argument must either have a tuple type or be passed to a rest parameter.
getTotal2(10,numbers); //16

함수 오버로딩 Function Overloadings

  • TypeScript에서 함수 오버로딩을 사용하면 매개변수 유형과 함수 결과 사이의 관계를 설명할 수 있습니다.
  • function 키워드로만 함수 오버로딩을 할 수 있으며 arrow function으로는 오버로딩을 할 수 없다.

- 매개변수 개수가 같을 때

function add(a:any, b:any):any {} 이 함수에 두 개의 함수를 오버로딩한 것인데, 각 함수 오버로드는 add() 함수에서 지원하는 유형의 조합을 정의합니다. 매개변수와 매개변수가 반환하는 결과 사이의 매핑을 설명합니다.

function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: any, b: any): any {
   return a + b;
}

- 매개변수 개수가 다를 때

함수를 오버로드할 때 필요한 매개변수의 수가 동일해야 합니다. 오버로드에 다른 것보다 더 많은 매개 변수가 있는 경우 추가 매개 변수를 선택 사항으로 만들어야 합니다. 

마지막 매개변수인 c를 optional parameter로 만들어서 2~3개의 매개변수를 가진 함수로 만들고 매개변수가 2개인 함수와 3개인 함수를 오버로딩할 수 있게 됩니다.

 

sum과 sum2 함수는 완전히 같은 동작을 하지만 함수 오버로딩을 사용하면 더욱 정확히 매개변수와 반환값 관계를 설명할 수 있다.

function sum(a: number, b: number): number;
function sum(a: number, b: number, c: number): number;
function sum(a: number, b: number, c?: number): number {
    if (c) return a + b + c;
    return a + b;
}

function sum2(a: number, b: number, c?: number): number {
    if (c) return a + b + c;
    return a + b;
}

 

 

 

출처

https://www.typescripttutorial.net/typescript-tutorial/typescript-function-overloadings/

'개발 > Javascript(Typescript)' 카테고리의 다른 글

[디자인 패턴] 싱글톤  (0) 2023.08.08
타입스크립트 4 - 클래스  (0) 2023.07.21
타입스크립트 3 - 인터페이스  (0) 2023.07.20
자바스크립트 this  (0) 2023.07.14
타입스크립트 1 - 기본 타입  (1) 2023.07.13

this 키워드는 자바스크립트에서 다른 언어와 다르게 작동한다. strict mode일 때와 아닐 때도 차이가 있다.

bind() 메소드는 어떻게 그것을 호출했는지와 상관 없이 this 값을 설정할 수 있다. 그리고 화살표 함수는 this 바인딩을 제공하지 않는다.

 

전역 실행 맥락에서 this는 엄격 모드 여부에 관계 없이 전역 객체를 참조합니다.

웹브라우저에서 this는 window를 가리킵니다.

 함수

function f1() {
  return this;
}

// 브라우저
f1() === window; // true

// Node.js
f1() === global; // true

function f2(){
  "use strict"; // 엄격 모드
  return this;
}

f2() === undefined; // true

call(), apply()

// call 또는 apply의 첫 번째 인자로 객체가 전달될 수 있으며 this가 그 객체에 묶임
var obj = {a: 'Custom'};

// 변수를 선언하고 변수에 프로퍼티로 전역 window를 할당
var a = 'Global';

function whatsThis() {
  return this.a;  // 함수 호출 방식에 따라 값이 달라짐
}

whatsThis();          // this는 'Global'. 함수 내에서 설정되지 않았으므로 global/window 객체로 초기값을 설정한다.
whatsThis.call(obj);  // this는 'Custom'. 함수 내에서 obj로 설정한다.
whatsThis.apply(obj); // this는 'Custom'. 함수 내에서 obj로 설정한다.

function add(c, d) {
  return this.a + this.b + c + d;
}

var o = {a: 1, b: 3};

// 첫 번째 인자는 'this'로 사용할 객체이고,
// 이어지는 인자들은 함수 호출에서 인수로 전달된다.
add.call(o, 5, 7); // 16

// 첫 번째 인자는 'this'로 사용할 객체이고,
// 두 번째 인자는 함수 호출에서 인수로 사용될 멤버들이 위치한 배열이다.
add.apply(o, [10, 20]); // 34

비엄격 모드에서 this로 전달된 값이 객체가 아닌 경우, call apply는 이를 객체로 변환하기 위한 시도를 합니다. 

null undefined 값은 전역 객체가 됩니다. 

7이나 'foo'와 같은 원시값은 관련된 생성자를 사용해 객체로 변환된다.

function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7);     // [object Number]
bar.call('foo'); // [object String]
bar.call(undefined); // [object global]

bind()

f.bind(someObject)를 호출하면 this는 원본 함수를 가진 새로운 함수를 생성합니다. 새 함수의 this는 호출 방식과 상관없이 영구적으로 bind()의 첫 번째 매개변수로 고정됩니다.

function f() {
  return this.a;
}

var g = f.bind({a: 'azerty'});
console.log(g()); // azerty

var h = f.bind({a: 'yoo'}); // bind는 한 번만 동작함!
console.log(h()); // yoo

var i = h.bind({a: 'fff'});
console.log(i()); // yoo

var o = {a: 37, f: f, g: g, h: h};
console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, yoo

화살표 함수

화살표 함수를 call(), bind(), apply()를 사용해 호출할 때 this의 값을 정해주더라도 무시합니다. 어떤 방법을 사용하든 함수 this는 생성 시점의 것으로 설정됩니다. 사용할 매개변수를 정해주는 건 문제 없지만, 첫 번째 매개변수(thisArg)는 null을 지정해야 합니다.

 

객체의 메소드

함수가 정의된 방법이나 위치에 전혀 영향을 받지 않는 것에 유의해라.

아래에서 independent 함수가 나중에 객체에 포함되어도 this가 그 객체를 가리키며 객체안의 객체에 포함되면 객체안의 객체를 가리킨다.

const test = {
  prop: 42,
  func: function() {
    return prop; // 그냥 접근 불가능, test.prop 또는 this.prop으로 접근 가능하다.
  },
};

console.log(test.func());


var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37


o.b = {g: independent, prop: 42};
console.log(o.b.g()); // logs 42

객체의 프로토타입 체인에서의 this

함수 f 는 p 의 메소드로서 호출된 이후로, this 는 p 를 나타낸다. 이것은 JavaScript 의 프로토타입 상속의 흥미로운 기능이다.

var o = {
  f:function() { return this.a + this.b; }
};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5

DOM 이벤트 처리기

함수를 이벤트 처리기로 사용하면 this는 이벤트를 발사한 요소로 설정됩니다. 일부 브라우저는 addEventListener() 외의 다른 방법으로 추가한 처리기에 대해선 이 규칙을 따르지 않습니다.

 

인라인 이벤트 핸들러

두번째 경우에 this는 window를 가리킨다. 첫번째 경우에 올바르게 현재 버튼을 가리킨다.

<button onclick="alert(this.tagName.toLowerCase());">
  this 표시
</button>

<button onclick="alert((function() { return this; })());">
  내부 this 표시
</button>

 

다음~

생성자, 접근자, 설정자~

 

출처

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

'개발 > Javascript(Typescript)' 카테고리의 다른 글

[디자인 패턴] 싱글톤  (0) 2023.08.08
타입스크립트 4 - 클래스  (0) 2023.07.21
타입스크립트 3 - 인터페이스  (0) 2023.07.20
타입스크립트 2 - 함수  (0) 2023.07.17
타입스크립트 1 - 기본 타입  (1) 2023.07.13

기본 타입

Boolean Number String Object Array Tuple
Enum Any Void Null Undefined Never

 

let str: string = 'hi';
let num: number = 5;
let isBool: boolean = false;

let arr1: number[] = [1,2,3];
let arr2: Array<number> = [1,2,3];

let tup: [string, number] = ['a',1]; // tuple: 배열의 길이는 고정, 각 요소의 타입이 지정되어 있는 배열

let every: any = "hi";

let printSomething = (a: number, b: number): void => {
    console.log(a+b);
};

 

Enum

TypeScript 열거형은 상수 값의 그룹입니다. 기본적으로 0부터 시작합니다.

enum Color {Red = 1, Green, Blue}

let c: Color = Color.Green;
console.log(c); // 2

let d: string = Color[0];
let e: string = Color[2];
console.log(d); // undefined
console.log(e); // "Green"

 

Never 

타입스크립트에서 never 타입은 값의 공집합이다. 집합에 어떤 값도 없기 때문에, never 타입은 any 타입의 값을 포함해 어떤 값도 가질 수 없다. 그래서 never 타입은 때때로 점유할 수 없는 또는 바닥 타입이라고 불린다.

숫자 체계에 아무것도 없는 양을 나타내는 0처럼 문자 체계에도 불가능을 나타내는 타입이 필요하다. 

  • 절대 발생할 수 없는 타입을 나타냄
  • 종료되지 않는 함수
  • 함수의 끝에 절대 도달하지 않는다는 의미
  • never는 함수 표현식이나 화살표 함수 표현식에서 항상 오류를 발생시키거나 절대 반환하지 않는 반환 타입으로 쓰인다.
  • 변수 또한 타입 가드에 의해 아무 타입도 얻지 못하게 좁혀지면 never 타입을 얻게 될 수 있다.
// never를 반환하는 함수는 함수의 마지막에 도달할 수 없다.
function error(message: string): never {
    throw new Error(message);
}
 
// 반환 타입이 never로 추론된다.
function fail() {
    return error("Something failed");
}
 
// never를 반환하는 함수는 함수의 마지막에 도달할 수 없다.
// break를 사용하면 error 발생
function infiniteLoop(): never {
    while (true) {
    }
}

 

null , undefined

// 이 밖에 이 변수들에 할당할 수 있는 값이 없습니다!
let u: undefined = undefined;
let n: null = null;

 

연산자를 이용한 타입 정의

  • Union Type

유니온 타입(Union Type)이란 자바스크립트의 OR 연산자(||)와 같이 A이거나 B이다 라는 의미의 타입입니다.

* 타입스크립트 관점에서는 introduce() 함수를 호출하는 시점에 Person 타입이 올지 Developer 타입이 올지 알 수가 없기 때문에 어느 타입이 들어오든 간에 오류가 안 나는 방향으로 타입을 추론하게 됩니다. 기본적으로는 Person Developer 두 타입에 공통적으로 들어있는 속성인 name만 접근할 수 있게 됩니다.

// any를 사용하는 경우
function getAge1(age: any) {
    age.toFixed(); // 에러 발생, age의 타입이 any로 추론되기 때문에 숫자 관련된 API를 작성할 때 코드가 자동 완성되지 않는다.
    return age;
  }
 
// 유니온 타입을 사용하는 경우
function getAge2(age: number | string) {
    if (typeof age === 'number') {
        age.toFixed(); // 정상 동작, age의 타입이 `number`로 추론되기 때문에 숫자 관련된 API를 쉽게 자동완성 할 수 있다.
        return age;
    }
    if (typeof age === 'string') {
        return age;
    }
    return new TypeError('age must be number or string');
}
// 주의
interface Person {
    name: string;
    age: number;
  }
interface Developer {
    name: string;
    skill: string;
}
function introduce(someone: Person | Developer) {
    someone.name; // O 정상 동작
    someone.age; // X 타입 오류
    someone.skill; // X 타입 오류
}
  • Intersection Type

여러 타입을 모두 만족하는 하나의 타입을 의미합니다. 

interface Person {
    name: string;
    age: number;
  }
interface Developer {
    name: string;
    skill: number;
}
type Capt = Person & Developer;

/* Capt
{
    name: string;
    age: number;
    skill: string;
}*/

 

 

출처

https://lakelouise.tistory.com/178

https://joshua1988.github.io/ts/guide/basic-types.html#void

https://ui.toast.com/posts/ko_20220323

'개발 > Javascript(Typescript)' 카테고리의 다른 글

[디자인 패턴] 싱글톤  (0) 2023.08.08
타입스크립트 4 - 클래스  (0) 2023.07.21
타입스크립트 3 - 인터페이스  (0) 2023.07.20
타입스크립트 2 - 함수  (0) 2023.07.17
자바스크립트 this  (0) 2023.07.14

+ Recent posts