0%

계산기

배울 기술

  • UIStackView
  • IBDesignables
  • IBInspectable

UIStackView

열 또는 행에 View 들의 묶음을 배치할 수 있는 간소화된 인터페이스

  • axis : 방향 결정
  • distribution : 어떻게 분배할지
    • Fill : 채우게 ,huging, compresion 값 에따라 달라짐
    • Fill Equally : 요소 크기를 같게 채우기
    • Fill Proportionally : 비율에 맞게
    • Equal Spacing : 각각 간격이 같게
    • Eual Centering : 각 서브 뷰들의 센터의 간격을 동일하게
  • alignment : 주축 반대축에 대하여
    • fill
    • leading
    • top
    • first baseline
    • center
    • trailing
    • bottom
    • last baseline
  • spacing : subview 들의 간격 조정

IBInspectable, IBDesignables

UIView안에 요소를 를 상속하는 클래스를 만들어서 코드로 속성에 접근, 변경할 수 있다.

@IBInspectable 어노테이션을 붙히면 스토리 보드에서도 속성에 값을 변경할 수 있도록 할 수 있다.

@IBDesignable 어노테이션을 붙혀서 실시간으로 속성값 변화를 스토리보드에서 확인할 수 있다. 남용하게 되면 스토리 보드 열때마다 오래 걸릴수도 있다.

QuoteGenerator

명언 생성 앱

배울기술

  • Storyboard
  • AutoLayout
  • UILabel
  • UIButton

알아야 할 기본 개념

  • UIKit
  • UIViewController
  • AutoLayout
  • IBOutlet & IBAction

UIKit

Cocoa touch Framework → IOS Application framework (UIKit(사용자 인이벤트 처리등 UI관련), Foundation(자료구조, 네트워크 등등..), CoreDate… etc )

  • 사용자 이벤트 처리
  • 뷰 관련
  • MVC 디자인 패턴을 따라 개발하는데 현실 UIKit 에서는 View와 Controller 가 깊게 연결되어 있어서 분리하기 어렵다

ViewController

UIView → 화면의 직사각형 영역

  • 앱의 근간을 이루는 객체로 모든 앱은 최소한 하나 이사의 뷰 컨트롤러를 가지고 있다.
  • 데이터 변화에 따라 view 업데이트, 상호작용, 리사이징, 다른 뷰 컨트롤러 들과 앱을 구성

AutoLayout

제약 조건을 이용해서 뷰의 위치를 지정하는 것 → 다양한 해상도 뷰의 맞게 UI 개발을 하기 위함

IBOulet & IBAction

storyboard 에 생성한 UIObject에 접근하여 컨트롤하기 위해서 변수에 바인딩 한것을 Outliet 변수라고 한다.

  • storage 에서 strong, week 은 메모리 회수 정책이다. strong 은 일단 참조가 되어 있다면 메모리를 헤제 하지 않지만, week 은 참조 되어 있더라도 해제 될 수 있다. strong은 메모리 누수 발생 여지가 있다.

Action 함수는 동작을 정의하는 함수로 UI와 동작을 연결하여 UIVewController 에서 사용할 수 있도록 해준다.

Argument , Action message 를 이벤트 핸들러인 sender를 설정한다.

Content Hugging, Compression Resistance

  • Content Hugging : 크기가 늘어나는데 저항하는 성질로서 높을수록 늘어나지 읂는다.
  • Compression Resistace : 크기가 줄어드는데 저항하는 성질로서 크기가 높을수록 줄어들지 않는다.

RTK Query

RTK Query 웹 애플리케이션에서 데이터를 로드하는 일반적인 경우를 단순화해서 데이터를 가져오거나 캐시할수 있는 도구이다. RTK의 createSlicecreateAsyncThunk 와 같은 RTK의 API를 활용하여 해당 기능을 구현한다.

store와 API Service 설정

API service 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Need to use the React-specific entry point to import createApi
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { Pokemon } from './types'

// Define a service using a base URL and expected endpoints
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query<Pokemon, string>({
query: (name) => `pokemon/${name}`,
}),
}),
})

// Export hooks for usage in functional components, which are
// auto-generated based on the defined endpoints
export const { useGetPokemonByNameQuery } = pokemonApi

