env란

  • environment variable로 환경변수를 뜻합니다.
  • API_KEY, DB관련 정보 등 개발팀 내에서만 알아야 하는 값이 있습니다.
  • 이때 dotenv 패키지를 사용해 환경변수 파일을 외부에 만들어 필요할 때마다 import해 하드코딩하지 않고 사용할 수 있습니다.
  • 또한 .env파일을 gitignore에 추가해 github에 올라가지 않도록 설정 가능합니다.
  • 팀내에서 공유할 땐 그냥 내 env 파일 긁어서 복붙해서 주거나 slack bot을 이용할 수 있습니다.

 

프로젝트에서 어떻게 쓰나

1. react-native-dotenv 라이브러리 설치

yarn add -D @types/react-native-dotenv

 

2. babel.config.js 파일에서 plugins 항목에 값 넣어주기

module.exports = function () {
  return {
    ...,
    **plugins: [
      [
        "module:react-native-dotenv",
        {
          moduleName: "react-native-dotenv",
        },
      ],
    ],**
  };
};

 

3. 최상단에 .env 파일 만들고 내용 추가하기

//.env
EXPO_PUBLIC_KAKAO_REST_API_KEY = 어쩌고 저쩌고
EXPO_PUBLIC_KAKAO_REDIRECT_URI = https://moyeota-webview.netlify.app/
EXPO_PUBLIC_환경변수_이름 = 어쩌고 저쩌고
  • 우리는 Expo 환경에서 개발중이기에 env파일 내의 변수 이름 앞에 EXPO_PUBLIC_ 을 붙여주어야 합니다.
  • 여담으로 CRA를 이용해 프로젝트를 만든 경우 REACT_APP_환경변수이름 = 값 의 형태로 쓰면 됩니다.
  • 또 여담인데 vite로 프로젝트를 만들면 VITE_환경변수이름 = 값 으로 하면 됩니다.

 

4. 갖다 쓰기

  • process.env.변수이름 의 형태로 가져올 수 있다.
  • 이 경우 프로젝트에서 자동으로 인식해 .env 파일에서 가져온다.
${process.env.EXPO_PUBLIC_KAKAO_REST_API_KEY}
${process.env.EXPO_PUBLIC_KAKAO_REDIRECT_URI}

 

5. 혹시 모르니 gitignore 확인하기

  • gitignore에 .env가 들어있는 지 확인한다. 그래야 깃헙에 안올라가니
  • 만일 다른 사람이 env 파일이라고 주면 자신의 .env 파일에 추가한다.

들어가기 전에

  • SVG 파일을 public > svg 폴더에 넣어서 직접 import 해와서 사용하고 있었다.
  • 그러니 해당 SVG 파일에 width, height 등의 속성을 넣으니 아래 사진과 같은 에러가 발생했다.
  • 따라서 vite-plugin-svgr 라이브러리를 이용해 SVG를 ReactComponent로 바꿔 사용하고자 한다.

환경 설정

라이브러리 설치

npm install --save-dev vite-plugin-svgr
yarn add -D vite-plugin-svgr
pnpm add -D vite-plugin-svgr

vite.config.js 파일 수정

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),

    /* 여기서부터
    svgr(
      {
      exportAsDefault: true,
      svgrOptions: {
        icon: true,
      },
    }
    ),
    여기까지 */
  ],
  server: {
    port: 3000,
  },
});

custom.d.ts 생성

  • Root 폴더에 custom.d.ts 파일을 만들어 아래 코드를 복붙한다.
declare module '*.svg' {
  import React = require('react');
  export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
  const src: string;
  export default src;
}

tsconfig.json 수정

  • include에 custom.d.ts를 추가해준다.
  "include": ["src", "custohttp://m.d.ts"],

package.json 수정

  • script 부분에 "svgr"을 추가해준다.
  • public/svg에 있는 파일을 src/assets/svg 폴더에 tsx파일로 바꾸어 준다는 뜻이다.
    "svgr" : "npx @svgr/cli -d src/assets/svg --ignore-existing --typescript --no-dimensions public/svg"

