React 순수 함수와 커링 기법

|

에듀캐스트 장고&리액트 강의를 듣고 정리하는 글이다.

리액트는 함수형 프로그래밍을 적극 활용

  • 컴포넌트의 많은 루틴을 순수 함수로서 작성하기를 요구
    • 상탯값/속성값이 같으면, 항상 같은 값을 반환해야 한다.
    • 다른 Side effects를 발생시키지 않아야 한다. (HTTP 요청, 데이터 저장, 쿠키 조작 등)
  • 컴포넌트의 상탯값은 불변 객체(Immutable Object)로 관리해야만 한다.
    • 수정할 때에는 기존 값을 변경하는 것이 아니라, 같은 이름의 새로운 객체를 생성한다.

이를 통해, UI 개발의 복잡도를 낮추고, 버그 활생 확률도 줄인다.

순수 함수

하나 이상의 인자를 받고, 인자를 변경하지 않고, 참조하여 새로운 값을 반환. Side Effects가 없도록 구성한다.

let tom = {
  name: "Tom",
  canRun: false
};

// 값은 변경해버림.
function not_pure_fn(){
  tom.canRun = true;
}

// 새로운 객체를 만들고 값은 변
function pure_fn1(person){
  return {
    ...person,
    canRun: true
  };
}

const pure_fn2 = (person) => ({
  ...person,
  canRun: true
});

순수 함수를 활용한 데이터 변환

reduce, filter, map, join 등이 있다.

  • 자바스크립트 ```javascript const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; const number = numbers.reduce((acc, n) => acc + n, 0); // 배열 합 구하기 console.log(number);

const even_numbers = numbers.filter(i => i % 2 ==0); consoel.log(even_numbers);


- 파이썬
```python
from functools import reduce

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
number = reduce(lambda acc, n: acc + n, numbers, 0)
print(number)

even_numbers = filter(lambda i: i % 2 == 0, numbers)
print(tuple(even_numbers))

커링 (Currying)

일부의 인자를 고정한 새로운 함수를 반환하는 함수를 만드는 기법. 파이썬의 데코레이터랑 비슷하다고 생각하면 된다.

  • 자바스크립트 ```javascript function userLogs(username){ function wrap(message){ console.log(${username} - ${message}); return wrap; } }

const log = userLogs(‘sjh’); log(‘Hello World’);

// #2 const userLogs = username => message => { console.log(${username} - ${message}); } const log = userLogs(‘sjh’); log(‘Hello World’); ```

React

|

에듀캐스트 장고&리액트 강의를 듣고 정리하는 글이다.

패키지 관리자

  • npm (node package manager): nodejs 기본 패키지 관리자
    • npm install –global 패키지명: 디폴트가 로컬에 설치되기에 전역 설치를 위해 global 옵션 사용(파이썬은 반대이며 가상환경으로 해결한다.)
    • npm install 패키지명
  • yarn: 페이스북 주도로 개발된 패키지 관리자 [설치] npm install –global yarn

yarn global add 패키지명 yarn add global 패키지명 -> global 이름의 패키지가 설치되는 것이니 조심하자 yarn add 패키지명 yarn add –dev 패키지명: 개발용으로 설치하고 싶을때 yarn add

이 실습에서는 yarn을 통해서 react를 설치해 볼 것이다.

[react 설치] 프로젝트 디렉토리를 만들 위치로 이동해서 다음과 같은 명령어를 입력해주자. yarn create react-app "프로젝트명"

시간이 좀 걸리니 찬찬히 기다려주면 완료된다.

완료가 되고 cd “프로젝트명”으로 들어가보면 git이 init 되어있다.

ES6 문법

  • let과 const: 이 타입이 생기기전에는 우리는 var로 변수를 선언해서 사용했을 것이다.
var name = 'hsj';
console.log(name);

이렇게 했을 시 문제 없이 출력이 될 것이다.

console.log(name);
var name = 'hsj';
console.log(name);

