Nodejs에서 Typescript 사용해보기!

nodejs를 하면서 Typescript에 대하여 어려번 들었습니다.

기본적으로 nosejs에 대한 개발을 REPL 기반으로 하고 있습니다.

TDD를 하기 위해서는 타입에 대한 검증등 많은 것들을 처리 해야 하는데요. 이는 Typescript와 더 잘 맞습니다.

한번 사용해보기 위해서 nodejs에서 Typescript를 사용하는 방법을 설명드리겠습니다.

Typescript 사용해 보기

평소에는 npm을 사용하지만, 이번에는 yarn을 사용해보려고 합니다.

프로젝트 생성하기

먼저 프로젝트 디렉토리를 생성하고 yarn 명령어를 이용해서 초기화 합니다.

$ mkdir learn-typescript
$ cd learn-typescript
$ yarn init -y

Typescript 사용을 위한 모듈 설치하기

  • typescript : Typescript 라이브러리
  • ts-node : node에서 Typescript를 사용하기 위한 라이브러리
$ yarn add typescript ts-node

Typescript 설정 파일 생성하기

타입스크립트에 대한 정보를 가지고 있는 설정파일을 생성합니다.

$ yarn run tsc --init

실행을 하면 디렉토리에 tsconfig.json 파일이 생성됩니다.

해당 파일의 내용은 아래와 같습니다.

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "es2016" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    // "lib": [],                             /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    "outDir": "./dist/" /* Redirect output structure to the directory. */,
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true /* Enable all strict type-checking options. */,
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */

    /* Advanced Options */
    "skipLibCheck": true /* Skip type checking of declaration files. */,
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  }
}

물론 명령어 없이 추가해도 됩니다.

Typescript 컴파일

다음 명령어로 .ts 파일을 컴파일 하여 .js 파일로 변환합니다.

$ yarn run tsc

컴파일 후 기본적으로 같은 디렉토리에 .js파일로 생성됩니다.

tsconfig.json 파일의 outDir 값을 이용해서 다른 디렉토리에 생성되도록 변경이 가능합니다.

nodejs에서 Typescript 실행하기

매번 컴파일을 하지 않고 ts-node 명령어를 이용해서 실행할 수 있습니다.

# run ts file
$ yarn run ts-node ./src/index.ts

여기까지 기본적은 Typescript를 nodejs에서 사용하는 명령어를 확인하였습니다.

Typescript에 대하여 자세히 알고 싶다면 TypeScript Documentation 문서를 확인하면 됩니다. :)

마지막으로 마틴 아저씨가 REPL로 개발한 경험을 블로그에 올리셨습니다.

So I’ve learned my lesson. REPL driven development feels easier and faster than TDD; but it is not. Next time, it’s back to TDD for me.

내 맘대로 직역 :

내가 배운 교훈은 REPL개발은 TDD에 비해 쉽고 빠르게 보이지만, 실제로는 그렇지 않다. 여러 부분에서 더 많은 비용을 들이게 된다.
그래서 나는 TDD를 다시 사용한다.

nodejs에서 명확히 구조화된 프로그램 작성을 위해서는 Typescript를 사용하는 것을 추천합니다. :)

참고자료

Posted by lahuman

댓글을 달아 주세요

swagger-node에서 express-session 설정 & 사용하기

기본적으로 swagger-nodeexpress를 기반으로 동작합니다.

swagger-node는 API 용으로 이용하기 때문에 기본적으로 session을 발행하지 않습니다.

다만 필요에 따라 로그인 프로세스 구현을 하게 될 경우 다음 라이브러리를 이용해야 합니다.

app.js 코드에 다음과 같이 설정을 하면 세션을 이용할수 있습니다.

express 4.X 부터는 body-parser를 사용하지 않고 express에서 제공되는 것을 이용합니다.
또한 app.use(express.urlencoded({ extended: true })); 을 사용하면 fileupload 처리를 이전과 같이 사용할 수 없습니다. 아래 multer를 이용한 예제를 참고 하셔요.

app.use(
  require("express-session")({
    secret: "keyboard cat",
    cookie: {
      maxAge: 1000 * 60 * 60 , // 1 hour
    },
    resave: false,
    saveUninitialized: false,
  })
);
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

추가로 session 관리를 passport를 이용해서 쉽게 관리 할수 있습니다.

다음 예제는 SSO의 방식중 하나인 SAML으로 처리한 예제를 준비 하였습니다.

예제 코드 바로 보기

주요점은 passport는 express-session에서만 동작 하기 때문에 세션 설정을 잘해야 합니다.

