자바스크립트 E6(ES2015)가 나오면서, 편리한 자료구조인 ES2015-Collections( Map, Set )가 등장했습니다.


자바스크립트의 MapSet의 API가 타 언어에 비해 조금 다르더라도, 


타 언어와 많이 다르지 않기 때문에 사용하는것이 어렵진 않습니다.


다만, 순회하는 방법이 조금 독특하기 때문에 이번 포스팅을 하게 되었습니다.



forEach 메서드로 순회하기


Map, Set에서의 forEach( [Map or Set].prototype.forEach )는 ArrayforEach( Array.prototype.forEach )와 비슷하지만 조금 다릅니다.


Array의 forEach가 받는 콜백함수의 인수는 순서대로 , 인덱스, 배열 순으로 들어옵니다.


하지만 Map, Set에서의 forEach가 받는 콜백함수의 인수는 순서대로 , , 오브젝트(Map or Set) 로 들어옵니다.


Set의 콜백함수는 key 대신에 value2가 들어옵니다. value2는 value와 똑같습니다. 

아래의 예시와 "개별 값으로 순회 하기" 설명을 확인해주세요.


[ Ex) JavaScript / TypeScript ]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// JavaScript
const map = new Map();
const set = new Set();
 
// TypeScript
const map = new Map<string, string>();
const set = new Set<string>();
 
map.set('name''Mommoo');
map.set('age' , 'secret');
 
set.add('Mommoo');
set.add('secret');
 
map.forEach((value, key, mapObject) => console.log(key +' , ' +value));
// name , Mommoo
// age , secret
 
set.forEach((value1, value2, setObject) => console.log(value1 +' , '+ value2));
// Mommoo , Mommoo
// secret , secret
cs



for.. of 문법으로 순회하기


forEach 방법은 순회 중간에 continue, break, return 과 같은 루프 기능을 못쓰지만, 


ES6(ES2015)에서 새로나온 for.. of 문법을 사용하면, 가능합니다.


Mapfor.. of로 호출되는 값은 벨류가 들어가 있는 배열 입니다.


Setfor.. of로 호출되는 값은 벨류입니다.


[ Ex) JavaScript ] 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const map = new Map();
const set = new Set();
 
map.set('name''Mommoo');
map.set('age' , 'secret');
 
set.add('Mommoo');
set.add('secret');
 
for ( let item of map ) {
  console.log(item[0+' , '+ item[1]);
}
// name , Mommoo
// age , secret
 
for ( let item of set ) {
  console.log(item);
}
// Mommoo
// secret
cs


TypeScript는 조금 까다롭습니다. 이유는 Iterable 속성 때문인데요. type iterable 속성때문에 for.. of가 컴파일이 되질 않습니다.


컴파일이 되지 않는 이유를 알고 싶으신 분은 다음 링크 2개를 참고해주세요.

http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#new---downleveliteration

https://stackoverflow.com/questions/37699320/iterating-over-typescript-map


위의 JavaScript와 같이 사용하고 싶다면 컴파일러(tsconfig) 속성인 --downlevelIteration 을 켜주셔야 합니다.


아래의 예시는 속성을 키지 않고, 대안으로 ES6(ES2015) Array APIArray.from API를 사용하여 구현한 예제 입니다.


Array.from : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/from


[ Ex) TypeScript ] 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const map = new Map<string, string>();
const set = new Set<string>();
 
map.set('name''Mommoo');
map.set('age' , 'secret');
 
set.add('Mommoo');
set.add('secret');
 
for ( let item of Array.from(map) ) {
  console.log(item[0+' , '+ item[1]);
}
// name , Mommoo
// age , secret
 
for ( let item of Array.from(set) ) {
  console.log(item);
}
// Mommoo
// secret
cs



Iterator로 순회하기


ES2015-Collection인 MapSet는 순회가능한 Iterator입니다. ( IterableIterator )


2번째 방법인 For..of는 내부적으로 Iterator 속성을 이용하여 순회하게 됩니다.


이번에는 직접 Iterator 속성을 이용하여 순회하는 방법입니다. 


for.. of 와 마찬가지로 continue, break, return 과 같은 루프 기능을 사용 할 수 있습니다.


[ Ex) JavaScript / TypeScript ]


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
// JavaScript
const map = new Map();
const set = new Set();
 