이렇게 하면 undefiend와 hsj가 출력이 될 것이다. 이렇게 되는 이유는 javascript는 호이스팅이라고 해서 선언한 변수명이 맨 위로 올라간다고 하는데, 이렇게 name은 참조하는 것이 없기 때문에 undefiend가 출력이 되는 것이다. ES6부터는 var대신 let을 사용하면 위의 혼란스러움을 해결할 수 있다. const는 상수값을 선언하는 것이기에 필히 선언할때 값을 입력해주자.

객체 복사

JS는 Object/Array에 대해서는 대입 시에 얕은 복사가 이루어 진다. 얕은 복사는 참조값이 같기에 어느 한쪽에서 수정하면 다른 변수로 출력해도 같은 값이 표시된다.

const obj1 = { value: 10};
const obj2 = obj1;
const obj3 = JSON.parse(JSON.stringify(obj1)); // 깊은 복사

obj1.value1 += 1;

console.log('obj11:', obj1); // 11
console.log('obj11:', obj2); // 11
console.log('obj11:', obj3); // 10

여러 줄 선언, 표현식

백쿼터( ` )를 사용해서 여러줄을 표현할 수 있고 ${}를 사용해서 변수나 함수 등을 입력받을 수 있다..

const name = 'hsj';
const text = `
줄1
줄2
${name};
`

배열 비구조화 (Array Destructuring)

리액트에서 자주 쓰는 문법

let [name] = ["Tom", 10, "Seoul"]; // "Tom" 저장
let [,age,] = ["Tom", 10, "Seoul"]; // 10이 저장

let [name, age, region, height] = ["Tom", 10, "Seoul"] // height는 undefiend이 할당. 파이썬이었으면 ValueError 예외가 발생한다.
let [name, age, region, height=150] = ["Tom", 10, "Seoul"] // 디폴트값을 할당할 수 있다.

function get_default_height() {
  console.log("get_default_height() 호출")
  return 150;
}
let [name, age, region, height=get_default_height()] = ["Tom", 10, "Seoul"] // 실제 디폴트값 할당이 필요할 때 호출된다.

객체 비구조화 (Object Destructuring)

이것 또한 자주 쓰이는 문법이라 한다.

const tom = {
  name: "Tom",
  age: 10,
  region: "Seoul"
};
const {age, name, height} = tom; // 객체에서 있는 값 가져가고, 없으면 undefiend


const print_person1 = (person) => {
  console.log(person.name);
};

const print_person2 = ({name}) => {
  console.log(name);
};
print_person1(tom); // 이름 출력
print_person2(tom); // 마찬가지로 이름이 출력된다.

const people = [
  {name: 'Tom', age:10, region: 'Seoul'},
  {name: 'Steve', age:12, region: 'Pusan'}
];

for (const person of people){
  console.log(person.name, person.age);
}

for (const {name, age} of people){
  console.log(name, age);
}

const person = {
  name: 'Tom',
  age: 10,
  region: {
    country: '서울',
    postcode: '06222',
  }
};
const {name, region: {postcode}} = person;
console.log(name, postcode);

전개 연산자(Spread Operator)

파이썬의 *과 ** pack, unpack과 유사하다.

let [name, ...rest] = ["Tom", 10, "Seoul"]; // "Tom"을 제외하고 rest 배열에 할당

let names = ["Steve", "John"]
let students = ["Tom", ...names, ...names]; // names배열을 unpack

let printArgs = (...args) => {
  console.log(args);
}

// 리액트에서 정말 많이 사용된다고 한다.
let tom = {
  name: "Tom",
  age: 10,
  region: "Seoul"
};

// 속성명이 중복되는 경우, 마지막 값이 남는다.
let steve = {
  ...tom,
  name: "Steve"
}

const numbers = [1, 3, 5, 7, 9];
Math.max(numbers) // Nan 출력, max함수는 인자들을 받아서 사용하기 때문에 아래처럼 풀어줘야 한다.
Math.max(...numbers)

함수 / Default Parameters

모든 타입의 값들을 디폴트 파라미터로 지정할 수 있다.

  • 파이썬에서는 Immutable 값들만 디폴트 파라미터로 지정 가능 ```javascript function hello(name=”Tom”, age=10){ console.log(나는 ${name}. ${age}살이다.); }

const get_default_age = () => 10 // () 인자, => 이후는 return

function hello(name=”Tom”, age=get_default_age()){ console.log(나는 ${name}. ${age}살이다.); } console.log(hello(“Steve”))


### 함수 / Named Parameters
객체 비구조화를 활용한다.
```javascript
function print_person1(name, age, region){
  console.log('1>', name, age, region);
}
print_person1('Tom', 10, 'Seoul') // 순서대로 인자에 들어간다.

// 아래 방식을 많이 사용한다.
function print_person2({name, age, region}) {
  console.log('2>', name, age, region);
}

print_person2({name: 'Tom', age: 10, region: 'Seoul'})

함수 / Arrow function

return을 사용하지 않아도, 계산된 값을 반환한다. 인자가 1개일 경우, 소괄호 생략 가능하다.

var hello1 = function(name, age){
  return `Hello. I'm ${name}. ${age}`;
};
const fn = x => x+ 10;
let hello2 = (name, age) => `Hello ${name} ${age}` // 중괄호 없고, return 값 없이도 사용할 수 있다.

