이 블로그 검색

2025년 5월 26일 월요일

서버 모니터링시 유용한 Linux 명령어

 ps aux --sort=-%mem | head -n 10

메모리 사용량 높은 순서대로 돌고 있는 프로세스 보여주기 (상위 10개만 보여주기)


cat var/log/syslog (Debian/Ubuntu) 또는 /var/log/messages

시스템 로그 보여주기


systemctl list-units --type=service --state=running

실행중인 모든 서비스 보기


ps aux | grep streamli

streamlit(서비스 명) 상태 보기


free -m

메모리 사용 용량


df -h

디스크 사용 용량


top, htop

시스템 프로세스 및 리소스 사용량



2024년 7월 24일 수요일

console.log 에서는 같은 값이 찍히는데, 값이 다른 경우(fs로 파일이나 폴더 이름 가져올때 발생)

 fs 라이브러리로 외부의 파일이나 폴더 이름 등을 read 할때, 유니코드 encoding이 달라서, 콘솔에 찍히는 값은 동일한데, 다르게 인식하는 경우가 있음. (매우 당황스러움)

이런 경우는 nomalize 함수를 이용해서 유니코드 인코딩 값을 통일 시켜줌.

normalize('NFC') 해주면 유니코드 인코딩 값을 정규화 해줌.

names_to_match 값이 외부 파일 이름을 가져온 배열인데, 아마도 유니코드가 다른 방식으로 인코딩이 되었나 보다.

let resultUpdate = await this.users.findOne({where:{name:names_to_match[0].normalize('NFC')}});

2024년 1월 17일 수요일

postgresql 에서 id 시작 값 재 설정

   

            SELECT setval('user_id_seq', 21, true); -- next value will be 22


2023년 10월 11일 수요일

Dbeaver Data Export, import 할때, 필드명 대문자 인식 못하는 문제

 

설정에서 바꿔줘야 한다. 
Dbeaver > Setting > 연결 > 메타데이터 ---> Use case-sensitive names in DDL statements  체크!


2020년 11월 17일 화요일

Android 프로덕션 빌드(플레이스토어 앱 출시) 는 왠만함 app bundle 로 해야됨.. 구 방식의 apk로 하게 되면 오만가지의 이유로 안되는 경우가 많음

 Android 프로덕션 release 빌드(플레이스토어 앱 출시)는 왠만함 app bundle 로 해야됨... 구 방식의 apk로 하게 되면 오만가지의 이유로 안되는 경우가 많음  

각종 경고와 오류가 뜸 

ex) 버전이 맞지 않습니다.(아무리 버젼 맞춰도 안됨) 등등 

2020년 2월 10일 월요일

매번 할때 마다 해매는 설정 (1) : VS(Visual Studio) Code Remote SSH 설정

1. VS Code 확장 플러그인은 Remote Development 이걸 그냥 받자. 생각하지 말구


2. Remote Development config 파일 구성

Host vcm
  HostName ec2-13-209-68-67.ap-northeast-2.compute.amazonaws.com
  User ubuntu
  IdentityFile C:\Users\memeo\.ssh\id_rsa

1) IdentityFile 에서 퍼블릭키(.pub)로 설정하는 실수 하지 말자.. 프라이빗 키로 당연 설정을 해야한다. 퍼블릭키는 서버에 넣지 않았는가!
2) HostName 에서 http:// 는 빼고 순수 호스트 이름만 넣자


3.  rsa 키 만들기
 -> 헛갈릴것 없다.
ssh-keygen -t rsa -b 4096
위 명렁어를 콘솔에 치면, 
id_rsa(개인키), id_rsa.pub(공개키) 두개가 홈폴더(Users/memeoo/) 의 .ssh 폴더에 자동으로 생성된다.
해당 폴더(홈폴더/.ssh)로 가서 , cat id_rsa.pub 해서 공개키를 디스플레이 함.
그걸 그대로 복사함. 
서버에 가서 역시 홈폴더(~/)의 .ssh 폴더에 가면, authorized_keys 라는 파일이 있음.
이 파일을 sudo vim authorized_keys 로 열음.
연다음, 카피한 걸 맨끝에 붙여넣음.
헛갈리는 이유가 원리를 모르고 해서 그럼 :
ssh-keygen 을 하면 로컬의 개인키와 매핑되는 서버의 공개키가 한쌍으로 생성됨.
로컬에서 접속할때는 당연히 개인키를 가지고 (IdentityFile) 서버의 authorized_keys라는 곳에 개인키에 매핑되는 공개키를 넣어 주면 짝짝궁이 맞아 들어가는 구조.  당연히 authorized_keys 에는 여러 로컬(노트북 1, PC1, 노트북2, ...)에서 설정한 공개키 들이 저장되어 있을것이다.