RTK 쿼리를 사용하면 일반적으로 전체 API 정의를 한곳에서 정의해서 관심사를 모으고 추적하기 쉽도록 한다.

유지 보수하기 위해서 엔트포인트 별로 쿼리를 분리하고 싶을 수 도 있는데 그럴땐, create API 를 사용하여 base URL을 공통으로 갖고 endpoints 는 비어있는 함수로 정의하고 반환된 API에 injectEndpoints 를 사용하여 endpoint api 를 주입하는 방법으로 분리하여 관리 할 수 있다.

Add the service to your store

redux store에 reducer와 middleware 를 추가하고, Provider를 사용해 APP 에 store를 주입한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { configureStore } from '@reduxjs/toolkit'
// Or from '@reduxjs/toolkit/query/react'
import { setupListeners } from '@reduxjs/toolkit/query'
import { pokemonApi } from './services/pokemon'

export const store = configureStore({
reducer: {
// Add the generated reducer as a specific top-level slice
[pokemonApi.reducerPath]: pokemonApi.reducer,
},
// Adding the api middleware enables caching, invalidation, polling,
// and other useful features of `rtk-query`.
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(pokemonApi.middleware),
})

// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch)

Use the query in a component

useGetPokemonByNameQuery 를 사용하여 데이터의 상태와 데이터를 가져온다. isLoading , isFetching , isSuccess , isError 와 같은 데이터 상태에 bool 도 제공한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import * as React from 'react'
import { useGetPokemonByNameQuery } from './services/pokemon'

export default function App() {
// Using a query hook automatically fetches data and returns query values
const { data, error, isLoading } = useGetPokemonByNameQuery('bulbasaur')
// Individual hooks are also accessible under the generated endpoints:
// const { data, error, isLoading } = pokemonApi.endpoints.getPokemonByName.useQuery('bulbasaur')

return (
<div className="App">
{error ? (
<>Oh no, there was an error</>
) : isLoading ? (
<>Loading...</>
) : data ? (
<>
<h3>{data.species.name}</h3>
<img src={data.sprites.front_shiny} alt={data.species.name} />
</>
) : null}
</div>
)
}

Redux

Rules of Reducers

  • state와 action을 통해서만 새로운 state가 계산되어야 함
  • state는 불변성을 지키면서 업데이트해야함.
  • 순수 함수 여야 함. random이나, asycLogic 등 side effects를 발생시키지 말아야 함.

이렇게 해야하는 이유?

  • state 와 action만으로 새로운 상태가 나오기 때문에 예측하기 쉽고, test 하기 쉽다.
  • 그렇지 않다면 어떻게 동작하는지 어떤 결과를 리턴하는지 알 수 없게 된다.
  • Redux가 올바르게 동작하지 못하게 하여서 bug를 유발한다.

Redux Toolkit에 createSlice 는 내부적으로 immer 라이브러리를 사용하여 immutable 하게 업데이트 하는 작업을 편하게 해준다. immerstateProxy 객체로 감싸고 변경사항이 있을대 비교하여 immutablestate 를 반환할수 있게 해준다.

→ 내부적으로 immer 를 사용하는 createSlicecreateReducer 를 사용하지 않는다면 immutable 하게 객체를 업데이트해야 한다.

Writing Async Logic with Thunks

RTK 는 내부적으로 redux-thunk 를 포함한다. createAsyncThunk 를 사용하면 Thunk를 쉽게 생성할 수 있다.

보안

  • Local Storage 정보는 XSS Attack 으로 도난 당할 수 있다.

XSS Attack 이란?