let hello3 = (name, age) => {
  return `Hello ${name} ${age}`;
};

this와 arguments를 바인딩 하지 않는다. Arrow 함수를 사용하면 this의 값이 바뀌지 않는다.


var tom = {
  name: "Tom",
  print1: function() {
    console.log(`[print1-1] name: ${this.name}`);
    (function(){
      console.log(`[print1-2] name: ${this.name}`);
    })();
  },
  print2: function(){
    console.log(`[print2-1] name : ${this.name}`);
    var me = this;
    (function(){
      console.log(`[print2-2] name : ${me.name}`);
    })();
  },
  print3: function() {
    console.log(`[print3-1] name : ${this.name}`);
    (()=>{
      console.log(`print[3-2] name : ${this.name}`);
    })();
  }
}

함수의 다양한 형태

const mysum1 = (x, y) => x + y;
const mysum2 = (x, y) => {x, y} // 객체 생성 key, value가 같으면 이처럼 사용해도 된다.
const mysum3 = (x, y) => ({x: x, y: y});
const mysum4 = (x, y) => {
  return {x; x, y: y};
}

const mysum5 = function(x, y){
  return {x: x, y: y};
}
function mysum6(x, y){
  return {x: x, y: y};
}

콜백지옥

콜백함수는 요즘 지양함. Promise, async/await 사용

클래스와 상속

  • ES6 이전 ```javascript function Person(name, age){ this.name = name; this.age = age; } Person.prototype.print = function(){ console.log(this.name + “, “ + this.age); }

var tom = new Person(“Tom”, 10); tom.print();


- ES6 이후
```javascript
// 문법이 다를 뿐, 여전히 prototpye을 사용한다.
class Person {
  constructor(name, age){
    this.name = name;
    this.age = age;
  }
  print() {
    console.log(this.name + ", " + this.age);
  }
}
const tom = new Person("Tom", 10);
tom.print()

// 상속
class Developer extends Person {
  constructor(name, age, field){
    super(name, age);
    this.field = field;
  }
  print() {
    super.print();
    console.log(`field : ${this.field}`);
  }
}

모듈 시스템

  • 예전 웹 상의 자바스크립트에서는 script 태그를 통해서만 로딩했다.
    • 모두 전역 객체에 바인딩
  • 지금은 2가지 모듈 시스템이 있다.
    • CommonJS Module : nodejs에서 주로 활용 ```javascript // my_module.js const name = “tom”; const age = 10;

    module.exports = { name, age, region: “Seoul” };

    // in_nodejs.js const my_module = require(“./my_module”); // require 문법을 사용 console.log(name);

    - ES6 Module : 리액트에서 주로 활용
    ```javascript
    // my_module_es6.js
    const name = "tom";
    const age = 10;
    
    export default {
      name,
      age,
      region: "Seoul"
    };
    
    export {
      name,
    };
    
    // in_react.js
    import my_module from "./my_module" // default를 참조
    import { name } from "./my_module" // export를 참조
    