사용하기

  • public에 svg 폴더를 생성 후 해당 폴더에 svg 파일을 넣는다.

  • pnpm svgr / yarn svgr / npm svgr 등 각자의 패키지 매니저 명령어와 함께 svgr을 입력한다.

  • src/assets/svg 폴더에 public/svg 폴더에 있던 svg 파일들이 tsx형태로 저장된다.

  • 이를 가져다 쓰면 된다

  • 이제 width, height를 지정해줘도 에러가 나지 않는다 !!!

비트마스크란?

정수의 이진수 표현을 자료구조로 쓰는 기법입니다. 비트마스크는 엄밀히 말해 자료구조라고 할 수는 없지만 굉장히 유용하게 사용됩니다.

 

비트마스크의 장점

1. 더 빠른 수행시간

비트마스크 연산은 O(1)에 구현되는 것이 많기 때문에 적절히 사용할 경우 다른 자료구조를 사용하는 것보다 훨씬 빨리 동작합니다. 

물론 비트마스크 연산을 사용할 수 있다는 말은 원소의 수가 많지 않다는 뜻이기에 엄청나게 큰 속도 향상을 기대할 수 없지만, 이와 같은 연산을 굉장히 여러 번 수행해야 할 경우에는 작은 최적화도 큰 속도를 가져올 수 있습니다. 

 

2. 더 간결한 코드

다양한 집합 연산들을 반복문 없이 한 줄에 쓸 수 있기 때문에 비트마스크를 적절히 사용하면 굉장히 짧은 코드를 작성할 수 있다.

 

3. 더 작은 메모리 사용량

비트마스크를 이용하는 코드들은 같은 데이터를 더 적은 메모리를 사용해 표현 가능합니다.

더 많은 데이터를 미리 계산해 둘 수 있기 때문에 프로그램도 빨라지고, 캐시 효율도 더 좋습니다.

 

4. 연관 배열을 배열로 대체

불리언 값 배열을 키로 갖는 연관 배열 객체 map<vector<bool>, int>를 사용하고 있다고 치면, 이를 비트마스크를 사용하다면 단순 int[] 배열을 사용해 같은 정보를 나타낼 수 있습니다.

이 기법은 엄청난 시간과 메모리 차이를 가져옵니다.

 

용어 정의 

비트(bit)

이진수의 한 자리, 0 혹은 1의 값을 가질 수 있으며, 컴퓨터가 표현하는 모든 자료의 근간이 됩니다.

 

예) 부호 없는 8비트 정수형 여덟 자리 이진수로 표시할 수 있는 모든 정수를 표현할 수 있습니다.

따라서 부호 없는 8비트 정수형이 가질 수 있는 최소 값은 0, 최대 값은 1111 1111(2) => 255입니다.

 

최상위비트(Most Significant Bit)

부호 없는 N비트 정수형 변수는 N자리의 이진수로 쓸 수 있습니다.

이때 각 비트가 표현하는 값은 2의 0승 ~ 2의 N-1승입니다. 이때 2의 N-1승에 해당하는 비트를 최상위 비트라고 부릅니다.

 

최하위비트(Least Significant Bit)

부호 없는 N비트 정수형 변수는 N자리의 이진수로 쓸 수 있습니다.

이때 각 비트가 표현하는 값은 2의 0승 ~ 2의 N-1승 입니다. 이때 2의 0승에 해당하는 비트를 최하위 비트라고 부릅니다.

 

 

비트 연산자

비트마스크를 사용하기 위해서는 정수 변수를 비트별로 조작할 수 있는 비트 연산자를 사용해야 합니다.

 

AND

AND 연산은 입력받은 두 정수를 한 비트씩 비교하면서, 두 정수에 해당하는 비트가 모두 켜져 있을 때만 결과의 비트를 켭니다.

 

OR

OR 연산은 입력받은 두 정수를 한 비트씩 비교하면서, 두 정수에 해당하는 비트가 하나라도 켜져 있으면 결과의 비트를 켭니다.

 

XOR

XOR 연산은 입력받은 두 정수를 한 비트씩 비교하면서, 두 정수중 하나의 비트만 켜져있을때 결과의 비트를 켭니다.

 

NOT

정수 하나를 입력 받아 켜져있는 비트는 끄고, 꺼져있는 비트는 켭니다.

 

a >> b

정수 a의 비트를 오른쪽으로 b칸씩 밀고 빈 자리는 0으로 채웁니다.

 