(Cross-Site Scripting Attack)

  • injection 관련 보안 이슈
  • 사용자가 신뢰하는 웹사이트에 스크립트를 주입해서 정보를 빼내거나 의도치 않은 작업을 하는 것, 웹 어플리케이션, 통상적으로 form 안에 input을 통해서 주입한다.
  • 헤커가 자바스크립트를 준비해서 웹사이트에 숨겨 놓는다.
  • 사용자가 이용하다가 숨겨진 스크립트에 의해 쿠키나 localStorage에 정보를 attacker 에게 전달할수 있다.
  • 민감한 정보를 localStorage에 저장하면 안됨..
  • 해결 방법
    • 메모리 상의 저장 → 브라우저 나가면 로그인 유지 되지 않는다거나 사용자 경험이 떨어짐
    • 쿠키를 사용하는데, http only 옵션을 넣어줌.→ 브라우저만 쿠키 정보를 읽을 수 있도록 함. 자바스크립트로 읽을 수 없게함. 만료 기간을 설정하면 만료 전까진 쿠키에 유지 됨.
      • 모바일 클라이언트엔 적용할 수 없음.
      • CSRF attack에는 취약함.
  • 서버에서는 cors 에 creadentials를 true (Access-Control-Allow-Credentials)로 설정하고 http only로 쿠키를 보내주어야 한다.
  • 헤더에 cookie로 넣어버리면? 모바일 클라이언트는 문제가 생김, 일단은 그대로 바디로 token을 넘겨주기도 하고, header로 설정하기도 해야 함.
  • 서버에 auth 부분에서는 Cookie 도 확인하고 Header도 확인해야 함. 모바일 클라이언트도 있기 때문에

211223

리엑트 쿼리

  • 리엑트 쿼리 : useQuery 데이터의 캐시 키와 Promise 를 반환하는 함수를 기반으로 데이터의 로딩 결과 오류 상태를 관리해 준다.
  • Promise 를 반환하는 함수의 매개변수를 캐시키에 포함시킨다.
  • stale time 과 cache time
    • stale time : 신선하지 않다는 의미 → 데이터가 더이상 유효하지 않다 → 재요청 , 기본값은 0 인데 불러온 시점부터 유효하지 않게 되어서 재요청이 필요한 상태가 된다. 재용청 기회가 주어지는 시점은 똑같은 캐시 키를 사용하는 useQuery 를 사용하는 컴포넌트가 마운트될 때이다.
    • useQuery Hook을 사용하는 컴포넌트가 언마운트되고 나서 해당 데이터를 얼마 동안 유지할지에 대한 설정. 기본값은 5분이다. 그래서 만약에 컴포넌트가 언마운트 되고 5분이 안되서 다시 마운트 되었다면 isLoading이 true가 되지 않고 이전에 data 값을 사용하게 된다. 그리고 staelTime 에 따라 해당 데이터가 유효하다면 재요청 하지 않고 유효하지 않다면 재요청 한다.
    • 기본 옵션의 경우 useQuery를 사용하는 어떤 컴포넌트가 마운트 되고, 처음 마운트된 컴포넌트가 5분이 되지 않은 상태에서 다른 컴포넌트에서 사용한다면 일단 data를 이전 데이터에서 가져다가 쓰고, 유효하지 않기 때문에 재요청을 실시해서 대체한다. 만약 5분이 지났다면 data 가 undefined 이고 새로 요청을 실시한다.
  • axios 인스턴스를 사용하는 이유?
    1. baseURL을 설정하기 위해서
    2. 공통 헤더를 인스턴에 넣어서 요청할 수 있다.
  • react-query를 프로젝트에서 사용할 때에는 QueryClientProvider를 최상단에서 감싸줘야 한다. 캐시를 관리할때 사용하는 QueryClient 인스턴스를 자식 컴포넌트에서 사용할수 있게 해주기 때문이다.
  • 데이터를 생성,수정, 삭제 할때는 useMutation 이라는 hook 을 사용한다. → useMutation 은 특정 함수에서 우리가 원하는 때에 직접 요청을 시작하는 형태로 작동한다.
  • refetch 를 이용하는 방법은 구현하기 쉽지만 모든 페이지에 대해서 재용청 하는 문제가 있다. → useInfiniteQuery 는 반대 방향으로도 페이지네이션 할 수 있는데 그때 사용하는 getPreviousPageParam 을 옵션 설정하여 구현 최적화할 수 있다.

Run your tests

Intro

Node.js 와 Mocha frameworks 를 사용하여 Docker 안에서 Unit test 를 진행하는 방법을 알아본다.

Create a test

./test 폴더를 application 안에서 생성한다

1
$ mkdir -p test

test.js 파일을 ./test 폴더 안에 생성한다.