Multer를 이용한 첨부 파일 uploade

app.use(express.urlencoded({ extended: true }));를 설정하면, formData를 바로 접근하지 못하게 됩니다. 이때 다음 샘플을 기준으로 첨부파일을 처리 할 수 있습니다.

// multer 설정
const multer = require("multer");
const storage = multer.diskStorage({
  // upload path
  destination: function (req, file, cb) {
    cb(null, "tempfiles");
  },
  // 업로드된 파일 이름
  filename: function (req, file, cb) {
    cb(null, `${moment().format("YYYYMMDDHHmmssSSS")}${file.originalname}`);
  },
});

const upload = multer({
  storage: storage,
  limits: { fileSize: 10 * 1024 * 1024 },
});

... 설정 처리

SwaggerExpress.create(config, function (err, swaggerExpress) {
  if (err) {
    throw err;
  }
  // swagger-node에서 미들웨어 처리 방법
  app.use(
      "/jira/attachments/upload",
      upload.single("filepond"),
      async (req, res, next) => {
        try {
          const file = req.file;
          res.status(201).json({
            status: "OK",
            file_nm: file.originalname.normalize("NFC"),
            file_path: file.filename,
          });
        } catch (e) {
          logger.error(e);
          res.status(400).json({ status: "ERROR", message: e });
        }
      }
    );
});

주요 코드만 표기 하였습니다.
예제 코드 바로 보기app.js를 참고 하면 전체 코드를 작성하실수 있습니다.

참고 자료

Posted by lahuman

댓글을 달아 주세요

첨부파일을 다른 서버로 포워딩 하기

첨부 파일을 아래 그림과 같이 API server에서 받아서 다른 내부 서버에 전달을 하려고 합니다.

API 서버에는 따로 첨부파일 정보를 저장하지 않고, buffer를 바로 내부 서버로 전달을 합니다.

이를 처리하는 방식으로는 2가지가 있습니다.

  1. Proxy 사용
  2. axios와 다른 라이브러리를 이용하여 post 통신

1. Proxy 사용

필요 라이브러리

사용법

express-http-proxy를 다음과 같이 설정하면 해당 주소로 오는 요청의 통신을 설정된 서버로 포워딩 해줍니다.

# 예제
const proxy = require('express-http-proxy');

const app = require('express')();

app.use('/proxy', proxy('http://proxy_target_domain', {
  proxyReqPathResolver: async (req) => {
    return '/proxy/target/url?id='+req.params.id;
  },
  proxyReqOptDecorator: (proxyReqOpts) => {
    const newProxyReqOpts = { ...proxyReqOpts };
    newProxyReqOpts.headers = { host: 'spacial hosts', apikey: 'spacial key' };
    newProxyReqOpts.rejectUnauthorized = false;
    return newProxyReqOpts;
  },
}));

2. axios와 다른 라이브러리를 이용하여 post 통신

필요 라이브러리

  1. axios
  2. multer
  3. form-data

사용법

우선 첨부파일을 multer를 이용해서 객체로 만들고, 이를 form-data로 감싸서 axios를 통해 전송합니다.

const axios = require("axios");
const https = require("https");
const multer = require("multer");
const FormData = require("form-data");
const express = require('express');

const app = express();
const router = express.Router();

app.use('/', router);

const upload = multer();
router.post(
  "/upload",
  upload.single("filepond"), // multer를 이용하여 업로드 파일 처리
  async (req, res, next) => {
    try {
      // buffer를 FormData로 감쌈
      const formData = new FormData();
      formData.append("filepond", req.file.buffer, {
        filename: req.file.originalname,
      });

      // 다른 서버로 전송
      const result = await axios.post(
        'http://proxy_target_domain/proxy/target/url',
        formData,
        {
          headers: {
            ...formData.getHeaders(),
            "Content-Length": formData.getLengthSync(),
            apikey: "apikey",
            host: "hosts",
          },
          httpsAgent: new https.Agent({
            rejectUnauthorized: false,
          }),
        }
      );
      res.status(200).json(result.data);
    } catch (err) {
      logger.error(err);
      res
        .status(500)
        .send(`${err}`);
    }
  }
);

첨부 파일을 다른 서버로 전송할때 주의 하는 부분이 있습니다.

formData.append("filepond", req.file.buffer, {
        filename: req.file.originalname,
      });

이 부분에서 3번째 옵션 파라메터에 filename 이외의 값을 함부로 추가 하면 400 Bad request 가 발생합니다.

파일을 전달하는 것이 어려운게 아닌데 명확한 인터페이스를 확인하지 못해서 시간이 많이 지체 되었습니다.