2019년 12월 21일 토요일

React Native의 끔찍한 버그

React Native로 개발 시, 여러 잔 버그 때문에 많이 고생해 보았는데, 이것 만큼 끔찍했던건 없었던 듯 하다.
 Render 함수 내의 에러(즉, JSX에러)는 React Native 에서 잡아 주지 않는 것이 있다.
 ==> React Native Debugger 로그에도 안뜨고, Metro Bundler 에러 메세지도 없으며, 그냥 앱이 픽 죽어 버리면서 화면이 닫힘..(심지어는 폰 자체에 뻘겋게 뜨는 에러 창에도 안나옴... ;;)

 개발을 하다가 이런 증세가 있음, Render 함수 내의 JSX에 뭔가 잘못 넣은게 있는지 확인하는게 정신 건강에 좋다. (ex, 스타일시트에서 width: 240 인데, width:'240' 으로 했는지...)
(진짜 이런거 한번 걸리면 멘탈 터짐)
하이브리드 모바일 개발에 있어 React Native 의 위상이나 인기가 개인적으로는 거품이거나 지나친 고평가 된게 아닌가 싶다. 기존에 Angular 기반의 Ionic 프레임워크로 개발시에는 프레임워크 내의 잔버그가 하나도 없었다. (정말 1도 없었다.)
 리액트 네이티브로 개발 시, 정말 수많은 짜잘한 프레임워크 내 버그와 싸웠던 기억으로 인해 스스로 내가  만든 앱의 신뢰성에 의구심이 들 정도다.. (과연 이번엔 잘 돌아가는데, 다음에 해도 잘 돌아갈까?)
 React JS의 성공으로 인해 React Native가 별 검증없이 하이브리드 모바일 개발 프레임워크로 급격한 인기를 얻은 듯 싶다.
 만약 React Native와 Ionic 에서 무엇을 메인 개발 프레임워크로 고민하는 개발자가 있다면, 두 프레임워크로 모두 개발을 해본 사람 입장에서 아이오닉을 강하게 추천한다. 리액트 네이티브는 아이오닉에 비해 너무 지저분하다.. 안정성이 많이 떨어진다.. 스트레스로 인한 생명 감소가 느껴지는 프레임워크...ㅋ 누가 이렇게 띄어 놓은거냐...대체 ㅋ




2019년 6월 28일 금요일

[react-native] 안드로이드 signed apk 만드는 방법 (안드로이드 배포 막바지 단계)
* 퍼옴: 출처 - https://iam.holy.kiwi/6


react-native 개발이 웬만큼 끝났다면!! 이제 배포를 해야한다.

안드로이드 apk 파일을 플레이스토어에 배포하기 위해서는 고유한 키스토어를 생성해서 다른 사람이 자신의 앱을 올리지 못하도록 해야한다.

안드로이드 signed apk를 만드는 방법을 알아보자!

1. 키스토어 생성


1
keytool -genkey --keystore <YOUR_KEYSTORE_NAME>.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

cs


2. 생성된 키스토어 파일을 android/app 경로 내에 넣음



3. gradles.properties에 다음 코드를 넣음


1
2
3
4
MYAPP_RELEASE_STORE_FILE=<YOUR_KEYSTORE_NAME>.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=<YOUR_PASSWORD>
MYAPP_RELEASE_KEY_PASSWORD=<YOUR_PASSWORD>
cs


4. app/build.gradle에 다음 코드를 넣음


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
...
cs



5. 다음 명령어를 통해 개발자 모드를 끈다. (이 작업은 프로젝트 루트 폴더에서 해야 한다. - 다른 곳에서 안됨, 그리고 이 작업을 안하면 만든 apk가 정작 실행이 안됨..;; )


1
2
3
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
cs