1
2
3
4
5
6
7
8
var assert = require('assert');
describe('Array', function() {
describe('#indexOf()', function() {
it('should return -1 when the value is not present', function() {
assert.equal([1, 2, 3].indexOf(4), -1);
});
});
});

Running locally and testing the application

Docker image 를 컨테이너 안에서 build 하고 실행시킨다.

1
$ docker-compose -f docker-compose.dev.yml up --build

Install Mocha

개발 의존성으로 Mocha 를 설치한다.

1
$ npm install --save-dev mocha

Update package.json and Dockerfile to run tests

컨테이너 안에서 test 가 진행될 수 있도록 package.json을 수정하자. 위에서 똑같은 docker run command를 실행시킬건데 이번에는 package.json 에 test 스크립트를 추가하고 test가 실행 될 수 있도록 한다.

1
2
3
4
5
6
{
"script": {
"test" : "mocha ./**/*.js",
"start" : "nodemon --inspect=0.0.0.0:9229 server.js"
}
}

test 실행:

1
$ docker-compose -f docker-compose.dev.yml run notes npm run test

Multi-stage Dockerfile for testing

명령에 따라 테스트를 실행하는 것 외에도 Dockerfile을 사용해서 이미지를 빌드할 때 테스트를 실행할 수 있다. 밑에 Dockerfile 은 test를 진행하고 production image 를 build 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# syntax=docker/dockerfile:1
FROM node:14.15.4 as base

WORKDIR /code

COPY package.json package.json
COPY package-lock.json package-lock.json

FROM base as test
RUN npm ci
COPY . .
CMD [ "npm", "run", "test" ]

FROM base as prod
RUN npm ci --production
COPY . .
CMD [ "node", "server.js" ]

먼저 , base image에 라벨을 as base 로 추가한다. build stage 마다 참조할 수 있도록 해준다. docker command 를 입력할 때 --target test 같이 명시해서 build stage를 명시해서 build 할 수 있다.

1
$ docker build -t node-docker --target test .

이렇게 하면 test 이미지가 빌드 된다. 이제 test 이미지를 실행해 본다.

1
$ docker run -it --rm -p 8000:8000 node-docker

테스트가 실행 된다.

지금은 build 한다음 run 을 하는 방식을 사용하는데 이렇게 하면 실행하기 위해 2번씩 명령어를 입력해야 한다. Dockerfile 내부에 CMD 를 RUN 으로 바꾸어서 조금 개선할 수 있다. CMD 는 컨테이너에서 이미지를 실행할 때 실행된다. 반면에 RUN 은 이미지를 build 할때 실행 되고 실패하면 중지된다. 수정한 Dockerfile은 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# syntax=docker/dockerfile:1
FROM node:14.15.4 as base

WORKDIR /code

COPY package.json package.json
COPY package-lock.json package-lock.json

FROM base as test
RUN npm ci
COPY . .
RUN npm run test

FROM base as prod
RUN npm ci --production
COPY . .
CMD [ "node", "server.js" ]

똑같이 build 한다

1
$ docker build -t node-docker --target test .

DockerCompose

docker compose 사용하면 컨테이너간의 의존성을 파일 하나로 관리하면서 실행시킬 수 있다. 이번시간에는 개발 환경을 직접 docker-compose 로 build 해 보도록 한다.
사용하는 이미지는 mysql 과 node 환경을 이용하고 서버 프레임 워크로는 Express 를 사용한다.

docker-compose.dev.yml

먼저 docker-compose 파일을 생성해준다. 개발 환경임을 명시하기 위해서 dev.yml 파일로 생성한다. docker-compose 파일을 사용하지 않고도 run 명령어로 실행시킬 수 있지만 compose 파일을 사용하면 하나의 파일로 의존성을 관리할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
version: '3.8'

services:
mysqldb:
image: mysql
ports:
- 3306:3306
command: # 명령어 실행
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- mysql:/var/lib/mysql
- mysql_config:/etc/mysql
environment:
- MYSQL_ROOT_PASSWORD=1q2w3e
- MYSQL_DATABASE=test