고차 함수 (Hig Order Function)

함수를 인자로 받거나 반환이 가능하고, 다른 함수를 조작하는 함수. 함수/클래스 역시 모두 객체이다.

// #1
function base_10(fn){
  function wrap(x, y){
    return fn(x, y) + 10;
  }
  return wrap;
}

function mysum(x, y){
  return x + y;
}

mysum = base_10(mysum);
console.log(mysum(1, 2));

// #2
const base_10 = fn => (x, y) => fn(x, y) + 10;

let mysum = (x, y) => x + y;
mysum = base_10(mysum);

console.log(mysum(1, 2));
def base_10(fn):
  def wrapper(x, y):
    return fn(x, y) + 10
  return wrapper

def mysum(x, y):
  return x + y

mysum = base_10(mysum)
print(mysum(1, 2))

200803-200809_TIL

|

8월 3일 (월)

  • 에듀캐스트 장고&리액트 강의를 수강중이다. 얼른 다 들어야겠다.

8월 6일 (목)

  • 지금은 리액트 강의를 수강하고 있다. 리액트도 알아야 할게 참 많은거 같다.

8월 7일 (금)

  • 리액트 강의를 계속 수강중이다. 자바스크립트도 계속 병행해보면서 이해해야 할거 같다..!

8월 8일 (토)

  • 친구와 작업중인 홈페이지 스타일을 위해서 CSS 강의를 봐보았다.

200727-200802_TIL

|

7월 27일 (월)

  • 친구가 부탁받은 사이트의 레이아웃을 꾸며보았다. 해당 사이트는 php로 구성되어있는데, 장고가 써왔던 내가 보았을 때, 템플릿과 로직이 같이 있으니까 정말 어지러웠다. 장고가 정말 보기에 깔끔한 프레임워크임을 느끼게 되었다. 어쨌건 CSS 노가다를 했는데, 디자인도 정말 어려운 영역임을 느끼게 되었다.

7월 28일 (화)

  • 오늘은 에듀캐스트의 장고 강의를 계속 수강했다. 얼른 다 듣고, 내가 했던 것들에 반영해볼 수 있도록 해야겠다.

7월 29일 (수)

  • git에 대해서 알아보았다. merge는 쉽게 되던데, rebase는 쉽게 안되더라. 더 알아봐야겠다.

7월 30일~ 8월2일(일)

  • 가족 휴가로 영덕을 갔다. 간만에 친척들도 보고 낚시하고 잘 쉬었다.

200720-200726_TIL

|

7월 20일 (월)

  • 면접 본 데서 빠르게 결과를 알려줬다. 예상대로 불합격 통보 받았다.. 하지만 면접을 봐봤다는 점에 의의를 두고, 더 열심히 공부해서 새로 도전해봐야겠다.
  • 책으로만은 아직 실력이 많이 부족함을 느끼기에 에듀캐스트에서 강의를 듣기로 결심했다! 백수에게 22만원은 큰 타격이지만 내 미래를 위한 투자니 과감히 결제했다. 가자!!
  • open .을 입력하면 현재 디렉토리를 열 수 있다.

7월 21일 (화)

  • 장고를 jupyter에서 사용하려면 아래와 같이 설정을 해주자. 세번째 줄은 python3버전에서 사용할 때, 비동기 지원을 위해 입력해줘야 한다고 한다. ```python import os os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘askcompany.settings’ os.environ[‘DJANGO_ALLOW_ASYNC_UNSAFE’] = ‘true’

import django django.setup() ```

  • 하루종일 강의만 들으면서 복습을 해보고 있다. 예전에 이해안갔던 것이 지금은 이해가 가는게 신기하다. 더 열심히 하자.

7월 24일 (금)

  • git 파일을 관리할 때, 디렉토리가 비어있으면 안된다. git은 파일을 관리하지 디렉토리를 관리하는 것이 아니기 때문이다.

7월 25일 (토)

  • 친구와 홈페이지를 맡아 디자인해보기로 해보았다. 나는 지금까지 백엔드로만 공부하긴 했지만.. 일단 도전!!