// TypeScript
const map = new Map<string, string>();
const set = new Set<string>();
 
map.set('name''Mommoo');
map.set('age' , 'secret');
 
set.add('Mommoo');
set.add('secret');
 
const mapIterator = map.entries();
 
while ( !mapIterator.next().done ) {
  const [key, value] = mapIterator.next().value;
  console.log(key +' , ' +value);  
}
// name , Mommoo
// age , secret
 
const setIterator = set.entires();
 
while ( !setIterator.next().done ) {
  const [value1, value2] = setIterator.next().value;
  console.log(value1 +' , ' +value2);  
// Mommoo , Mommoo
// secret , secret
cs



개별 값으로 순회 하기


지금까지 본것 처럼, ES2015-Collection은 IterableIterator로써, 두개의 값을 가집니다. 


Map은 각각 KeyValue로써, 가치가 매겨지는 반면, Set역시 두개의 값을 가지지만, 두개의 값은 서로 같습니다. 


Set이 필요없는 값을 가지고 있는 이유는 상위 개념인 ES2015-Collection의 다형성 관점으로 구현했기 때문입니다.


위의 예제와 같이 entries 메서드를 호출하면 두개의 값을 가진 IterableIterator인 반면,


두개의 값중 개별 값을 가진 IterableIterator를 만들 수 있습니다. 


첫번째 값은 keys 메서드로 호출하고, 두번째 값은 values 메서드를 호출하여 IterableIterator 객체를 만든 후,


2번째 방법 ( for.. of ) 또는 3번째 방법 ( iterator )으로 순회하시면 됩니다.



[ Ex) JavaScript / TypeScript ]


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
48
49
50
51
52
53
54
55
56
57
58
// JavaScript
const map = new Map();
const set = new Set();
 
// TypeScript
const map = new Map<string, string>();
const set = new Set<string>();
 
map.set('name''Mommoo');
map.set('age' , 'secret');
 
set.add('Mommoo');
set.add('secret');
 
// 첫번째 값 ( 키 )
const mapSingleIterator = map.keys();
// 두번째 값 ( 벨류 )
const mapSingleIterator = map.values();
 
 
// 첫번째 값 ( 벨류 )
const setSingleIterator = set.keys();
// 두번째 값 ( 벨류 )
const setSingleIterator = set.values();
 
/** for of 방법 typescript는 Array.from 메서드로 변환 해야함. 2번째 방법 예시 참고 */
 
for ( let single of mapSingleIterator ) {
    console.log(single);
}
// name
// age
// ---- or -----
// Mommoo
// secret
 
for ( let single of setSingleIterator ) {
  console.log(single);
}
// Mommoo
// secret
 
 
/** iterator 방법 */
 
while ( !mapSingleIterator.next().done ) {
  const single = mapSingleIterator.next().value;
  console.log(single);  
}
// name or Mommoo
// age or secret
 
while ( !setSingleIterator.next().done ) {
  const single = setSingleIterator.next().value;
  console.log(single);  
}
// Mommoo
// secret
cs




준비한 내용은 여기까지 입니다.


읽어주셔서 감사합니다.



포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee


보통 JavaScript에서 숫자 여부를 판단할때 많이 쓰이는 방법은 아래와 같습니다.