notes:
depends_on:
- mysqldb
build:
context: .
working_dir:
/app
ports:
- 443:8080
- 9229:9229
environment:
- SERVER_PORT=8080
- DB_PORT=3306
- MYSQL_DATABASE=test
- USER=root
- MYSQL_ROOT_PASSWORD=1q2w3e
- HOST=mysqldb
- CHOKIDAR_USEPOLLING=true
volumes:
- ./:/app
command:
- bash
- -c
- |
/app/wait-for-it.sh mysqldb:3306 -t 10
yarn run nodemon-dev

volumes:
mysql:
mysql_config:
  • mysqldb로 서비스를 만들었고, notes 서비스에서 HOST를 mysqldb로 환경 변수를 전달하고 있는데 DNS를 지원하기 때문에 compose 된 환경 안에서 이름 그대로 접근할 수 있다.
  • notes 에서 build로 context로 현제 폴더를 지정해 주었는데 이렇게 하면 현제 폴더에서 Dockerfile를 참조해서 build를 실행한다. 명시적으로 파일을 지정해 줄 수 도 있다.
  • depends_on 을 통해서 의존성을 명시한다. 해당 서버에서 mysql 에 test table을 조회하는데 test table이 만들어지 않은 상태에서 접근하려고 하면 에러가 발생한다. 의존성을 명시해서 먼저 mysqldb 에 build 가 실행된 이후에 notes 에 build 가 실행되도록 한다.
  • 다만, depends_op은 실행 순서는 보장해 주지만 준비 상태까지는 보장해 주지 않는다. 따라서 wait-for-it.sh 스크립트를 사용했는데 조금 서치해보면 어떻게 설치하는지 알 수 있다. 그냥 사용하면 권한 거부 에러가 발생하기 대문에 wait-for-it.sh 의 실행 권한을 설정하고 build 해야 한다.
  • dockerfile로 개발환경을 설정할때에는 현제 로컬에 수정사항을 반영하기 위해서 $(pwd) 같은 것을 사용했었는데 docker-compose 파일을 사용하면 상대 경로를 통해서 수정사항을 반영할 수 있도록 하는게 가능하다.

211221

리액트 네이티브

  • 커스텀 버튼에서 primary 버튼과 secondary 버튼을 만드는 방법 <429p>
  • React.forwardRef(CusomComponent) 와 같이 선언하고 CustomComponent에서 원하는 컴포넌트에 props 다음으로 받아온 ref 를 proos로 사용하게 설정하면 사용하는 쪽에서 CustomComponent에 ref를 넘겨줌으로써 CustomComponent 내부의 컴포넌트를 참조 할 수 있다.
  • 스택에 화면을 비워야 한다면? 로그인 했는데 로그인 화면으로 스와이프해서 넘어가는것 방지하는 경우 같은.. reset이라는 메서드가 있는데 번거로움.. 대신에 특정 조건을 만족하면 스택에서 화면을 제거하는 방법으로 구현 가능하고 공식문서에서도 이 방법을 추천함. → rootStack 같은 곳에서 특정 상태를 기반으로(ex. user) 조건부 렌더링으로 스택을 처리하면 됨.
  • 로그인 정보를 유지하기 위해서 일반적으로는 AsyncStorage를 사용한다.
  • RefreshControl 을 사요하면 FlatList 에서 아래로 내리는 스와이프 동작으로 새로고침을 구현할 수 있다. FlatList 에 refreshControl 컴포넌트로 RefreshControl 을 주입하면 된다.
  • useNavigationState 함수를 사용해서 내비게이션 상태를 조회할 수 있다.
  • Pressable 에 hitSlop을 설정하면 컴포넌트 영역은 그대로 유지하고 터치 가능한 영역만 설정한 숫자 만큼 늘려준다. 숫자도 넣을 수 있고, Rect 타입의 객체를 넣을 수 도 있다.

211216

