개요

C# Application에서 C++ Dll을 호출하기 위해서는 마샬링 과정이 필수적이다. 또한, 마샬링 과정에서 Calling Convention이 조율되지 않으면 스택에서 오류가 발생하는데, 어떻게 이러한 문제가 발생하는 것인지 알아보자.

목표

  1. 마샬링이 무엇인지 설명할 수 있다.
  2. Calling Convention이 무엇인지 설명할 수 있다.

C# Application과 C++ Dll의 통신

마샬링(Marshalling)

마샬링이란 한 객체의 메모리에서의 표현방식을 저장 또한 전송에 적합한 다른 데이터 형식으로 변환하는 과정입니다.

이는 데이터를 서로 다른 프로그램간에 전달할 필요가 있을 경우 사용합니다.

즉, 이는 직렬화와 유사하며 직렬화된 한 객체로, 멀리 떨어진 객체와 통신하기 위해 사용합니다.

이렇듯 복잡한 통신을 단순화하여 쉽게 데이터를 주고받을 수 있도록 해주는 것이 마샬링 입니다.

따라서, Managed Language인 C#과, Unmanaged Language인 C++ 프로그램 간 통신을 위해서는, 어떤 타입으로 데이터를 송수신할 지 마샬링을 통해서 조율할 수 있는 것이다.

마샬링과 직렬화는 무엇이 다른가?

마샬링은 객체의 메모리 구조에서 저장 또는 전송에 적합한 다른 데이터 형식으로 변환하는 과정

  • 마샬링은 프로그램간 이동할 때 사용하는 변환 과정

→ 이 과정에서 비마샬링할 때 객체의 복사본을 얻을 수 있게 원격 객체의 상태와 코드베이스를 기록한다.

직렬화는 객체의 상태를 저장하기 위해 객체를 바이트 스트림(Byte Stream) 형태로 변환하는 것

  • 객체에 저장된 데이터를 스트림 형태로 쓰기위해 연속적인 데이터로 변환하는 것이다

마샬링은 직렬화보다 더 큰 개념으로 사용된다. 그래서 직렬화 가능하거나 리모트 가능한 모든 객체는 마샬링이 가능하다.

→ 큰 차이는 직렬화는 객체가 대상이고 마샬링은 변환 그 자체의 목적으로 코드베이스를 기록하는데 차이가 있다.

함수 호출 규약이란?

호출 규약은 어떻게 서브루틴이 그들의 호출자(caller)로부터 변수를 받고, 어떻게 결과를 반환하는지에 대한 규약이다.

  • 프로그래밍 언어, 플랫폼 마다 각기 다른 호출 규약을 사용한다. (CPU 아키텍쳐 + 운영체제)
  • 여러 언어에서 작성한 모듈을 병합할 때, 또는 작성 장소가 다른 언어의 운영 체제 및 라이브러리 API를 호출할 때 문제를 일으킬 수도 있다
  • 호출자(caller)와 피호출자(callee)가 사용하는 호출 규약을 조율하는데 관심을 가져야 한다.
  • 단일 프로그래밍 언어를 사용하는 프로그램에서 여러 개의 호출 규약을 사용할 수 있다.

왜 이렇게 다양한 함수 호출 규약이 존재하는가?

왜 이렇게 다양한 함수 호출 규약이 존재하는지 궁금하여 Stack Overflow 문서를 확인하던 중 아래의 답변을 발견했다.

호출 규칙은 수십 년에 걸쳐 다양한 언어와 하드웨어에 맞게 설계되었습니다. 그들은 모두 다른 목표를 가지고 있었습니다. cdecl은 printf에 대한 가변 인수를 지원합니다. stdcall로 인해 코드 생성이 더 작아졌지만 가변 인수는 없었습니다. Fastcall은 구형 시스템에서 하나 또는 두 개의 인수만 사용하여 간단한 함수의 성능을 크게 향상시킬 수 있습니다(그러나 오늘날에는 속도가 거의 향상되지 않습니다). x64가 도입되었을 때 적어도 Windows에서는 단일 호출 규칙을 갖도록 설계되었습니다.

즉, 언어와 하드웨어의 발전 및 다른 목표를 위하여 여러개의 Calling Convention(cdecl, stdcall, fastcall…)이 설계되었고, 현대의 64bit 운영체제에서는 단일 호출 규칙을 사용한다고 한다.

그렇다면 현재 사용되고 있는 단일 호출 규약은 무엇일까?

64bit 기본 함수 호출 규약

MS 공식 문서의 x64 calling convention 페이지에 의하면, 현재 기본적으로 사용되는 함수 호출 규약은 __vectorcall 이라는 호출 규약을 사용하는 것으로 보인다. 또한, __vectorcall 문서에 의하면 이 __vectorcall의 경우 __fastcall 호출 규약을 베이스로 만들어진 것으로 보인다.