6. 다음 명령어를 통해 release apk를 빌드한다.


1
cd android && ./gradlew assembleRelease
cs

7. app-release.apk 파일은 android/app/build/outputs/apk/release 경로에서 찾을 수 있다.

8. 이런 Error 가 나오는 경우가 있음

Execution failed for task ':app:mergeReleaseResources'.Error: Duplicate resources

--> https://stackoverflow.com/questions/53239705/react-native-error-duplicate-resources-android

 그 중 첫 번째 이게 답임

--> After bundling delete the drawable folder from Android Studio. You could find this in android/app/src/main/res/drawable

안드로이드 스트디오까지 갈것 없고 그냥 찾아서 지워주면 됨. drawable 어쩌구 폴더를 전부 다 지워주면 됨.


2018년 10월 15일 월요일

Promise 의 이해

Promise는 JavaScript의 비동기 처리를 위해 탄생했기 때문에 Java나 C++ 등의 동기형 객체지향 프로그래머들이 이해하기 여간 까다로운 개념이 아님.

자바 스크립트는 함수를 인자로 받을 수 있다. 이 점을 잘 인식해야 한다. 여기서 모든 헛갈림이 시작된다.

아래는 인자를 함수로 받는 함수의 정의(선언)
Ex)
function getData(callbackFunc) {
  $.get('url 주소/products/1', function (response) {
if(response){
callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
}
  });
}

이렇게 인자를 함수로 받은 함수를 사용(호출) 할 때 인자로 전달된 함수를 정의(선언) 해서 쓴다.

getData(function(tableData){
console.log(tableData);
});

즉, callbackFunc = function(tableData){
console.log(tableData);
} 이 되는 셈.

프로미스를 쓰면, 이렇게 함수를 정의한다.
function getData() {
return new Promise(function(resolve, reject){
$.get('url 주소/products/1', function(response){
if(response){
resolve(response);
}
reject(new Error("Request is failed"));
});
});
}

즉 promise 라는 객체를 생성 시키는 방법은 function(resolve, reject)함수를 생성자 인자로 던져 주면 된다.
여기서 promise를 return 하는 이유는 return을 함으로써 getData() 함수 밖에 쓸 수(즉 콜백 지옥을 벗어날 수)있기 때문이다.

그리고 promise 의 생성자 인자로 던져진 함수 내부에 시간이 걸리는(즉, 비동기 처리에 원인이 되는- 볼드체 부분) 코드를 넣으면 된다.
그리고 나서 resolve() 함수에 비동기 처리된 결과 값(response)를 넘겨준다.

getData().then(function(data){
console.log(data);
})

그러면 위와 같이 then() 안에 인자로서 resolve(reponse)를 실제 어떤 동작을 하는지 정의(선언) 해주면 된다.
즉, resolve(reponse)는 맨 위의 callbackFunc(response)와 똑같은 역할을 한다.

 getData().then(function(data){
console.log(data);
}).catch(function(err){
console.log(err);
});

에러처리는 위와 같이 catch()를 이용한다.
간단히 말해, then에 들어가는 인자는 resolve()를 함수로서 구체화 하는 코드가 들어가고,
catch에 들어가는 인자는 reject()를 함수로서 구체화 하는 코드가 들어가면 된다.


2018년 6월 22일 금요일

ionic 데이터를 객체 형태로 뷰로 넘길 때 발생하는 undefined(null)

ionic에서 viewDidLoad() 에서 데이터를 set 했는데, View단에서 그 데이터를 못 가져오는 경우가 있다.
이런 경우는 View 단에 Data를 넘길때 객체(Object) 형태로 넘겨서, 뷰단에서 그 값을 빼서(fetch) 표시하는 경우 자주 발생한다. 뷰단에 넘기는 데이터는 string이나 number 처럼 primitive 형태의 데이터를 넘기는 것이 안전하다. 코드단에서 전부 가공을 마치고 말 그대로 뷰(View)단에서는 최종적으로 유저에게 보여지(viewed)는 data만을 넘긴다. 

2017년 12월 12일 화요일

전역 변수를 사용했을시 직면할 수 있는 버그
 => 데이터가 리프레쉬가 안되는 현상.
 변수의 데이터가 계속 쌓이면서 초기화가 안되는 문제가 있을때 자신이 전역변수를 사용하고 있지 않는지 체크해 볼 필요가 있다.