a << b

정수 a의 비트를 왼쪽으로 b칸씩 밀고 빈 자리는 0으로 채웁니다.

 

 

유의할 점들

1. 우선순위

C++과 자바에서 &, |, ^ 등의 비트 연산자의 우선순위는 == 혹은 != 등의 비교 연산자보다 우선순위가 낮습니다.

 

int c = (6 & 4 == 4)

 

만일 위 코드를 6 & 4 비트연산 계산 후, 해당 결과 값이 4와 같은 지 확인하는 용도로 짰다면 이는 올바르게 동작하지 않습니다.

비트 연산자가 비교 연산자보다 우선순위가 낮기 때문에 4 == 4가 먼저 계산되고, 결과인 1이 6과 &연산을 하는 식으로 흘러갈 것입니다.

 

올바른 코드

int d = ((6 & 4) == 4)

 

위 코드처럼 비트 연산을 소괄호로 묶어줘야 합니다. 꼭 그게 아니더라도 가독성을 위해서는 소괄호로 묶어주는 것이 좋습니다.

 

 

2. 오버플로우

64비트 정수를 비트마스크로 사용할 때 오버플로우가 발생합니다.

부호 없는 비트마스크 a의 b번 비트가 켜져있는지 확인하기 위한 코드를 다음과 같이 작성했다고 해봅시다.

bool isBitSet(unsigned long long a, int b) {
	return (a & (1 << b)) > 0;
}

 

위 코드는 정상적으로 동작하지 않습니다. 왜일까요 ?

C++에서는 1은 부호 있는 32비트 상수로 취급되기 때문에 b가 32이상이면 1 << b 에서 오버플로우가 발생하기 때문입니다. 

이를 해결하기 위해서는 1뒤에 이 상수가 부호 없는 64비트 정수임을 알려주기 위해 접미사 ull을 붙여 주어야 합니다.

 

3. 부호있는 정수형의 사용

부호 있는 정수형에서 최상위 비트가 켜진 숫자는 음수를 표현합니다.

32비트 정수형에서 하위 20비트만 사용한다든지하는 문제는 별 문제 없지만, 32비트를 전부 사용하고 싶다면 이와 같은 차이는 자잘한 버그를 불러올 수 있습니다.

 

따라서 변수의 모든 비트를 다 쓰고 싶다면 부호 없는 정수형을 쓰는 것이 좋습니다.

 

4. N비트 정수에서 N비트 이상 시프트

얼핏 생각해보면 결과가 0이 되어야 할 것 같지만, C++언어 명세에는 이 결과가 정의되어 있지 않으므로 이런 코드는 환경에 따라 다른 결과를 낼 수 있습니다.

 

비트마스크를 이용한 집합의 구현

비트마스크의 가장 중요한 사용 사례는 집합을 구현하는 것입니다.

N비트 정수 변수는 0 ~ N-1까지의 정수 원소를 가질 수 있는 집합이 됩니다. 이때 원소 i가 집합에 속해있는지 여부는 2의 i승을 나타내는 비트가 켜져있는지 여부로 나타냅니다. 

 

예) 1, 4, 5, 6, 7, 9를 표현하는 정수는 754입니다.

10 1111 0010(2) = 754

공부 목적

코딩테스트를 위한 자료구조, 알고리즘을 하다보니 모래성 위에 개념을 쌓고 있는 느낌이었습니다. 기본적인 STL에서의 쓰임새와, 알고리즘 문제 풀이에서 어떤 과정에서 사용해야 할 지는 알지만 좀 더 탄탄한 기반을 만들 필요성이 느껴져서 공부하게 되었습니다.

 

교재

종만북이라고 불리는 '알고리즘 문제 해결전략'을 중심으로 공부할 예정입니다 !

 

목차

아래 순서대로 게시 예정입니다 !

1. 비트마스크

2. 선형자료구조

3. 큐와 스택, 데크

4. 문자열

5. 트리

6. 우선순위 큐와 힙

7. 이진검색트리

8. 트라이

9. 그래프

10. 깊이 우선 탐색

11. 너비 우선 탐색

12. 최단경로 알고리즘

13. 최소 스패닝 트리

14. 네트워크 유량

 

+ Recent posts