Posted by lahuman

댓글을 달아 주세요

node:Alpine 에서 puppeteer 기동 하고 한글 깨짐 처리 하기

GitOps 스타일의 지속적인 배포를 구축하여 자동 배포 시스템을 Git ==> jenkins ==> Kubernetes로 구축하여 사용하고 있습니다.

배포가 문제 없이 되었으나 puppeteer를 사용하는 순간 다음과 같은 오류를 만나게 되었습니다.

....
Error: Failed to launch chrome! spawn /app/node_modules/puppeteer/.local-chromium/linux-609904/chrome-linux/chrome ENOENT
...

원인 해결 방법으로 chrome을 설치하고 실행 위치를 강제로 잡아주면 된다.

# Dockerfile 내부
# chromium 설치
RUN apk add --no-cache udev ttf-freefont chromium

# npm 설치 시 chromium 다운하지 않도록 설정
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
# 설치된 위치를 환경 변수로 설정(node에서 사용)
ENV CHROMIUM_PATH /usr/bin/chromium-browser

이후 puppeteer를 실행하는 곳에서 다음과 같이 처리 해줍니다.

puppeteer.launch({
  executablePath: process.env.CHROMIUM_PATH,
  args: ['--no-sandbox'], // This was important. Can't remember why
});

이후 다음과 같은 오류가 발생할 수 있습니다.

Protocol error (IO.read): Invalid parameters handle: string value expected

이유는 node:12-alpine를 사용할 경우 발생하는 오류로 node:13-alpine를 이용하면 해결 됩니다.

마지막으로 이렇게 처리 했음에도 한글이 깨지고 맙니다.

한글 폰트를 다음과 같이 설치하여 줍니다.

# Dockerfile
# 한글 폰트 설치
RUN mkdir /usr/share/fonts/nanumfont
RUN wget http://cdn.naver.com/naver/NanumFont/fontfiles/NanumFont_TTF_ALL.zip
RUN unzip NanumFont_TTF_ALL.zip -d /usr/share/fonts/nanumfont
RUN fc-cache -f -v

추가 : 전체 Dockerfile을 예제

Alpine 이란? 알파인 리눅스는 보안, 단순성 및 자원 효율성을 높이는 고급 사용자를 위해 설계된 범용 리눅스 배포판으로 musl libc와 busybox를 기반으로 하기에 GNU/Linux 배포판 보다 작고 가벼우며 yum이나 apt 같은 패키지 관리자가 아닌 apk라는 자체 패키지 관리자를 가지며 보안에 염두해두고 설계되었기에 모든 바이너리는 독립적인 실행 파일(PIE)로 컴파일 됩니다.

FROM node:13.12.0-alpine3.11 as build

USER root

# 앱 디렉터리 생성
WORKDIR /usr/src/app

COPY . .
# chromium 설치
RUN apk add --no-cache udev ttf-freefont chromium

# 한글 폰트 처리
RUN mkdir /usr/share/fonts/nanumfont
RUN wget http://cdn.naver.com/naver/NanumFont/fontfiles/NanumFont_TTF_ALL.zip
RUN unzip NanumFont_TTF_ALL.zip -d /usr/share/fonts/nanumfont
RUN fc-cache -f -v

# 앱 디렉토리로 다시 이동
RUN cd /usr/src/app
# npm install 시 Chromium 다운로드 제외 처리
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
# chromium-browser 설치 위치를 환경 변수에 저장
ENV CHROMIUM_PATH /usr/bin/chromium-browser

# 시간을 서울로 변경 처리
RUN apk --no-cache add tzdata && \
        cp /usr/share/zoneinfo/Asia/Seoul /etc/localtime && \
        echo "Asia/Seoul" > /etc/timezone

# Set the lang
ENV LANG=ko_KR.UTF-8 \
    LANGUAGE=ko_KR.UTF-8

# node module 설치
RUN npm  install --unsafe-perm 

# docker 외부 OPEN 포트
EXPOSE 3000
CMD ["npm", "start"]

아마 나중에 다시 만날 문제일꺼 같습니다.

한글 꺠짐 문제는 늘 한번씩 돌아오네요.

참고자료

Posted by lahuman

댓글을 달아 주세요

[Mac TIP] OS 업데이트 이후 다시 설치해야 하는 xcode 재설치 하는 법!

Mac의 OS를 업데이트를 하고 나면 꼭 다음과 같은 오류를 만나게 됩니다.

xcode CommandLineTools을 분명히 설치 했음에도 발생합니다.