2017년 12월 1일 금요일

JSON Doc 에서 Array나 Object를 못 가져올 때 (Unable to get access Array or Object from JSON in Javascript)

답은 JSON.stringfy() 로 doc을 읽어 들인 후 ==> JSON.parse()로 다시 바꿔줘야 한다.
Express 등에서 디비에서 떨궈서 받은 Json 데이터 안에 Array나 객체에 접근 못하는 경우가 종종 있다. 콘솔이나 로그에는 명확히 찍히기 때문에 매우 당황 스럽다.
 이는 JavaScript 의 JSON 이 우리가 흔히 말하는 JSON 포맷과 다르기 때문에 발생한다. 즉 자바스크립 버젼의 JSON을 JSON 인터페이스 포맷으로 바꿔야 한다. 그 후 다시 JSON.parse()로 바꿔 줌.
방법은
let originalJson = JSON.stringfy(javaScriptJson)
let parsedJson = JSON.parse(originalJson);

2017년 11월 28일 화요일

ionic2 Android build and Release

우선 프로젝트 루트 폴더의 config.xml 파일에서 widget id와 버전(version)을 체크하고 변경해 준다. (이게 같으면 나중에 다 해놓구 플레이 스토어에 안올라감... ;;)
그리고 해당 프로젝트 루트 폴더에서 CLI로 다음과 같이 입력
$ ionic cordova build --release android
그러면 android-relase-unsigned.apk 가 나온다.
(이 apk 파일은 프로젝트폴더\platforms\android\build\outputs\apk\ 에 생성되니 헤메지 말자)
이 녀석을 Sign해 줘야한다.
따라서 Keytool 이라는 명령어(JDK)를 이용해서 사인을 할 key를 만들어줘야 한다. (이미 key가 있으면 이 과정은 생략하고 jarsigner를 이용해 sign을 하면 된다.)
keytool은 JDK 명령어 이므로, Java path(C:\Program Files\Java\jdk1.8.0_152\bin)를 시스템 환경 변수에 잡아 줘야 정신건강에 이롭다.
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
위의 명령어를 이용해서 사인키를 만들었으면, my-release-key.keystore 라는 파일이 현재의 폴더에 생성될거임
그럼 역시 JDK 명령어인 jarsigner를 이용해서 다음과 같이 사인해줌.(즉 키가 이미 있음위의 keytool 과정은 생략해도 됨)
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore android-release-unsigned.apk alias_name
당연히 alias_name에 바꾸고 싶은 이름을 넣어야 함. 근데 주의할건 이 alias_name 이 keytool 명령어에서 사용했던 alias_name 이랑 일치해야 함. 
(이때 가끔 아래와 같이 암호를 제대로 넣었는데오 저런 재수없는 에러가 나올수 있는데, 이건 해당 폴더에 쓰기 권한 설정이 없어서 그런거임. (회사컴등으로 작업할때 나올 수 있음) 폴더에 권한을 주면 됨.
Enter Passphrase for keystore:
jarsigner: unable to create: android-release-unsigned.apk.sig)

그러면 그냥 똑같은 파일이름으로 android-release-unsigned.apk 가 생성되는데 사실 이건 unsigned 가 아니고 sign 된 거임. 이걸 zipalign 이라는 Android SDK 빌드툴로 압축해줘야 함. (당연히 안드로이드도 환경 변수로 잡아야 정신건강에 이로움 - 안드로이드 빌드 툴은 보통 ~Users\AppData\Local\Android\Sdk\build-tools\ 이라는 깊고 깊은 곳에 있음.)
zipalign -v 4 android-release-unsigned.apk HelloWorld.apk
이렇게 해주면 최종 Signed Release apk 가 생성됨
(참고: 위의 과정을 c:\signing 와 같은 정해진 폴더에 android-release-unsigned.apk, my-release-key.keystore 같은 파일들을 때려넣고, 자바와 안드로이드 패쓰를 잡고 해당 폴더에서 작업을 하는게 편함)
플레이스토어에서 올리는 법


2016년 7월 4일 월요일

mean stack setting

요 페이지가 베스트 임..

https://www.npmjs.com/package/generator-mean-stack

2016년 6월 1일 수요일