백엔드-Authentication

  • 인증이란? : you are who you say you are, 다양한 방법으로 인증 가능하다 통상적으로 password, id 로
    • 먼저 회원가입을 진행해서 서버에 id, passwrod 를 저장한다.
    • 클라이언트는 로그인 할때 회원가입한 id, password를 서버에 전송한다.
    • 어떻게 로그인 상태를 유지할 수 있을까?
  • 세션과 쿠기 (서버에서 사용할 수 있는 전통적인 옵션- 어떻게 로그인 상태를 유지할지에 대한 방법)
    1. 세션
      • 서버에서 확인후 세션을 만든다 (userId, sessiontId, expiration) - Session DB에 저장 or 파일시스템이나 메모리도 될 수 있음
      • 쿠키에 HTTP Only로 sessiontId 정보를 전달함.
      • 다음 요청때마다 쿠키 정보를 전달해줌
      • 장점 : 브라우저에 전달만 하면 되서 간단하고, sessionId 만 전달하면되서 사용자의 정보를 전달하지 않아도 된다. HTTP Only를 사용하면 스크립트로 못읽기 때문에 보안상의 이점도 있다.
      • 단점 : Stateful 하기 때문에 다양한 서버들이 SettionDb를 읽어야 하고 많은 요청이 들어오게 된다. 내부적으로 네트워킹이 많아짐. 성능 하락
    2. JWT (Json Web Token)
      • 다음과 같은 정보를 JSON으로 만들고 토큰화해서 보낸다. header, payload, signature, 모든 정보는 인코딩해서 보내고 서버에서 secrete으로 사용하는 키도 인코딩해서 signature에 포함해서 보낸다.
      • 로그인 하면, 로그인 정보 + 만료 시간 등등 합쳐서 JWT를 만듦.
      • 클라이언트는 Header를 이용하여 모든 request마다 JWT를 포함해서 전달해 줌.
      • 서버는 JWT를 검증한 후에 데이터를 반환함.
      • 장점 : 서버에 State가 없다. 서버를 확장하거나 분산하기에 용이하다.
      • 단점 : JWT 자체가 단점이 될 수 있다. → 계속 JWT를 주고 받아야 한다. 만약 영원히 만료되지 않은 JWT를 헤커가 탈취한다면.. 사용할때 보안에 신경써야 한다.
  • bcrypt 란? : 사용자 정보를 그대로 저장하는 것이 아니라 암호화 해서 저장하기 위해 사용함. → 암호화만 가능한데 (암호화 한것을 비교하는 것), salt 가 없다면 경우의 수로 암호화 해 보면서 유추할 수 있어서 salt를 포함하여 경우의 수를 늘림. 10~12 정도로 설정. 길어지면 cpu 부하 심해짐..
  • JWT, 32 시크릿 키로 권고 됨. 한번 발행된 토근은 변경되면 안된다. → 만약 한버이라도 변경 한다면 최종적으로 붙은 signature도 변경되어서 verify시 오류 발생하고 누군가 변경한 토큰인지 확인 가능하다.
    • 만료될 수 있도록 만들어야 한다. → option으로 전달함. {expiresIn: 2} 이런식으로 → 2초 후에 만료