이럴때는 아래의 명령어로 삭제후 재설치 하여야 합니다.

$> sudo rm -rf /Library/Developer/CommandLineTools
$> sudo xcode-select --install

MAC OS 종특인듯...

Posted by lahuman

댓글을 달아 주세요

[TIP ReactJS] Material-UI에서 애니메이션을 제거하여 성능 향상 처리

얼마전 회사 내에서 ReactJS의 디자인 라이브러리에 대한 비교를 하였습니다.

비교 디자인 라이브러리 목록

  • ant design
  • Material-ui
  • React-Bootstrap

비교 결과

우선 React-Bootstrap의 경우 애니메이션 효과가 전혀 없기 때문에 동일한 랜더링 결과를 확인할 수 없다고 판단되었습니다.
따라서 Material-UI에서 애니메이션 효과를 제거하는 코드를 반영해보았습니다.

Material-UI에서 애니메이션 효과를 제거하는 코드

각 컴포넌트마다 애니메이션 효과를 제거할 수도 있고, 전체적으로 제거 할 수 있습니다.

아래는 모든 컴포넌트에서 애니메이션 효과를 제거하는 코드입니다.


import { createMuiTheme, ThemeProvider } from '@material-ui/core';

const theme = createMuiTheme({
  props: {
    // Name of the component ⚛️
    MuiButtonBase: {
      // The properties to apply
      disableRipple: true, // No more ripple, on the whole application 💣!
    },
  },
  transitions: {
    // So we have 'transition: none;' everywhere
    create: () => 'none',
  },
});

export default (props) => {
  <ThemeProvider theme={theme}>
    <div className={classes.root}>
    ....
    </div>
  </ThemeProvider>
}

결과

Material-UI에서 애니메이션 효과를 제거 후 UI 성능은 눈에 띄게 좋아졌습니다.

추가적으로 저성능 디바이스에서는 애니메이션 효과를 제거하고 사용하는 것을 추천합니다.

참고 자료

Posted by lahuman

댓글을 달아 주세요

수동으로 설치한 WSL 삭제 하기

보안프로그램을 피해서 WSL 설치하기!를 통해서 설치한 경우 제어판 > 앱에 Ubuntu가 표기 되지 않습니다.

압축을 풀었던 디렉토리를 삭제하고 다시 압축을 풀고 Ubuntu.exe 실행하면 그때부터는 0x80070003 메시지를 만나게 됩니다.

메뉴얼 삭제시에 windows의 wsl에 등록된 정보를 삭제하지 않았기 때문에 발생하는 문제입니다.

PowerShell에서 wsl을 삭제해주어야 됩니다.

# 설치된 wsl 목록 확인
PS C:\Users\admin> wslconfig.exe /l
Linux 배포용 Windows 하위 시스템:
Ubuntu-18.04(기본값)

# 설치된 wsl 목록 삭제
PS C:\Users\admin> wslconfig.exe /u Ubuntu-18.04
삭제중...

# 이후 확인하면 설치된 wsl목록이 없음
PS C:\Users\admin> wslconfig.exe /l
Windows Subsystem for Linux has no installed distributions.
Distributions can be installed by visiting the Windows Store:
https://aka.ms/wslstore

# 이후 Ubuntu 디렉토리 삭제 진행

메뉴얼 방식으로 설치된 WSL을 삭제를 위해서는 wslconfig.exe를 이용한 레지스트리 제거가 필요 합니다.

참고 자료

Posted by lahuman

댓글을 달아 주세요

한글 입력기 설정

기본적으로 이전에 진행한 Windows WSL에서 GUI 사용하기가 적용되어야 합니다.

우선 아래 명령어를 이용하여 한글 폰트를 설치 해야 합니다.

$ sudo apt-get install fonts-nanum fonts-nanum-coding fonts-nanum-extra

폰트가 설치 되었으면 uim을 설치 합니다.

uim 은 "universal input method"로 다국어 입력기 프레임워크 입니다.

기존에는 uim-byeoru를 함께 설치 하였는데, ubuntu 18.04에서는 uim-byeoru 패키지가 삭제 되고, uim에 Byeoru가 포함되어 있습니다.
출처 : 한글 입력기 uim-byeoru 패키지 없어짐

$ sudo apt-get install uim

이후 환경 설정에 다음을 추가 해야 합니다.

$ vi ~/.bashrc
# 가장 밑에 아래 내용을 추가

export XIM=uim

export XMODIFIERS=@im=uim

export UIM_CANDWIN_PROG=uim-candwin-gtk

export GTK_IM_MODULE=uim