Restful put 에서 파라메터로 객체를 넘겨야 한다.

말 그대로 Restful put() 에서 파라메터로 객체를 넘겨야 한다.
primative 값(int 등)으로 넘기면 400 에러(Not found)를 밷는다..
이것 때문에 많이 헤멤...;;

2016년 2월 8일 월요일

터미널에서 띄운 서버 앱이 터미널 세션 종료시 같이 죽는 문제

 nohup  명령어를 쓰면 된다.
nohup은 프로세스를 백그라운드로 돌려주는 기능

~$ nohup 명령어 &

* 보통 nohup은 /usr/bin 에 있을거임.
그래서, 요렇게 치면 될듯
예)
~$ /usr/bin/nohup node app.js &

그 후 터미널을 나가도 잘 돌아간다~~


그러면 또, 강제로 죽여야 할 때도 있을 것이다.
그때는 "ps -ef | command이름" 을 이용해서 해당 프로세스 ID를 찾은다음
kill -9 processID 로 종료시키면 된다.

Ex)

//node 명령어를 사용하는 프로세스 조회

ubuntu@ip-172-31-13-41:~/d2dessay$ ps -ef | grep node   

ubuntu   20252     1  0 Feb08 ?        00:00:00 node app.js
ubuntu   21102 21018  0 03:55 pts/0    00:00:00 grep --color=auto node

//해당 프로세스 종료시키기 

ubuntu@ip-172-31-13-41:~/d2dessay$ kill -9 20252

2016년 1월 19일 화요일

SublimeText 핵심 단축키

* MAC

Command + L : 한줄 선택
Command + D : 같은 내용 선택 --> 여러번 누르면 계속 같은 걸 선택하게 한다.

Command + R : 요소 찾기 : JavaScript 이든 HTML, CSS 이든 다 찾아 줌..

Command + CTRL 화살표 위아래 : 위아래로 줄을 바꿔준다.


2015년 10월 26일 월요일

Log 작성 시 유용한 툴: Thread 객체

    private static void log(char level, String msg) {
        if(DEBUG) {
            Thread thread = Thread.currentThread();      // <- 이와같이 Thread 객체를 이용하면
            String threadName = thread.getName();        // 현재 Thread 이름
            String  fileName = thread.getStackTrace()[4].getFileName();  // 현재 로그가 찍히는 file 이름
            int nLine = thread.getStackTrace()[4].getLineNumber();     // 현재 로그가 찍히는 줄넘버 까지 다 알수 있음.

            if(fileName.length() > 20) {
                fileName = fileName.substring(0, 20);
            }

            String strLog = String.format("%s:%-10s[%-20s %5d]%s\n", TAG, threadName, fileName, nLine, msg);

            switch(level) {
                case 'D':
                    Log.d(TAG, strLog);
                    break;
                case 'E':
                    Log.e(TAG, strLog);
                    break;
                case 'W':
                    Log.w(TAG, strLog);
                    break;
                case 'I':
                    Log.i(TAG, strLog);
                    break;
                case 'V':
                    Log.v(TAG, strLog);
                    break;
            }

        }

2015년 10월 3일 토요일

안드로이드 키보드 호출 option: adjustPan, adjustResize

안드로이드 키보드 호출 시 가장 중요한 두 옵션이다. (설정은 manifest의 해당 activity에서 하면 된다.)

Ex) <activity android:name=".activities.BoardActivity" android:windowSoftInputMode="adjustPan"></activity>

이 두 옵션의 가장 큰 차이는 한마디로 키보드의 높이만큼 올라가서 가려지는 부분을 허용하겠느냐, 말겠느냐의 차이라 볼 수 있다.

adjustPan 은 쿨하게 가려버리라는 것이고, (즉, 가려져도 상관없다.) 
adjustResize 는 한마디로 "리사이즈" 해서라도 가려지는 부분이 없도록 다 보이게 하라는 의미이다. (가려지는 부분이 있으면 안된다.) 

따라서, pan 으로 설정하면 각 UI 컴포넌트(즉,뷰(View)들)의 사이즈 변화가 없고, Resize로 설정하면 View 들의 높이가 줄어들게 된다.(키보드의 높이만큼 뷰들이 나누어서 크기가 줄어든다고 생각하면 됨)