리액트 네이티브

  • Platform.OS 로 플랫폼 종류를 알 수 있다.
  • KeyboardAvoidingView 에서 behavior Props 로 동작 장식을 정의할 수 있다.
    • padding : 키보드 열렸을때 뷰 하단에 패딩을 설정
    • height: 뷰의 높이 자체를 변경
    • position: 뷰의 위치를 설정
  • Platform.select({ios:, android,}) 를 사용해서 플랫폼 별로 옵션을 줄 수 있다.
  • 터치 했을때 효과 주기
    • TouchableHighlight: 터치했을 대 배경색 변경
    • TouchableNativeFeedback: 안드로이드에서 물결 효과 ios에서는 오류
    • ToucableOpacity: 투명도 조정
    • ToucableWithoutFeedback: 아무 효과도 적용하지 않는다.
  • keyboard.dismiss() 는 현제 나타난 키보드를 닫는다.
  • onSubmitEditing → enter 눌렀을때 이벤트
  • returnkeyType=”done” → 키보드 눌렀을대 return 타입을 보여줌.
  • FlatList에 ItemSeparatorComponent Props를 지정해서 컴포넌트 사이에 구분선을 설정할 수 있다.
  • react-nativevector-icons 를 사용하면 벡터 아이콘을 리액트 네이티브 프로젝트에서 간편하게 컴포넌트처럼 사용할 수 있게 해준다.
  • ios/proejctForderName/info.plist → 앱의 이름, 아이콘, 버전 등 앱에서 필요한 설정값을 지니고 있다.
  • android/app/build.gradle → 프로젝트의 의존성, 프로그인 및 빌드에 필요한 설정에 대한 정보를 지니고 있다.
  • Alert.aler(제목, 내용, 버튼, 옵션) 버튼 부분에 {text, onPress, style} 을 각각 설정해서 버튼 스타일 내용, 눌렀을때 동작등을 정의할수 있다. 안드로이드에서는 버튼 스타일이 적용되지 않아서 따로 만들어야 한다. 설정할 수 있는 style은 다음과 같다.
    • cancel: 취소 기본에 폰트 두껍게
    • default: 기본 파란색
    • destructive: 파괴적인? 삭제하는 상황에 적합 빨간색이 됨.
  • 옵션으로는 바깥에 눌렀을때 동작이나, 안드로이드에서는 바깥에 눌렀을때 취소 옵션 같은걸 줄 수 있다.
  • 브라우저에 localStorage 와 비슷한 AsyncStorage 를 사용할 수 있다. API도 비슷한데 다른점이라면 AsyncStorage는 비동기로 동작해서 Promise를 반환한다. yarn add @react-native-community/async-strage 로 설치한다.
  • useEffect 에는 cleanup 하는 기능이 있는데 내부 함수가 promise를 반환하면 충돌하기 때문에 내부에서 async 함수를 선언한 후에 호출하는 방법을 사용한다.
  • AsyncStorage를 사용할때는 추상화 해서 사용하는 것을 추천한다 → 나중에 다른 스토리지를 사용할때 쉽게 교체할 수 있도록
  • android 는 AsyncStorage 로 6MB를 저장할 수 있다 늘리려면 gradle.properties를 수정한다. ios 는 따로 최대 용량이 설정되어 있지 않다.
  • AsyncStorage는 데이터가 많아지면 성능이 떨어진다. 또한 정렬이나 인덱싱 기능을 지원하지 않는다. 소규모에서 적합하고 조금 규모가 커지면 대안으로 react-native-sqlite-storage 같은것을 사용하면 된다.

211221

리액트 네이티브

네비게이션

  • 네비게이션을 위해서 @react-navigation/native 를 사용한다. 의존하는 라이브러리로 react-native-screens react-native-safe-area-context 를 설치한다.
  • 브라우저에 history 와 같은 기능을 사용하기 위해서 Native Stack Navigator 를 사용한다. 설치 @react-navigation/native-stack
  • 스크린을 사용되는 컴포넌트는 navigation을 props로 받음. navigation.navigate 나 navigation.push 로 화면 전환을 할 수 있다.
  • 마찬가지로 props로 route도 받아온다. route는 key, name, params 를 갖는다.
  • navigate 와 push 에 차이는 navigate 는 전환 화면이 현제 화면과 다르면 화면을 쌓지 않고, push 는 다른 화면을 쌓는다.
  • 뒤로가기 navigation.pop( ) 으로 하고, 가장 처음 화면으로 이동할 때에는 navigation.popToTop() 으로 이동한다.
  • 드로어 네비게이터를 사용하려면 @react-navigation/drawer react-native-gesture-handler react-native-reanimated 를 설치한다
  • Screen 이 아닌 곳에서는 React와 마찬가지로 hook을 통해 route 와 navigationd 을 가져올 수 있다. useNavigation , useRoute
  • useFocusEffect 웹과 달리 앱은 화면이 사라지는 것이 아니라 쌓게 된다. 따라서 Home 면에서 Detail 화면으로 넘어갈때 화면을 쌓일 뿐이여서 componentWillUnmount 같은 로직이 호출되지 않는다. 마찬가지로 Detail 에서 Home으로 돌아올 때도 componentDidMount 같은 로직이 호출되지 않는다. 그래서 만약 다른 화면을 봤다가 다시 돌아왔을때 어떤 작업을 하려면 useFocusEffect hook 을 사용해야 한다. → 반드시 useCallback 과 같이 사용해야 한다. 안그러면 렌더링 될때마마다 useFocusEffect 에 등록한 함수가 실행된다.

알고리즘

  • DP 와 분활정복의 차이 ?
    • 큰문제가 작은 문제로 나누어짐, 가장 큰 차이점은 부분 문제의 중복이다. DP 는 부분 문제의 중복이 존재하고, 분할정복은 그렇지 않다.