export QT_IM_MODULE=uim

#

if [ $SHLVL -eq 1 ]; then

  uim-xim &

fi

파일을 저장하고, 다음 명령어로 환경변수를 반영합니다.

$ source ~/.bashrc

마지막으로 uim-pref-gtk 명령어를 이용해서 기본 IM을 Byeoru를 설정하고 변환 키를 셋팅 합니다.

기본 IM을 Byeoru로 설정

Byeoru 가 선택창 가장 아래부분에 있습니다.

전체 키와 벼루 키가 충돌이 일어 날수 있어서 제외

벼루 키 설정

이후 GUI로 띄운 프로그램에서 한글 입력이 문제 없이 됩니다.

오늘도 하나 배웠네요.

참고 자료

Posted by lahuman

댓글을 달아 주세요

Windows WSL에서 GUI 사용하기

기본적으로 GUI를 사용하려면 ssh를 통한 접근 후 사용해야 합니다.

Windows 10에서 Windows Subsystem for Linux(WSL) GUI를 띄우는(크롬, interlij) 작업을 하기위해서 다음과 같은 설정이 필요합니다.

SSH 서버 설치 & 설정

기본으로 설치되어 있는 SSH 서버는 동작을 제대로 하지 못함으로 완전히 제거하고 재설치 한다.

# 설치 전에 APT repository 업데이트
$> sudo apt-get update
$> sudo apt-get upgrade

# ssh를 완전히 삭제하고 재설치
$> sudo apt-get purge openssh-server
$> sudo apt-get install openssh-server

이후 /etc/ssh/sshd_config 파일을 열고 다음 항목들을 설정한다.

# /etc/ssh/sshd_config 파일 내
Port 22
Protocol 2
PermitRootLogin no
AuthorizedKeysFile  .ssh/authorized_keys
PasswordAuthentication yes
PubkeyAuthentication yes
ChallengeResponseAuthentication no
X11Forwarding yes
UseDNS no

마지막으로 ssh 서버를 재시작 하고 나면 ssh에 대한 재설치와 설정은 끝이다.

$> sudo service ssh --full-restart
$> sudo service ssh restart

GUI 사용하기

다음 명령어를 이용해서 Machine ID를 생성한다.

# ID 생성
$> sudo systemd-machine-id-setup
$> sudo dbus-uuidgen --ensure
# ID 확인
$> cat /etc/machine-id

x-window 구성요소 설치를 합니다.

$> sudo apt-get install x11-apps xfonts-base xfonts-100dpi xfonts-75dpi xfonts-cyrillic

기본 디스플레이 포트 설정을 위해서 ~/.bashrc에 디스플레이 환경변수를 설정합니다.

# ~/.bashrc
export DISPLAY=:0

이후 다음 명령어를 이용해서 디스플레이가 동작하는지 확인합니다.

$> xeyes

실행이 성공적으로 되면 눈이 뜨면서 마우스를 따라 눈동자를 움직입니다.

참고 자료

Posted by lahuman

댓글을 달아 주세요

Windows에서 개발을 편하게 하기 위한 WSL 설치 가이드

기본 설치 방법은 보안프로그램에 의해서 진행이 안될 수 있습니다.
하지만 PowerShell을 이용한 설치는 보안프로그램에 대하여 우회가 가능합니다.

뭔가 엄청 특별한 방법이 있는것은 아니고, 수동 설치 지침을 참조 하여 설치 하면 됩니다.

먼저 Linux용 Windows하위 시스템 기능을 사용하도록 설정해야 합니다.

관리자 권한으로 PowerShell을 열어 다음 명령어를 실행합니다.

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

설치를 하고 나면 재부팅을 해줘야 한다.

재부팅이후, 설치를 원하는 Linux 배포판을 명령줄을 이용해서 다운로드 받습니다.

아래 명령어는 Ubuntu 18.04 버전으로 진행한 명령어 입니다.

Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1804 -OutFile Ubuntu.appx -UseBasicParsing

설치가 끝나면 다음 명령어로 설치 할수 있다고 합니다.

Add-AppxPackage .\Ubuntu.appx

하지만!!! 설치 이후 실행을 하면 "File system Error (12030)"가 발생합니다.

이럴 경우 우선 기존에 설치된 배포판 버젼을 삭제 하세요.

그리고 다운로드 받았던 앱 파일 Ubuntu.appx의 파일 확장자를 .zip로 변경하세요.

압축을 풀고 해당 디렉토리에서 ubuntu1804.exe 파일을 실행하면 됩니다.

참고 자료

Posted by lahuman

댓글을 달아 주세요