1
2
3
4
5
6
7
8
9
isNaN(100)     // false;
isNaN('100px'// true;
 
function isNumeric(data) {
  return !isNaN(data);
}
 
isNumeric(100)   // true;
isNumeric('str'// false;


NaN은 숫자가 될수 없는 문자열을 숫자로 만들때 발생하는데요. ex) ( Number( '100px' ) );


isNaN 함수는 NaN 값인지 아닌지의 여부를 알려주는 함수 입니다.


이로인해 isNaN 함수로 숫자를 판별 할 수 있습니다.


하지만, Type 엄격한 TypeScript에서의 isNaN 함수는 인자로 number 타입만을 받습니다.


string 데이터를 넣지 못하니.. 자바스크립트 처럼 isNaN 함수로만, 숫자 여부를 판단할 수 없습니다.


어떻게 하면 될까요? 정답은 Number 함수를 사용하면 됩니다.


Number 함수에 인자로 string을 넣었을시, 무조건 number 타입으로 리턴이 됩니다.


변환이 가능한 string값은 숫자 값이 올바르게 파싱되지만,


변환이 불가능한 string 값은 NaN이라는 number 타입으로 리턴이 됩니다.


이 개념을 가지고 아래와 같이 메서드로 작성할 수 있습니다..!



1
2
3
4
5
6
7
8
9
Number(100)     // 100;
Number('100px'// NaN;
 
public isNumeric(data : string) : boolean {
  return !isNaN(Number(string));
}
 
isNumeric('100')   // true;
isNumeric('100px'// false;
cs


포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

본 "개인정보 처리 방침"은 "Mommoo"가 배포하는 "안드로이드 어플리케이션"(이하 "앱") 사용을 위하여 요청하는 "민감한 권한" 및 "사용자 정보"에 대한 관리 및 운영에 관한 내용입니다.


1. 사용하는 "민감한 권한" 및 "사용자 정보"와 이의 이용 목적

  1) android.perimission.READ_CONTACTS 
    과기DAY가 "앱"에서 사용자가 등록한 캘린더의 정보를 보여주기 위하여 사용
     

2. "민감한 권한" 및 "사용자 정보"에 대한 수집

해당 과기DAY "앱"을 사용함에 있어 서비스의 이용 내역을 포함한 어떠한 개인 정보도 "Mommoo"가 운영/관리하는 서버로의 수집/전송/저장 하지 않습니다.


3. "민감한 권한" 및 "사용자 정보"에 대한 제3자 제공 및 위탁

"과기DAY" 에서는 정보 이용 목적의 범위를 넘어 사용하거나 제3자에게 제공 또는 위탁하지 않습니다.


4. 기타

본 "개인정보 처리 방침"은 2018년 05월 01일부터 시행됩니다.


'과기DAY > Notice' 카테고리의 다른 글

과기DAY - 2.0v 업데이트  (2) 2016.11.06
과기DAY - 1.7v 업데이트  (0) 2016.07.03
과기DAY - 1.5v 업데이트  (4) 2016.05.16

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee


오늘 포스팅 할 Angular 내용은 ngIf 디렉티브 와 ElementRef 상관관계에 대해서 다룹니다.




왜 ngIf 와 ElementRef 조합일까요?


ngIf 디렉티브를 사용하면, html element를 동적으로 추가/삭제를 구현하기가 편리합니다. 


무엇보다도, 가독성이 떨어지는 DOM API를 사용하는것 이 아닌, 직관적인 코드를 제공하는것이 큰 장점입니다.


하지만, DOM API를 피할 수 없는 순간도 존재합니다.


Angular는 DOM API를 ElementRef 라는 객체를 통해서 제공합니다. 


ElementRef는 HTML Element를 내부적으로 감싼 객체인데, 

보통 ViwChild 어노테이션이나, ViewChildren 어노테이션으로 참조합니다.


문제는 여기서 발생합니다.


ngIf 로 추가/삭제를 하는 HTML Element를 ElementRef 로 받았을 시,

ngIf 로 인한 추가/삭제 와 해당 ElementRef 를 참조하는것이 싱크가 되지 않는다.



해결 방법은?


다행히도, Angular가 제공해주는 API가 있습니다. 


ngIf와 ElementRef 의 싱크를 맞춰주기 위해 필요한 객체는 ChangeDetectorRef 입니다.


아래와 같이 TypeScript 생성자 문법으로 받아 올 수 있습니다. ( 컴포넌트 코드 안에서 작성하였습니다. )


받아 온 후, 싱크를 맞춰야할 메서드 안에서 detectChanges 메서드를 호출하면 됩니다.


1
2
3
4
5
6
7
8
9
10
11
constructor(private changeDetector : ChangeDetectorRef) {
    
}
 
//싱크를 맞추시고 싶은 곳에서
 
public click() : void {
  ...
  this.changeDetector.detectChanges();
  ...
}
cs




끝으로


프레임워크의 장점이자 단점은, 정해진 규칙과 틀을 이용해 개발을 한다는 점입니다.


가이드가 정확히 제시된 것들은 정말 빨리 배울수 있지만, 구현사항이 디테일 할 때 해당 프레임워크의 


이해도가 없다면 프레임워크를 직접 부딪히고 테스트 해봐야 할 것들이 많습니다.


특히 Angular 같이 아직 자료가 많이 없을시엔 더더욱 그렇습니다.


비슷한 이슈로 자료를 찾는 분에게, 본 포스팅으로 도움이 되셨으면 합니다.


감사합니다.

'Angular' 카테고리의 다른 글

Angular Context-Path 설정하기.  (2) 2018.04.04

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee


Angular 프로젝트의 Context-Path는 기본적으로 '/' 로 설정되어 있습니다.


Angular 프로젝트를 생성했을시, 루트 폴더안에 .angular-cli.json 이 존재합니다.


CLI 명령을 사용할때 참조되는 파일이며, 이 파일에 옵션 하나를 추가하면 Context-Path가 설정됩니다.


.angular-cli.json 중간에 "app" 키로 매핑된 값에 아래와 같이 추가하면 Context-Path가 설정됩니다.



1
2
3
4
5
6
7
"apps": [
    {
      ...
      "baseHref""context-path",
      ...
    }
]
cs


'Angular' 카테고리의 다른 글

Angular ngIf 디렉티브와 ElementRef 상관관계  (2) 2018.04.16

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee


TypeScript에서 JQuery를 쓰기 위해서 필요한 환경셋팅에 대해 기술하려고 합니다.


먼저 저의 환경입니다.


개발툴 : IntelliJ IDEA

설치한 추가 환경 : node.js


만약 TypeScript를 까셨다면, 컴파일러를 위해 node.js는 설치를 하셨을겁니다.


이러한 환경에서, JQuery를 쓰기 위해서 어떻게 환경 설정을 하는지를 포스팅 합니다.


참고로 npm 기준입니다.


npm 터미널에 


npm install jquery --save;

를 입력합니다. 해당 명령어는 진행하는 프로젝트에 의존 설정을 해줍니다.


이 명령어만 진행했을시, 타입스크립트 파일 상단에


import $ from 'jquery';


이와 같이 import를 진행 할 수 있습니다. 


하지만, 다른 타입스크립트 파일은 import를 진행한 타입스크립트 파일을 참조를 못하는 현상이 있는데요. ( 해당 부분은 제가 이해도가 낮아서, 저의 개발환경에서 발생한 이슈대로 작성했습니다. )


이것을 해결 하려면, 아래의 명령어를 추가로 입력해야 합니다.


npm install @types/jquery --save-dev;


위의 명령어가 실행되면,  타입 스크립트 파일이 JQuery가 임포트된 타입 스크립트 파일을 참조할 수 있습니다.




타입스크립트에 JQuery 라이브러리를 사용하는 방법을 포스팅 했는데요.


중간에 설명했드시 제가 npm에 대한 개념이 많이 없는지라, 틀린 설명이 있을 수 도 있습니다.


감안해서 봐주시면 감사하겠습니다. 

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

오늘 포스팅은 형상관리의 개념과 이유에 관해 간략하게 설명해볼까 합니다.

형상관리의 기본적인 것을 알아봅시다.



프로그래밍 패러다임


    오래전부터, 프로그래머에게 사랑을 받고 있는 프로그래밍 패러다임은 단연 객체지향 프로그래밍 이라 할 수 있습니다. 

객체지향 프로그래밍은 항상 절차지향 프로그래밍과 상반적으로 설명되곤 합니다. 

하지만, 이는 조금 잘못된 오해이며, 사실상 객체지향 프로그래밍은 상호 관계는 상반적이 아니라, 상보적 관계입니다. 

프로그램은 절차적으로 수행되는 집합체이며, 이는 객체지향도 마찬가지 입니다. 

다만, 객체지향은 절차적인 부분을 객체에게 맡깁니다. 

프로그래머는 잘 만든 객체를 요구사항에 맞게 알맞게 조합하여 하나의 프로그램을 만드는 것입니다. 

또한 객체지향 패러다임은 프로그래머로 하여금 유지보수를 쉽게 해줍니다. 

현재 패러다임에서의 핵심은 객체, 작게 말해서 클래스를 잘 작성하는 것이라 할 수 있습니다.



클래스를 잘 작성하는 방법


    클래스를 잘 작성하는 방법은 프로그래밍 패러다임에 맞는 개념과 방법론이 잘 적용이 되어야 합니다. 

또한, 유지보수가 쉽게 될 수 있도록 코드를 작성을 해야 합니다. 

유지보수는 코드 뿐만 아니라, 컴퓨터공학적 이론, 요구사항 등이 반영 됩니다. 

그렇다면, 유지보수를 위해서는 클래스를 잘 작성해야 할 뿐만 아니라, 잘 관리를 해야 합니다. 

인간이 어떤 무언가를 관리하기 위해, 오래전부터 사용하는 방법은 '기록' 입니다. 

변경사항을 하나 하나 기억할 수 없으므로, '기록'을 함으로서, 인간은 어떤 무언가를 효과적으로 관리를 해왔습니다.

클래스의 관리도 '기록'의 관점에서 접근 할 것입니다.



어떻게 기록 할까?


    클래스를 기록하는 것은 단순히 코드를 복사한 후 외부 파일로 저장하는 것이 아닙니다.

코드 뿐만 아니라 그 코드에 반영된 컴퓨터 공학적 이론, 기술, 사용자 요구사항 등 많은 요소들이 기록이 되어야 합니다.

또한, 소프트웨어 특성상 '개발환경' 까지 보존 해 줄 수 있어야 합니다.

이러한 것들을 반영한 것을 문서로 기록을 해야합니다.

하지만, 이렇게 작성할 시 문서들은 점점 많아지고, 그로인해 찾아서 읽기가 여간 만만하지 않습니다.

또한 찾더라도, 문서로만 읽은 '개발환경'은 사실상 적용하기가 불가능 합니다.

결국 문서를 넘어서, 프로젝트 그 자체를 기록할 수 있어야 합니다. 즉, '형상관리'를 해줄 수 있는 프로그램 필요해졌습니다.



Git의 등장


    Git이 등장하기 이전에는, 위에서 설명한 형상관리를 하기 위해 SVN을 썼었습니다.

Git이 등장 함에 따라, SVN 보다는 Git을 많이 쓰이는 추세로 바뀌었는데요. 

대표적으로 큰 변화중 하나는 저장방식 입니다. SVN은 중앙 집중 저장 방식인 반면, Git은 분산 저장 방식을 채택했습니다.

그로인하여, 좀더 효과적으로 형상관리를 할 수 있게 됬습니다. 

이러한 Git프로그램 덕분에, 프로그래머는 Git만 잘 사용한다면 프로젝트를 효과적으로 형상관리 할 수 있습니다.

또한, 협업 환경에서의 프로젝트에서도 효과적인 커뮤니티를 위해 반드시 다룰줄 알아야 합니다.  형상관리를 통해 소스코드를 서로 주고 받는 것이 아닌 메인 저장소에서 필요할 때마다 받을 수 있으며, 효과적인 버전 관리로 인해 생산성이 증대됩니다. 



어느곳에 저장할까?


    Git은 로컬저장소원격저장소 라는 2가지 개념의 저장소가 존재합니다. 로컬저장소는 본인의 컴퓨터나 원하는 곳에 만들 수 있습니다.

다만, 로컬저장소로써 기능을 하려면 Git을 이용해 원격저장소랑 연결을 해야합니다.  로컬저장소를 만들어 원격저장소에 remote연결을 하기도 하고, 원격저장소에서 clone하여 로컬저장소를 만들 기도 합니다. 

이때 원격 저장소는 여러가지가 있으며, 대표적으로는 GitHub, BitBucket등이 있습니다.



마치며


    이번 포스팅에서 말하고 싶었던 바는, 형상관리는 단순히 프로젝트를 백업하기 위한 용도로 사용하는것이 아닌, 효과적인 개발을 위해 필수적으로 사용되어야 한다는 점입니다. 저 포함하여 Git을 쓰는 많은 초보 개발자들은, 단순히 '저장'용도로 사용하고 있습니다. 이러한 저장 용도 보다는 클래스를 설계했을시, 또는 개념을 추가했을시 그러한 것들을 잘 반영하고, 기록하기 위해 형상관리를 활용해보는 것을 추천합니다.


'용어정리 > 프로그래밍용어' 카테고리의 다른 글

절대경로, 상대경로란?  (7) 2018.12.06
비즈니스 로직(Business Logic)이란?  (15) 2017.05.24
DTO와 VO란?  (2) 2017.02.08
GET방식 과 POST방식  (32) 2016.12.10
컴포넌트(Component)란?  (8) 2016.10.20

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

  오늘 포스팅은 Java JNI ( Java Native Interface) 입니다.


자바는 특정 운영체제에 종속되지 않도록, JVM이라는 가상머신 위에서 실행되게끔 만들어진 언어입니다.


운영체제에 맞는 JVM이 각기 존재하기 때문에, Java 개발자는 하나의 Java 파일만 만들면, 


운영체제 상관없이 원하는 결과물을 쉽게 얻을 수 있습니다.


하지만 단점도 있습니다.


그중 하나의 단점은 운영체제의 모든 기능을 JVM이 담지 못하는 것입니다.


따라서, 구현하고 싶은 몇몇 기능들은 Java 언어 자체로도 해결 안되는 경우가 존재합니다.



JNI (Java Native Interface) 란?


  위에서 언급한 Java언어 자체로도 해결 안되는 경우, 대처할 수 있는 방법중 하나입니다.


운영체제의 고유기능(Native)을 Java로 해결 하는 것이 아닌 운영체제가 구현된 언어 (보통 C, C++)로


운영체제의 고유기능을 만듭니다. 


JVM은 C,C++로 만들어진 고유기능 즉, 함수를 Java 메서드와 연결해줍니다.


그로인하여 Java 메서드를 호출 할 시, C나 C++로 작성된 함수가 실행 됩니다.




JNI를 구현하기 위해 필요한 것



  C, C++을 작성하기 위한 비쥬얼 스튜디오가 필요합니다. 저는 2015 Community 썼습니다.




Java 코드 작성하기.



  먼저 필요한 자바 코드를 작성합니다.


JNI 구현 예시로 쓸 2개의 메서드를 만듭니다. 


1개는 HelloWorld를 콘솔에 찍는 메서드, 다른 한개는 단순히 숫자 3을 가져오는 메서드를 만들 예정입니다.


코드는 아래와 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class JNI {
    
    static {
        System.loadLibrary("JNI");
    }
    
    private native int getNumber();
    private native void printHelloWorld();
    
    public static void main(String[] args){
        JNI jni = new JNI();
        
    
        jni.printHelloWorld(); //JNI로 호출 한 HelloWorld!
        
        System.out.println(jni.getNumber()); //JNI로 호출 한 숫자 메서드
    }
}
cs


static 초기화 블럭으로, 추후에 만들 dll 파일을 불러야 하는게 특징입니다.


또한, native 메서드를 만드는 갯수는 상관 없지만, 구현부가 비어있습니다.


dll 파일에 존재할 실제 구현된 함수를 호출하기 위해 만든 껍데기 메서드 입니다.



Java 코드 파일 컴파일, 헤더파일 만들기



  Java 파일 컴파일은 이클립스 같은 툴에서 진행 해도 됩니다.


하지만 헤더파일은 터미널 환경에서 컴파일을 진행 해야합니다. 


이클립스가 제공해주는 Terminal 환경에서 해도 무방합니다. 


하지만 헤더파일 컴파일은 Path 설정등으로 인하여,


잘 안되는 경우가 있기 때문에 아래의 방법을 추천합니다.


먼저 이클립스에서 JNI클래스를 컴파일 합니다.


당연히 dll파일을 찾지 못한다고 오류가 뜹니다. 상관없구요.


그다음 이클립스 workspace로 찾아가셔서 프로젝트폴더 - bin폴더로 갑니다.


그곳에서 Shift + 마우스 오른쪽 클릭 후, 


명령창 여기에서 열기 or PowerShell 여기에서 열기를 누릅니다.


터미널이 뜨면, 그곳에 아래와 같이 입력합니다.


javah 패키지명.클래스명

저 같은 경우 패키지명이 jni 클래스명이 위 예시와 같이 JNI 이므로


javah jni.JNI


로 했습니다.


제대로 컴파일 됬다면, bin폴더 어딘가에


패키지명_클래스명.h 파일이 생깁니다.


그 파일을 잘 보관합니다.



Visual Studio에서 C, C++ 작성하기.




1. 프로젝트 만들기


  Visual Studio를 실행합니다. 


아래와 같이 새로운 프로젝트를 만들어줍니다.



위와 같이 빈 프로젝트로 만들어 줍니다. 추후 dll파일을 만들때, 프로젝트명 으로 dll파일의 이름이 되므로,


프로젝트명을 잘지어줍니다.


2. 헤더 파일 넣기



위와 같이 헤더파일 폴더에 앞서 만들었던 헤더파일을 넣어줍니다.


조심해야 할 건, 복붙으로 넣지말고, 헤더 파일 폴더에 오른쪽 버튼 눌러서 툴의 도움으로 추가를 해야합니다.


그래야, 코드상에서 참조 가능합니다.


3. 프로젝트 속성 변경.



솔루션 탐색기 안에서 프로젝트 속성으로 들어갑니다.


그 후 프로젝트 기본값 - 구성 형식을 동적 라이브러리(.dll)로 바꿔주시고


일반 - 대상 확장명 도 .dll로 바뀌었는지 확인 해주세요.



4. 외부 라이브러리 설정




추가 포함 디렉토리를 누른 후 아래와 같이 입력합니다.


중요한점은, 개인 컴퓨터에 깔린 jdk 버전이 다르기 때문에 jdk 폴더 명은 다를 수 있습니다.




5. 코드 작성


헤더 파일에 있는 함수정보를 복사해서 파라미터를 아래와 같이 맞춰줍니다. (JNIEnv *  => JNIEnv *env , jObject -> jObject)




컴파일 한 후, 컴파일 된 dll파일을 찾습니다. ( 출력창에 dll이 생성된 path가 나옵니다.)



Java 프로젝트에 dll파일을 넣고 컴파일 하기



  만든 dll파일을 Java프로젝트 폴더 바로 아래에 넣고 컴파일 합니다.


dll파일을 아무곳에나 넣어도 상관은 없지만 대신 path를 맞게 입력해줘야 합니다.


프로젝트 폴더 바로 아래에 넣을 시, path 필요없이 파일명만 입력해도 되므로, 프로젝트 폴더 바로아래에 넣었습니다.


넣고 컴파일 해보면 아래와 같이 잘 작동하는걸 볼 수 있습니다.




여기까지가 준비한 내용입니다.


추가적으로 궁금한 사항있으면 댓글 달아주세요.


감사합니다.

'Java' 카테고리의 다른 글

[Java] CheckedException vs UnCheckedException  (0) 2020.09.27
[Java] 파일 경로 처리하기.  (2) 2019.01.24
JAVA - [SWING] LinearLayout 사용하기.  (0) 2017.08.25
JAVA - DownCasting(다운캐스팅)  (25) 2016.08.27
JAVA - HashMap key 구하기.  (1) 2016.08.25

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

+ Recent posts