<aside> 💡 The __vectorcall calling convention specifies that arguments to functions are to be passed in registers, when possible. __vectorcall uses more registers for arguments than [__fastcall](<https://learn.microsoft.com/en-us/cpp/cpp/fastcall?view=msvc-170>) or the default x64 calling convention use.

</aside>

마무리

마샬링과정에서 함수 호출 규약을 조율하지 않는다면 호출자와 피호출자간의 스택 정리 방법이 달라서 문제가 발생할 수 있다. 예를들어 호출자는 __stdcall 호출 규약을 사용하고, 피호출자는 __cdecl 호출 규약을 사용한다면, 호출자도 스택 관리에 관여하고, 피 호출자도 스택 관리에 관여하기 때문에 문제가 발생할 수 밖에 없는 것이다.

Reference

https://hwanine.github.io/network/Marshalling/

https://velog.io/@wlsrhkd4023/CS-마샬링Marshalling

https://stackoverflow.com/questions/3428332/why-are-there-so-many-different-calling-conventions

https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170

https://learn.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-170

'TIL' 카테고리의 다른 글

SPOPARTY 서비스 파일 업로드, 삭제 장애 대응  (1) 2024.03.02
Jenkins Container 접속 http 경로 변경하기  (0) 2024.02.28
[키워드 정리] VNC VS RDP, ICMP  (0) 2022.03.09
JavaScript ES6 문법 정리  (0) 2021.10.17
2021.09.11  (0) 2021.09.11

VNC와 RDP

개요

팀 회의 도중 생소한 키워드를 정리하기 위해 글을 씁니다.

VNC vs RDP

VNC (Virtual Network Computing)

VNC는 RFB(Remote Frame Buffer)프로토콜 방식을 이용해 서버에서 보낸 화면 정보를 클라이언트에 설치된 그래픽 라이브러리를 이용해 그리는 방식이다.

  • 사용을 위해 RFB를 전송 가능한 프로그램, 전달 받는 프로그램 (server, client)가 필요하다.
  • 원격에서 화면을 보는 기능만 지원하며, 클라이언트 별로 세션을 가지지 못한다. (여러 PC에서 동시에 접속한다면 하나의 화면을 공유하게 된다.)
  • VNC는 주로 클라우드 상에서 동작하는 서버 VM을 동작하기 위해서 사용하는 프로토콜이다.

RDP (Remote Desktop Protocol)

  • 마이크로소프트에서 자체적으로 개발한 프로토콜이며 VNC와 다른점은 사전 설정에 따라 클라이언트 세션을 여러개 생성가능하다는점이다.
  • 과거에는 Windows 운영체제만 지원했지만, 현재 Linux, mac, Android 등 다양한 운영체제를 지원한다.

Reference : https://selfish-developer.com/entry/VNC%EC%99%80-RDP

ICMP (Internet Control Message Protocol)

ICMP는 TCP/IP에서 IP 패킷을 처리할 때 발생되는 문제를 알려주는 프로토콜이다.
IP에는 오로지 패킷을 목적지에 도달시키기 위한 내용들로만 구성되어 있다.
따라서 정상적으로 목적지 호스트에 도달하는 경우에는 IP에서 통신이 성공하고 종료되므로 별도의 기능은 없다.

  • 통신 유무 확인시 자주 사용되는 Windows의 ping 기능도 이 ICMP를 사용한다고 한다.
  • 통신이 실패했을 떄 애러 메세지를 통해 통신에 실패하는 원인을 짐작할 수 있다.

'TIL' 카테고리의 다른 글

Jenkins Container 접속 http 경로 변경하기  (0) 2024.02.28
함수 호출 규약(Calling Convention)과 마샬링(marshalling)  (1) 2023.10.17
JavaScript ES6 문법 정리  (0) 2021.10.17
2021.09.11  (0) 2021.09.11
2021.09.09  (0) 2021.09.10

JavaScript ES6 문법 정리

const and let

ES6에서 추가된 변수 선언 방법입니다.

변수 재 선언

var의 경우 변수를 한번 더 선언했음에도 오류가 발생하지 않습니다.

var foo = "foo"
console.log(foo) // foo
var foo = "pee"
console.log(pee) // pee

let의 경우 변수를 한번 더 선언할 경우 오류가 발생합니다. (const의 경우도 마찬가지로 오류가 발생합니다.)

let foo = "foo"
console.log(foo)
let foo = "pee" // Uncaught SyntaxError: Identifier 'foo' has already been declared
console.log(foo)

const 와 let 차이점

let의 경우 값의 재할당이 가능하지만, const에서는 값을 재할당 할 수 없습니다.

let foo = "foo"
console.log(foo)
// let foo = "pee" // Uncaught SyntaxError: Identifier 'foo' has already been declared
// console.log(foo)
foo = "pee"
console.log(foo)

const foo = "foo"
console.log(foo)
foo = "pee" // Uncaught TypeError: Assignment to constant variable.
console.log(foo)

var의 경우 변수 선언이 사용보다 늦어도 오류가 발생하지 않습니다.

console.log(foo) // undefined
var foo = "foo"

const와 let의 경우

console.log(foo) // Uncaught ReferenceError: Cannot access 'foo' before initialization
let foo = "foo" 

호이스팅

자바스크립트에서는 소스코드를 실행하기전에 소스코드 평가 과정이라는 것을 거치게 됩니다.
이 때 모든 변수와 함수의 선언을 스코프 최상단으로 올리게 되는데, 이를 호이스팅이라고 말합니다.

위 처럼 var이 undefined로 오류가 발생하지 않고 실행된 이유는 호이스팅 때문인데,
위의 var을 사용한 변수 선언은 실제로 아래와 같이 표현됩니다.

var foo
console.log(foo) // undefined
foo = "foo"

그렇다면 let과 const는 호이스팅이 발생하지 않을까?

let, const도 호이스팅이 발생합니다.
그러나 var 처럼 undefined의 할당은 이루어지지 않고, 변수의 선언만 이루어집니다.
이게 구글링을 하다보면 호이스팅 발생한다는 사람들도 있고 아니라는 사람들도 있는데;;
Javascript 공식문서에서 호이스팅이 발생한다고 설명하고 있습니다.
다른 글들에 속지마시길!

화살표 함수

ES6에서 새로 등장한 함수를 선언하는 방법으로 전통적인 함수표현의 간편한 대안이다. (더 간결하다.)

ES5 함수 선언

var foo = function fooFunction(x) { return x * x } 

ES6 화살표 함수 선언

var foo = x => { return x * x }

const(or var or let) 변수명 = (매개변수1, 매개변수2) => { 함수 몸통 }

  • 매개변수가 없을 경우 : () (빈 소괄호를 이용)
  • 매개변수가 하나일 경우 : 매개변수 (소괄호 생략 가능)

람다식을 아신다면 람다식과 비슷하다고 볼 수 있을 것 같습니다.

템플릿 리터럴

문자열을 연결하기 위해 더하기(+) 연산자를 사용할 필요없이
백틱(`)을 사용하여 문자열 내에서 변수를 사용할 수 있습니다.

이전 문법 

function foo(name, age) {
    return name + "의 나이는 " + age + "입니다." 
}
console.log(foo("찬해형", 27)) // 찬해형의 나이는 27입니다.  

템플릿 리터럴 이용

const foo = (name, age) => {
    return `${name}의 나이는 ${age}입니다.`
}
console.log(foo("찬해형", 27)) // 찬해형의 나이는 27입니다.

기본 매개변수

매개 변수를 쓰지 않은 경우 함수의 매개변수에 기본값이 정의되어 있다면 기본값을 사용하도록 합니다.
const foo = (age = 5) => {
return 나이는 ${age}
}
console.log(foo()) // 나이는 5

배열 및 객체 비구조화 할당

비구조화를 통해 배열 또는 객체의 값을 새 변수에 더 쉽게 할당할 수 있습니다.

비구조화 할당을 사용하지 않을 경우 각각 변수 생성 후 object의 key에 접근하여 할당해야합니다.

const object = {
chanhae: "찬해",
inho: "인호",
hyeonwoo: "현우",
seungje: "승제"
}

const ch = object.chanhae
const ih = object.inho
const hw = object.hyeonwoo
const sj = object.seungje

console.log(ch)
console.log(ih)
console.log(hw)
console.log(sj)

비구조화 할당을 사용할 경우 코드가 훨씬 간단해집니다.

const object = {
chanhae: "찬해",
inho: "인호",
hyeonwoo: "현우",
seungje: "승제"
}

const {chanhae, inho, hyeonwoo, seungje} = object

console.log(chanhae)
console.log(inho)
console.log(hyeonwoo)
console.log(seungje)

만약 객체 내의 key값과 다른 이름으로 사용하고 싶다면 아래와 같이 합니다.

const {chanhae: ch, inho, hyeonwoo, seungje} = object

console.log(ch)
console.log(inho)
console.log(hyeonwoo)
console.log(seungje)

// 콜론과 함께 사용할 이름 지정. 
// 만약 객체의 key값과 다르게 사용하면 undefined가 반환됩니다.

비구조화 할당은 배열에서도 같은 방법으로 적용 가능합니다.

나머지 매개변수 및 확장 연산자

나머지 매개변수

현재 인덱스부터 마지막까지 하나의 변수에 할당하고 싶을 때 사용가능합니다.

const arr = ["찬해", "인호", "승제", "현우"]

const [ch, ih, ...rest] = arr

console.log(ch) // 찬해
console.log(ih) // 인호
console.log(rest) // ["승제", "현우"]

만약 arr의 값이 변경되면 나머지 매개변수 연산을 통해 얻은 배열의 값이 변경될까?

나머지 매개변수 사용
// 배열의 값을 변경하기위해 let 으로 선언
let arr = ["찬해", "인호", "승제", "현우"]
// 나머지 매개변수 이용하여 배열 복사
let [ch, ...rest] = arr
// 승제 자리 찬해로 변경
arr[2] = "찬해"

console.log(arr) // ["찬해", "인호", "찬해", "현우"]
console.log(rest) // ["인호", "승제", "현우"]

let arr = ["찬해", "인호", "승제", "현우"]

rest에 arr 바로 대입
let rest = arr

arr[2] = "찬해"

console.log(arr) // ["찬해", "인호", "찬해", "현우"]
console.log(rest) // ["찬해", "인호", "찬해", "현우"]

나머지 매개변수 연산에서는 arr의 값이 변경되어도 rest배열의 값은 변경되지 않았으므로, 깊은 복사가 일어난것을 알 수 있습니다.
배열을 그대로 변수에 대입할 경우, arr의 값이 변경되면 rest 배열의 값도 변경되었습니다.

전개 연산자

const arr = ["찬해", "인호"]
const arr2 = ["승제", "현우"]

const newarr = [...arr, ...arr2]
console.log(arr) // ["찬해", "인호"]
console.log(arr2) // ["승제", "현우"]
console.log(newarr) // ["찬해", "인호", "승제", "현우"]

배열을 이어 붙일 때 전개연산자를 통해 쉽게 이어붙일 수 있다.
객체에서도 가능!

const obj = {ch: "찬해", ih: "인호"}
const obj2 = {sj: "승제", hw: "현우"}

const newobj = {...obj, ...obj2}
console.log(obj) // { ch: "찬해",ih: "인호" }
console.log(obj) // { sj: "승제",hw: "현우" }
console.log(newobj) // { ch: "찬해",ih: "인호", sj: "승제", hw: "현우" }

프로미스

비동기 코드를 사용할 때 쓰기 좋은 ES6문법입니다.
이전에는 라이브러리로 이용할 수 있었으나, ES6부터 언어 차원에서 지원하게 되었다.
책에서는 ES5에서 기본으로 제공한다고 나와있는데.. 구글링하면 다 ES6부터라고 함;;
스택 오버플로우 문서찾아보니 ES6부터 지원하는게 맞는것 같음!

프로미스를 사용하지 않고 비동기 함수를 수행하는 방법

var async1 = function(param, callback) { callback(param*2); }
var async2 = function(param, callback) { callback(param*3); }
var async3 = function(param, callback) { callback(param*4); }

var start = 1;

async1(start, result => {
    async2(result, result => {
        async3(result, result => {
            console.log(result); // 24
        });
    });
});

보는것과 같이 callback 함수가 중첩되면서 들여쓰기 때문에 코드 가독성이 매우 떨어집니다.

function async1 (param) {
return new Promise(function(resolve, reject) { // 프로미스 객체 생성, resolve는 성공, reject는 실패
    resolve(param*2); // 요청이 성공했을 때 resolve를 보낼 수 있음. 만약 에러가 발생했다면 reject()로 오류전달
    });
}
function async2 (param) {
    return new Promise(function(resolve, reject) {
        resolve(param*3);
    });
}
function async3 (param) {
    return new Promise(function(resolve, reject) {
        resolve(param*4);
    });
}

var start = 1;
async1(start)
    .then(async2)
    .then(async3)
    .then(result => {
        console.log(result); // 24
    })
    .catch((err) => {
        console.log(err)
    });

프로미스 요청은 then 메소드로 비동기 요청을 이어붙일 수 있습니다. 이전 promise가 resolve되었다면 그 다음 promise가 실행됩니다.
여러개의 프로미스 체인중 하나라도 reject되었다면 마지막에 달린 catch()로 내려가서 에러를 처리합니다.

fetch 메서드로 promise 체인 사용해보기

function request() {
fetch('https://api.github.com/orgs/nodejs', {
    method: 'GET', // url에 get 요청 보냄.
})
.then(response => { // response 받은 값을 리턴
    return response.json();
})
.then(data => { // 리턴받은 값을 로그로 찍음
    console.log(data);
});
}

request();

실행가능한 코드는 모두 JSFiddle에서 테스트 했습니다.

Reference

https://velog.io/@kimhscom/JavaScript-%EC%9E%90%EC%A3%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-ES6-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC

https://velog.io/@recordboy/%EC%A0%84%EA%B0%9C-%EC%97%B0%EC%82%B0%EC%9E%90Spread-Operator

https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

https://han41858.tistory.com/11

'TIL' 카테고리의 다른 글

함수 호출 규약(Calling Convention)과 마샬링(marshalling)  (1) 2023.10.17
[키워드 정리] VNC VS RDP, ICMP  (0) 2022.03.09
2021.09.11  (0) 2021.09.11
2021.09.09  (0) 2021.09.10
2021.09.08  (0) 2021.09.08

JSX = Javascript + XML

Javascript와 XML구문을 결합해 사용하는 코드를 JSX 라고한다.

자바스크립트 표준에 JSX 구문이 없지만, 포함된 것 처럼 동작할 수 있는 이유는 ESNext 자바스크립트 컴파일러인 바벨(babel)이 플러그인 구조로 동작하기 때문이다,

바벨은 ESNext 자바스크립트 코드를 만나면 파이프라인 형태로 동작하여 이해할 수 있는 구문만 컴파일하여 자바스크립트로 변환한다.

페이스북은 JSX 구문을 컴파일 하고자 @babel/plugin-trnasform-react-jsx 라는 바벨 플러그인을 제공한다.

 

jsx 구문이 있는 타입스크랍트 코드는 .tsx 여야하며, 다음 임포트 문이 필요하다.

import React from 'react'

 

React.createElement 사용은 아래의 형태로 구현하는데, 이를 JSX 형태로 변환해보자.

Virtuala_DOM_Object = React.createElement(component_name, attribute_object, child_component)

<component_name>child_component</component_name> // JSX

그러므로 JSX 객체는 실제로는 createElement를 호출하는 것이다.

 

표현식과 실행문 그리고 JSX

 

표현식 : 1, true, "Hello World!"처럼 값으로 평가되는 어떤 것.

실행문 : if, switch/case, for 같은 그 자체로는 값이 아닌 것.

 

JSX문 안에서는 실행문을 사용하면 오류가 발생한다.

<SafeAreaView>

{console.log("test")} // error

</SafeAreaView>



<SafeAreaView>

if (isLoading) {

do something.. // error

}

</SafeAreaView>

 

오류가 발생하는 이유는 JSX 코드를 구성하는 한줄 한줄이 모두 React.CreateElement 호출 코드로 변환되어야 하는데, console.log는 변환이 불가능하므로.

 

오류를 해결하는 방법으로는 이러한 구문을

+ JSX 문 바깥에 두는 방법

+ 조건문을 단축 평가 코드로 바꿔 문제 해결

ex)

<SafeAreaView>

{isLoading && <Text>loading</Text>}

{!isLoadiong && <Text>Hello World!</Text>}

</SafeAreaView>

+ JSX 문을 변수에 담아 문제 해결

ex)

const children = isLoading ? (

<Text>loading..</Text>

) : (

<Text>Hello World!</Text>

)

 

컴포넌트와 속성 이해하기

faker 외부 패키지 : 가짜 데이터를 만드는 패키지

자바스크립트로 만들어진 패키지이므로, 타입스크립트에서 사용하려면 @types/faker 타입 라이브러리 사용

 

사용자 컴포넌트

객체지향 프로그래밍에서 컴포넌트는 UI를 담당하는 클래스를 의미합니다.

오랫동안 리액트와 리액트 네이티브 프레임워크에서는 객체지향 방식인 클래스 컴포넌트를 사용했습니다.

 

그러다 함수로 구현되는 함수 컴포넌트가 도입되었고, 버전 16.8 에서 리액트 훅 기능이 새로 도입되면서 함수 컴포넌트 + 리액트 훅을 사용할것을 장려하고 있습니다.

 

클래스 컴포넌트

 

반드시 Component 클래스를 상속 받아야한다.

render method는 반드시 null, undefined, React.createElement 호출로 얻은 반환값이나 JSX 문 중 하나를 반환해야한다.

 

화살표 방식 함수 컴포넌트

 

클래스 컴포넌트의 render 메소드는 함수형 컴포넌트에서는 함수 몸통에 구현하면된다. (같은 역할을 한다.)

요즘 많이 사용되는 리액트 훅을 사용할 수 있다. (클래스 컴포넌트는 사용할 수 없음.)

 

속성이란?

속성이란 클래스의 멤버변수를 의미한다.

재렌더링이란 리액트와 리액트 네이티브에서 바뀐 속성값을 화면에 반영하는 것을 의마한다.

리액트와 리액트 네이티브에서 속성은 클래스 속성 + 재렌더링을 의미한다.

 

 

이제서야 함수형 컴포넌트와 클래스 컴포넌트 구분할 수 있겠다.... 화이팅하자

'TIL' 카테고리의 다른 글

[키워드 정리] VNC VS RDP, ICMP  (0) 2022.03.09
JavaScript ES6 문법 정리  (0) 2021.10.17
2021.09.09  (0) 2021.09.10
2021.09.08  (0) 2021.09.08
[TIL] python OpenCV - threshold 함수로 경계선 얻기  (0) 2021.07.26

리액트 네이티브 개발에서 사용하는 명령

  • npm i

package.json 파일에 명시된 패키지를 node_modules 디렉터리에 설치

설치한 패키지는 android나 ios 디렉터리의 네이티브 모듈에서 동작하는 파일을 가진다.

  • npm pod-install

objc와 같은 c계열 언어는 원격 저장소에서 패키지를 내려받아 설치하는 기능이 없다.

따라서 pod 프로그램을 통해 패키지를 설치해야하므로 사용

  • npm start

npm run android, npm run ios 명령은 네이티브 부분 앱을 빌드하여 에뮬레이터에 설치하고 자동으로 실행한다.

에뮬레이터에 설치된 앱은 처음 실행될 때 메트로 서버에서 ES5자바스크립트 코드를 내려받는다.

그러므로 위의 명령을 실행하기 전에 npm start로 메트로 서버를 실행한다.

npm 과 npx

npm : Package Manager (관리)

npx : Package Runner (실행)

 

npx는 npm의 5.2.0 버전부터 새로 추가된 도구. 따라서 npm과 비교대상이 아닌 npm을 좀 더 편하게 사용하기 위해서 npm에서 제공해주는 하나의 도구.

 

등장 배경

 

npm 패키지 설치할 때 두가지 케이스가 있다.

  1. 전역으로 패키지를 설치하여 의존성 라이브러리들을 전체적으로 관리하는 방법
  2. 특정 프로젝트에만 의존성 라이브러리를 설치하는 방법

npx를 언제 사용할까?

  • npm run-script를 사용하지 않고 로컬에 설치된 패키지를 사용할 경우
  • 일회성 명령으로 패키지를 실행할 경우 -> 로컬에 설치된 패키지가 없다면 install및 호출을 한번에 해준다.
  • gist_based scripts를 실행할 경우 -> gist라는 곳에 스크립트를 올리고 npx {gist url}로 쉽게 코드 실행이가능하다.
  • 특정 노드 버전의 스크립트를 실행할 경우

npm run ios 빌드오류

React Native- Failed to build IOS project. We ran "xcodebuild" command but it exited with error code 65

위와 같은 오류가 발생했고, 구글링 과정에서 ios/pods/podfile 수정을 통해 해결할 수 있다고 해서 변경했다.

use_flipper ~

post_install do |installer|

flipper_post_install(installer)

end

 

이부분 삭제하고 저장.

 

수정 후

pod deintegrate

pod install

 

여기까지 수행하고 오류 그대로 발생. 그러나 오류코드 하단에

 

nvm is not compatible with the "npm_config_prefix" environment variable: currently set to "opt/homebrew"

Run 'unset npm_config_prefix' to unset it

 

이라는 메세지가 있어서

unset npm_config_prefix

수행 후 빌드 성공했다.

'TIL' 카테고리의 다른 글

JavaScript ES6 문법 정리  (0) 2021.10.17
2021.09.11  (0) 2021.09.11
2021.09.08  (0) 2021.09.08
[TIL] python OpenCV - threshold 함수로 경계선 얻기  (0) 2021.07.26
[TIL] python OpenCV - 1  (1) 2021.07.26

Git Flow

 

회사에서 사용하는 Git Flow 사용에 대해 오해가 있었다. 맨날 나만몰라...🥲

 

오늘 처음으로 팀 미팅이 있었는데, 회사의 개발 전략에 대해서 소개했었다.

Git Flow에 대해 소개하는 시간이 있었는데, Origin Remote Repository와 Remote Branch의 개념이 헷갈렸었다. 하 소개하는놈이

Github 의 React Repository의 경우로 생각하면 Upstream Remote Repositry의 경우 레포지토리의 주인인 Facebook이 React Repository의 Upstream Remote Repository일 것이다.

이를 내가 fork 할 경우 내 계정에 생성된 React 레포지토리가 Origin Remote Repository가 될것이다.

여기서 내 github에 있는 레포지토리를 clone 해서 로컬 PC에 저장하면 Local Repository가 된다고 보면된다.

 

항상 좋은 분위기로 정답을 이끌어주는 찬해형에게 감사를... ㅠ

 

Expo VS React-Native

 

Expo의 장점

- Expo앱을 개인 핸드폰에 설치하여 장치에서 쉽게 테스트, 디버깅이 가능하다

- Xcode, Android Studio 설치와 개발자 계정, signing.. 등의 번거로운 과정없이 바로 개발 가능하다. (이 부분은 구글링을 통해 검증하지 못했다.)

 

Expo 단점

- RN의 완전한 기능을 사용할 수 없다. (EXPO에서 제공하는 API만 사용가능하다.)

- OAuth2.0, Map API 사용에 어려움이 있다.

- 빌드시간이 오래걸린다. (찬해형 피셜 최악이었다고한다.)

 

사실 Expo의 장점에 대해서 크게 이점이라고 다가오는게 없었기도 했고, 구글의 방대한 자료(한국어 한정)에서도 Expo 사용에 긍정적인 반응이 크게 없었던것으로 봐서는 RN만으로 개발을 하는게 안전하지 않을까 싶다.

 

팀에 꼭 필요한 사람이 되자.

오늘 발표 절어서 매우 부끄러우니 다음에는 더 잘 할 수 있도록 하자.

좀더 노력하자. (맨날 핑계대지말고 좀 하자)

 

 

Reference

https://velog.io/@max9106/React-Native-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8Creact-native-%EB%91%90-%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95-c4k0gxe0tc

 

[React Native] 리액트 네이티브(react native) 두 가지 방법 #1 Expo CLI

리액트 네이티브 개발 방법 리액트 네이티브는 아래와 같이 2가지 개발 방법이있다. Expo CLI React Native CLI Expo란? 쉽게 말해, 리엑트 네이티브로 하는 개발을 쉽게 할 수 있게 해주는 것이다. 리엑

velog.io

https://floydkim.github.io/2019-05-04-React-Native-EXPO%EC%99%80-%EC%9D%B4%EB%B3%84%ED%95%98%EA%B8%B0/

 

React native : expo와 이별하기

EXPO와 이별하기 React-Native를 이용해 모바일 앱을 만들 때, EXPO는 개발자가 앱 코딩을 빨리 시작할 수 있도록 도와줍니다. EXPO 없이 React-Native만으로 개발을 시작하려면 Xcode나 Android Studio를 설치하

floydkim.github.io

https://medium.com/official-podo/expo%EB%A1%9C-%EC%95%B1-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B8-%ED%9B%84%EA%B8%B0-vs-vanilla-react-native-fc20c8dac937

 

expo로 앱 만들어본 후기(vs vanilla react-native)

함께해서 즐거웠고 다신 만나지 말자✋

medium.com

 

'TIL' 카테고리의 다른 글

2021.09.11  (0) 2021.09.11
2021.09.09  (0) 2021.09.10
[TIL] python OpenCV - threshold 함수로 경계선 얻기  (0) 2021.07.26
[TIL] python OpenCV - 1  (1) 2021.07.26
외부에서 내 컴퓨터 접속하기 (apache, 포트포워딩)  (1) 2021.03.29

이미지 경계선 얻기 - cv2.threshold()

 

우선 피포페인팅 도안을 생성하기 위해 도안이 될 이미지에서 선을 따는 작업이 필요했는데, 이를 도와줄 함수로 

cv2.threshold() 함수가 적절해 보여서, 사용하기로 했다. 비슷한 기능을 할 만한 함수로 cv2.canny() 함수가 있었는데, 다음 장에서 차이

threshold는 구글 번역기에서는 한계점 이라고 해석되는데, 구글링을 통해 관련 문서를 보면 임계점(사실 같은뜻이지만?) 이라고 많이 부르는 것 같다. 

 

임계점이라는 의미를 알았으니, OpenCV doc에서 cv2.threshold() 함수의 설명과 파라미터에 대해 알아보자.

 

문서의 내용을 간단히 요약하면, 

"픽셀 값이 임계값보다 작으면 0으로 설정되고, 그렇지 않으면 최대값으로 설정됩니다."

이 부분이 메인이라고 볼 수 있을 것 같다.

 

파라미터를 살펴보자.

cv2.threshold(src, thresh, maxval, type)

return value : retval, dst

parameter
src - 첫 번째 인수는 회색조 이미지여야 하는 소스 이미지 입니다.
thresh - 두 번째 인수는 픽셀 값을 분류하는 데 사용되는 임계값입니다.
maxval - 세 번째 인수는 임계값을 초과하는 픽셀 값에 할당되는 최대값입니다.
type - OpenCV는 함수의 네 번째 매개변수에 의해 제공되는 다양한 유형의 임계값을 제공합니다. 위에서 설명한 기본 임계값은 cv.THRESH_BINARY 유형을 사용하여 수행됩니다 . 

return value
retval - 첫 번째는 사용된 임계값이고
dst - 두 번째 출력은 임계값 이미지 입니다

 

OpenCV 문서에 아주 상세하게 설명되어 있다.

 

네번째 파라미터인 type을 변경해가면서 테스트를 해볼텐데, 나는 백예린님의 팬이므로 백예린님 사진을 통해 type을 변경해가면서 비교해보자.

 

코드의 출처는 OpenCV docs 문서이며, 이미지의 경로만 변경했다.

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('D:\yerin.jpg',0)
ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
ret,thresh2 = cv.threshold(img,127,255,cv.THRESH_BINARY_INV)
ret,thresh3 = cv.threshold(img,127,255,cv.THRESH_TRUNC)
ret,thresh4 = cv.threshold(img,127,255,cv.THRESH_TOZERO)
ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray',vmin=0,vmax=255)
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

 

 

내가 원하는 피포페인팅의 도안을 위해서는 BINARY type을 사용하는게 맞아보인다.

 

사실 지금 사용하고 있는 경계선을 얻어내는 방식은 cv2.canny()함수를 사용하고 있는데 프로토타입이 완성되면

품질 향상을 위해 threshold 함수도 고려해볼 수 있어보인다.

 

이상으로 오늘의 포스팅은 끗 ㅎㅅㅎ

 

Reference

 

https://docs.opencv.org/4.5.2/d7/d4d/tutorial_py_thresholding.html

 

OpenCV: Image Thresholding

Goal In this tutorial, you will learn simple thresholding, adaptive thresholding and Otsu's thresholding. You will learn the functions cv.threshold and cv.adaptiveThreshold. Simple Thresholding Here, the matter is straight-forward. For every pixel, the sam

docs.opencv.org

https://opencv-python.readthedocs.io/en/latest/doc/09.imageThresholding/imageThresholding.html

 

이미지 임계처리 — gramman 0.1 documentation

기본 임계처리 이진화 처리는 간단하지만, 쉽지 않은 문제를 가지고 있다. 이진화란 영상을 흑/백으로 분류하여 처리하는 것을 말합니다. 이때 기준이 되는 임계값을 어떻게 결정할 것인지가 중

opencv-python.readthedocs.io

 

'TIL' 카테고리의 다른 글

2021.09.09  (0) 2021.09.10
2021.09.08  (0) 2021.09.08
[TIL] python OpenCV - 1  (1) 2021.07.26
외부에서 내 컴퓨터 접속하기 (apache, 포트포워딩)  (1) 2021.03.29
C언어에서 배열의 크기를 변수로 선언할 수 있을까?  (5) 2019.10.29

2021.07.26

오늘부터 토이 프로젝트로 개발중인 P4Maker를 개발하면서 배운 점들을 기록하려고 합니다.

개발하게된 이유는 가지고있는 피포 페인팅이 완성 된 후 새로운 그림을 그리고 싶은데, 마음에 드는 도안이 없어서

직접 개발해보면 어떨까 싶은 생각에 개발하게 되었습니다.

 

오늘부터 화이팅 해보자 ^0^..

 

컴퓨터 공학 전공이 아닌 학교 친구가 통신에 대해서 여쭤봐서, 실시간으로 안드로이드 기기와 통신할 수 있는 방법을 알아야 했는데, 내 컴퓨터를 웹서버로 만들고 외부에서 접속하는 방법을 간단하게 알아보았다.

 

1. apache 설치 및 환경설정

 

https://www.apachelounge.com/download/ 아파치 공식 웹 사이트에 접속하여 아파치를 다운로드한다.

 

다운로드 후 apache24 폴더를 원하는 경로에 지정해준다. 나는 D:\Apache24 로 설정했다.

그 후 conf 폴더로 이동하여 httpd.conf 에서 몇가지 설정을 해준다.

 

폴더 경로를 아래와 같이 변경해준다.

Define SRVROOT "d:/Apache24"

그리고 포트를 변경하고 싶다면 LISTEN 을 검색한다. 기본으로 80으로 설정되어 있지만, 나는 8080으로 변경해줬다.

Listen 8080

 

그 후 D:\Apache24\bin 폴더에서 httpd.exe 파일을 실행해준다.

 

localhost에 접속하여 화면이 잘 나오는것을 확인하자.

 

2. 포트포워딩 설정하기

 

여기까지 설정이 되었다면 다음은 포트포워딩을 할 차례이다. 

 

필자는 딜라이브 공유기를 사용하므로 딜라이브 공유기 환경설정 페이지로 이동하겠다.

 

http://192.168.200.254/ 로 접속하여 네트워크 > 포트 포워딩 페이지에서 아래와 같이 설정한다.

 

설명 : 본인이 원하는 이름으로 설정. 나는 develop으로 설정했다.

ip주소 : cmd 창에서 ipconfig 입력 후 IPv4 주소를 입력한다.

포트번호 : 위에 설정한 포트번호와 같은 번호로 입력한다.

프로토콜 : UDP, TCP 중 선택가능하다. 나는 TCP로 선택했다.

 

마지막으로, 네이버에 공인IP 검색하여 공인IP를 알아낸다.

 

 

공인IP:8080 검색하여 접속하면 끝이다.

 

이번에는 웹서버 연결으로 외부 망 접속을 시도했으나. 조만간 소켓을 통해서도 연결하는 방법을 공부해봐야겠다..

'TIL' 카테고리의 다른 글

2021.09.09  (0) 2021.09.10
2021.09.08  (0) 2021.09.08
[TIL] python OpenCV - threshold 함수로 경계선 얻기  (0) 2021.07.26
[TIL] python OpenCV - 1  (1) 2021.07.26
C언어에서 배열의 크기를 변수로 선언할 수 있을까?  (5) 2019.10.29

+ Recent posts