반응형

이 포스트에서는 Node.js 설치와 Node.js를 이용하여 간단히 동작 테스트를 해본다.

 

Node.js 를 간략하게 설명하면 주로 백엔드(서버 사이드)를 개발하기 위한 하나의 플랫폼이다.

확장자에서 알 수 있듯이 자바스크립트로 개발을 하게 되며,

클라이언트(프론트엔드)에서 요청하는 이벤트에 따라 실시간으로 대응이 가능하다.

요즘 실시간으로 동작하는 웹게임들을 볼 수 있는데 그와 같은 것도 node.js를 이용했다고 보면 된다.

 

이제 설치 방법에 대해 알아보겠다.

 

먼저 https://nodejs.org/ 사이트로 이동한다.

 

위와 같은 화면을 볼 수 있는데 두가지 버전을 제공한다.

좌측에 있는 LTS 버전은 안정된 버전이라 보면 되며, 

우측의 Current는 현재의 최신 버전이라 보면 된다.

백엔드로 동작하는 서버는 안정성이 중요하므로 LTS 버전으로 다운 받을 것을 권장한다.

 

다운 받은 파일을 위와 같이 실행하여 설치한다.

그냥 쭉 Next를 눌러주면 된다.

 

설치를 모두 완료하였다면 명령 프롬프트를 띄우고 'npm -v' 를 입력해본다.

위와 같이 버전 정보가 나온다면 정상적으로 설치되었다고 볼 수 있다.

 

이제 설치는 모두 완료하였으므로 간단히 코드를 작성하여 Node.js를 테스트해볼 것이다.

먼저 명령 프롬프트에서 자신이 코드 작업할 경로로 이동한다.

(나는 C:\node_server\ 에서 작업하였다.)

 

그리고 아래와 같이 패키지 초기화 작업을 해줍니다.

 

위와 같이 'npm init' 명령을 입력 후 정보를 입력(입력하지 않을 경우는 계속 엔터)해준다.

그러면 package.json 파일이 생성되며, 이 파일은 앞으로 npm을 통해 필요한 여러 패키지를

설치할 때 의존성 관리를 위해 사용된다. 예로 다른 개발자에게 똑같은 환경 설정을 제공해주고자

할 경우 이 package.json 도 같이 넘겨주면 똑같은 환경으로 패키지를 설치할 수 있게 된다.

 

단순히 node.js 코드 테스트에는 필요없지만 결국에는 필요한 내용이므로 만들어보았다.

이제 node.js 동작 테스트를 위해 index.js 파일을 만들어보겠다.

 

이와 같이 'touch index.js' 명령으로 간단히 빈 파일을 만들 수 있다.

이제 편집을 해야하는데 나는 VS Code를 이용해서 편집하였다.

VS Code는 네이버에서 검색하여 다운받을 수 있다.

(메모장으로 편집하여도 상관없으나 VS Code가 깔끔하고 편하다.)

 

위와 같이 코드를 입력해주고 저장한다.

위에 보면 hostname에 0.0.0.0이라고 입력되어있는데, any라는 의미로 해석하면 된다.

127.0.0.1로 해서 로컬 서버를 열어주어도 되지만, 외부에서는 접속이 불가능하다.

이제 위 파일을 서버로 동작시켜보겠다.

 

위와 같이 명령 프롬프트에서 'node index.js' 를 입력해준다.

그럼 코드에서 입력해주었던 로그가 그대로 표시된다.

 

이제 웹브라우저에서 해당 페이지를 확인해볼 차례다.

 

위와 같이 http://localhost/ 로 접속해보면,

작성한 코드에서 응답으로 보내주는 'TEST'가 정상적으로 표시되었다.

 

간단하게 Node.js를 테스트해보았는데,

이것을 응용하여 많은 것들을 할 수 있으니 익혀두면 좋을 것 같다.

반응형
반응형

 

이 포스트에서는 안드로이드 스튜디오에 플러터를 설치해보기로 한다.

 

당연히 플러터를 설치하기 전에 기본적으로 안드로이드 스튜디오가 설치되어있어야 한다.

(필자는 안드로이드 스튜디오 3.4.2 버전이 설치되어있음)

 

먼저 https://flutter.dev/ 로 이동하여 'Get started' 버튼을 클릭한다.

 

 

그 다음 설치할 OS를 지정한다.(필자는 Windows에 설치할 것이므로 Windows를 선택했다.)

그 후에는 파일을 다운로드할 수 있는 버튼이 아래와 같이 생기며 해당 파일을 다운로드해준다.

 

모두 다운로드되었다면 압축을 풀어준다.

압축을 푼 내용 자체가 안드로이드 스튜디오 자체에서 참조할 SDK 경로가 된다.

(나는 C:\flutter\flutter 에 압축을 풀었다.)

 

압축 푼 경로로 이동하여 'flutter_console.bat' 을 실행한다.

 

위와 같이 해당 경로에서 'flutter doctor' 를 입력해준다.

이 명령어를 통해 어떤 부분이 부족한지를 확인할 수 있다.

 

보면 세가지의 문제가 있다. 

먼저 X 표시가 되어있는 플러터와 다트 플러그인 설치가 되지 않은 부분을 해결해보자.

 

안드로이드 스튜디오를 켠다. 프로젝트를 불러오기 전 Configure -> Plugins 을 선택한다.

(프로젝트를 불러온 상태라면 File->Setting->Plugins 로 들어가면 된다.)

아래의 창이 뜨면 flutter, dart를 각각 검색하여 설치해주기만 하면 된다.

 

위와 같이 Dart 플러그인을 설치했다면, 이제 flutter를 검색한다.

 

이제 플러그인은 모두 설치했으니 다시 flutter_console.bat 을 실행하여, 'flutter doctor' 를 입력해보자.

 

플러그인 부분은 해결이 되었고,

안드로이드 라이센스가 허가되어있지 않다고 나와있는 부분만 해결하면 된다.

이 부분은 위에 나와있는대로 해당 명령어만 쳐주면 해결된다.

 

위와 같이 입력 후 나오는 문구는 모두 y를 입력해준다.

그리고 다시 'flutter doctor'를 쳐보면 모두 해결되어있을 것이다.

 

위와 같이 안드로이드 스튜디오를 실행하면,

플러터 프로젝트가 생겨난 것을 확인할 수 있다.

반응형
반응형

이번에는 플러터에서 Stateful, Stateless의 차이점에 대해 알아보려고 한다.

 

이 두개의 개념은 플러터에서 상당히 중요한 위치를 차지하고 있고

 

이것을 모르고는 플러터 개발을 원활히 진행할 수 없다.

 

하지만 복잡하지는 않다.

 

Stateful

이것은 뜻 그대로 해석하면 '상태가 있는'을 의미하며,

의미 그대로 상태를 가질 수 있는 위젯을 사용하기 위해 사용한다.

예를 들면, CheckBox, Slider 등의 위젯이 있다.

CheckBox를 예로 들면 체크, 체크안함 이 두가지 상태를 갖고 있으며 사용자의

액션에 따라 상태가 변하게 된다. 즉, 이러한 상태를 갖는 위젯을 사용할 때는

Stateful을 사용해야 한다.

 

Stateless

위 Stateful과 반대로 '상태가  없는'을 의미하며,

사용자의 동작과 상호작용이 필요없는 위젯을 사용할 때 사용한다.

Container, Row, Column, Icon, Text 등이 있습니다.

이 위젯들은 사용자와 상호작용을 하지 않는 위젯들입니다.

CheckBox 같은 위젯과 달리 Container를 예로 들면

해당 위젯을 터치해서 무언가 반응을 해야할 필요가 없기 때문이죠.

 

여기서 어떤 분은 이런 의문을 품을 수도 있을 것 같습니다.

Text 내의 글자를 변경하게 된다면 그것은 Stateful에 해당되는 것이 아니냐?

Text 내의 글자를 변경하는 것은 사용자와 상호 작용을 하는 것이 아니므로

Stateful에 해당하지 않습니다. CheckBox와 Slider, Radio 등의 위젯처럼

사용자가 터치 등의 동작이 있을 때 반응해야 하는 위젯만이 Stateful 위젯에 해당됩니다.

 

왜 이렇게 나누어놓았는가?

우선 Stateful과 Stateless의 LifeCycle이 다릅니다.

당연히 상호작용이 필요없는 Stateless가 LifeCycle이 더 빠르게 동작하므로,

반응에 대한 비용을 절약할 수 있습니다.(Stateless가 속도가 빠름을 의미)

Stateful과 같이 상호작용이 필요한 부분은 사용자와 상호작용시마다

그 상태를 새로 업데이트해주어야 하기 때문에 LifeCycle 시간이 더 걸리게 됩니다.

즉, 더 효율적인 개발을 위해 위와 같이 나누어진 것이라고 보시면 되겠습니다.

반응형
반응형

플러터에서 앱 아이콘을 변경하는 방법을 설명한다.

 

해당 내용을 검색하다가 어이없는 설명을 발견...

 

플러터 사용자라면 모두가 알다시피 멀티플랫폼 개발이 가능하게 해주는 도구이다.

 

따라서, 앱 아이콘 또한 플러터에서만 한번 세팅을 해주면

 

각각의 플랫폼별로 세팅을 하지 않아도 자동적으로 동작하여야 한다.

 

그런데 내가 보았던 자료 중 하나는 각 플랫폼별로 직접 아이콘을 세팅해주는 내용이었다.

 

그러한 비효율적인 작업은 하지 않길 바라며 이 글을 작성해본다.

 

우선 원하는 아이콘을 구한 뒤 아래와 같이 세팅한다. (아이콘은 512x512로 작업하였다.)

 

위와 같이 프로젝트 루트에 icon 폴더를 만들고 아이콘 파일을 넣는다.

(경로는 자유롭게 지정하여도 된다.)

 

위와 같이 pubspec.yml 파일을 열어서 빨간박스의 내용들을 입력해준다.

image_path는 아이콘을 넣어준 경로를 지정하면 된다.

 

android: true

ios: true

이 두 부분이 플러터 자체에서 해당 아이콘을 알아서 각각의 플랫폼에 덮어씌워주는 역할을 한다.

 

거의 다 됐다. 

이제 실제로 위와 설정된 파일과 이미지를 패키지에 넣어주는 일만 해주면 된다.

 

위와 같이 Terminal 로 이동하여 위 두 명령어를 입력해주기만 하면 끝이 난다.

참고로 나는 플러터의 경로를 환경변수에 넣어주지 않아서 저렇게 실행 경로를 지정해주었으나,

환경변수에 넣어주면 실행파일명만 입력하면 된다

 

그리고 저 명령을 실행하는 위치는 반드시 자신의 프로젝트 경로에서 실행하여야 한다.

그렇지 않으면 오류가 발생하게 된다.

 

위처럼 완료되었다면 앱을 실행해보자.

아이콘이 바뀌어있는 것을 확인할 수 있을 것이다.

반응형
반응형

이 포스트는 STM32 칩을 쓰시는 분들 중 IAR을 사용하시는 분들에게 해당되는 내용이다.

 

위와 같은 오류를 한번쯤 경험했을 것이다.

 

일반적으로는 ST-LINK와 MCU간의 핀 맵핑이 잘못되어있거나,

MCU가 불량이거나, 전원이 제대로 들어가지 않거나 하는 등의 내용이 원인이다.

 

하지만 나의 경우는 더 난감한 경우를 경험하였다.

잘못된 코드를 다운로드하여 ST-LINK와 MCU와 연결을 할 수 없는 상태가 발생할 수 있는데

바로 이 상황을 겪었다.

 

문제의 코드는 바로 위의 '_HAL_AFIO_REMAP_SWJ_NOJTAG();'이다.

이것은 해당 ST-LINK가 다운로드 전용으로 사용하는 핀을 리맵핑하여

GPIO 등 다른 목적으로 쓰게 만들어준다.

하지만, 문제는 이렇게 하는 즉시 그 이후로는 다운로드 핀으로는 사용할 수 없게 되어버린다.

그 이후로는 맨 위의 디바이스를 찾을 수 없다는 메세지만 뜨게 된다.

해당 다운로드 핀을 반드시 써야하는게 아니라면 위의 코드는 쓰지 않는 것을 추천한다.

 

나는 보통 초기 MCU PIN 세팅 및 기본적인 세팅은 STM32CubeMX을 통해 코드화한다.

(STM32 칩을 쓰는 개발자라면 대부분이 이용할 것이다.)

나는 STM32CubeMX에서 각 기능을 세팅할 때 SYS의 Debug에 대해 관심을 갖지 않았었다.

하지만 저 부분을 Default인 'No Debug'로 두면 JTAG 혹은 ST-LINK와 같은 디버깅 툴을 사용하지

않는 것으로 간주하고, _HAL_AFIO_REMAP_SWJ_NOJTAG(); 코드를 생성해버린다.

 

위와 같이 ST-LINK를 사용한다면 Serial Wire, 그 외의 툴을 사용한다면 그에 맞게 지정하면 된다.

그리하면 위와 같은 코드가 생기지 않으며, 디버깅 툴을 문제없이 사용할 수 있게 된다.

 

이제 이미 잘못된 코드를 실수로 다운로드하여 더 이상 디버깅이 되지 않는 경우를

복구하는 방법을 설명할 것이다.

 

데이타시트를 보면 위와 같은 내용이 있다.

일반적으로 BOOT0을 GND에 붙여 사용하는데, BOOT0을 강제로 HIGH를 주고 전원을 넣을 경우

MCU는 메인 프로그램을 실행하지 않는다. 이 때는 디버깅 툴의 사용이 가능해지기 때문에,

해당 코드를 수정한 상태로 다운로드하고 원상복귀 시켜주면 해결이 된다.

 

이 외에도 Flash Loader를 이용해서 펌웨어를 다시 심는 방법도 있는데,

위 방법이 가장 간단한 것 같다.

반응형
반응형

 

이번에는 국가 코드를 가져오는 법을 알아볼 것이다.

다국어를 지원하는 앱을 개발하는 분들 중 단순히 텍스트 번역만이 아닌,

각 나라별로 프로그램의 동작이 바뀌어야 하는 등의 경우도 존재할 것이다.

그런 경우 어느 국가에서 실행했는지를 알아야 하는데,

이것을 국가 코드를 얻어와서 해결할 수 있다.

 

        Locale locale;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            locale = getApplicationContext().getResources().getConfiguration().getLocales().get(0);
        }else{
            locale = getApplicationContext().getResources().getConfiguration().locale;
        }
        String displayCountry = systemLocale.getDisplayCountry();
        String country = systemLocale.getCountry();
        String language = systemLocale.getLanguage();
 

코드는 위와 같다.

API Level 24 안드로이드 7.0(Nougat)부터는 getConfiguration()의 locale이 Deprecated되었기 때문에,

위처럼 조건으로 getLocales().get(0)을 사용해주어야 한다.

 

그 다음 코드를 보면 국가 코드를 가져오는 방법이 세가지가 있다.

 

첫번째 getDisplayCountry()는 나라 이름을 반환해준다.

한국이라면 "대한민국"

미국이라면 "United States"

이런 형식이다. 각 나라별 언어 문자로 반환을 하기 때문에 조금 불편할 수 있다.

 

두번째 getCountry()는 국가 코드를 반환해준다.

나의 경우는 이 국가 코드를 이용해서 국가를 구분한다.

한국이라면 "KR"

미국이라면 "US"

일본이라면 "JP"

중국이라면 "CH"

대만이라면 "TW"

이렇게 각 나라별로 고유의 국가 코드를 반환해준다.

 

세번째 getLanguage()는 국가 언어 코드를 반환해준다.

한국은 "ko"

미국은 "en"

일본은 "ja"

중국은 "zh"

대만도 "zh"

나라별로 국가 언어 코드를 반환해주지만,

중국과 대만은 구분되지 않는 것을 알 수 있다.

 

결론적으로 국가별 코드를 확실히 구분하려면 getCountry()를 사용하는 것을 추천한다.

 

 

반응형
반응형

 

안드로이드 핸들러를 잘 모르고 사용하시는 분들 중 제목과 같은 현상을 겪은 사람이 많을 것이다.

핸들러의 주 목적은 서브 쓰레드에서 주 쓰레드로 데이타를 전달해주는 것이다.

 

 예를 들면 아래와 같다.

토스트 같은 경우는 안드로이드에서 메세지 띄워주는 용도로 매우 유용한데,

메인 쓰레드에만 사용할 수 있으며 그 외의 쓰레드에서 사용하게 되면 오류를 내며 튕겨버린다.

서브 쓰레드에서 쓰기 위해 보통 아래와 같이 핸들러를 구성하고

서브 쓰레드에서 ProcessMessage() 함수를 호출하면 정상적으로 토스트가 동작한다.

 

하지만 코드에서 핸들러 부분이 블럭 처리되어있어서 무언가 찝찝하다.

마우스를 한번 갖다대보자.

 

핸들러를 정적으로 사용하지 않으면 메모리 릭이 발생할 수 있다는 의미이다.

'More'를 눌러서 더 자세한 내용을 보면 아래와 같다.

 

This Handler class should be static or leaks might occur (anonymous android.os.Handler) less... (Ctrl+F1)
Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected. If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references to members of the outer class using the WeakReference object.

 

정리하면 핸들러는 내부 클래스로 선언되어 가비지 컬렉터에 의해 소멸되지 않을 수 있다는 것이다.

그래서 핸들러를 정적 내부 클래스로 선언하면 해당 이슈를 해결할 수 있다.

추가로 정적 내부 클래스로 선언하게 되면, 외부 클래스의 정적멤버 외에는 접근할 수 없다.

그래서 혹시나 외부 클래스의 멤버에 접근하고 싶다면 WeakReference 객체를 이용하면 된다.

여기서는 단순히 토스트를 띄우는 것이 목적이므로 해당 객체를 사용하지는 않을 것이다.

 

서론이 길었는데 어쨌든 해결 방법은 간단하다.

위의 핸들러 관련 코드를 아래와 같이 수정하면 된다.

 

    private final MyHandler handler = new MyHandler();

    private static class MyHandler extends Handler {
        public MyHandler() {
        }

        @Override
        public void handleMessage(Message msg) {
            if(msg.arg1 == 1)
                Toast.makeText(Global.getContext(), "오류가 발생하였습니다.", Toast.LENGTH_SHORT).show();
            else if(msg.arg1 == 2)
                Toast.makeText(Global.getContext(), "정상적으로 처리되었습니다.", Toast.LENGTH_SHORT).show();
        }
    }

 

이처럼 단순히 정적 내부 클래스로 선언하면 된다.

그럼 메모리 릭의 걱정도 없고, 문제 없이 핸들러를 사용할 수 있다.

반응형
반응형

 

개발자들이 시간 측정의 용도로 GetTickCount()를 애용하고 있다.

 

정밀도 높은 시간 측정은 아니지만 편리한 맛에 많이 사용되고 있다.

 

GetTickCount() 함수를 간단하게 설명하자면, 이 함수는 윈도우즈가 부팅된 이후부터 시간이 카운팅되는 함수이며

 

수치는 1ms 단위로 카운팅된다. 즉, 윈도우즈 부팅 후 1초가 지났다면 반환 값은 1000이 된다.

 

하지만 이 함수는 한계가 있는데 바로 반환 시간이 최대 DWORD(32비트)라는 것이다.

 

날짜로 따지면 49.7일인데, 49.7일 동안 윈도우즈를 종료하지 않을 경우 0으로 초기화되는 것이다.

 

unsigned long Timer = GetTickCount();

while(true)
{
	if(GetTickCount() >= Timer + 1000) //1초가 지났는가?
	{
	    printf("1초 지남");
	    Timer = GetTickCount();
	}
}

위와 같은 코드가 있다고 하자.

 

1초에 한번씩 1초가 지났다는 메세지를 띄워주게 된다.

 

그런데 49.7일이 거의 다 된 상태에서 만약 "1초 지남"을 프린트하고 Timer 변수를 갱신한 뒤에,

 

49.7일이 지나 GetTickCount()가 0으로 초기화된다면?

 

즉, 예로 Timer = 10000이 들어간 상태에서 GetTickCount()가 0으로 초기화가 된다면

 

1초가 지날 때마다 조건을 만족해야함에도 불구하고 초기화로 인해서 10초를 더 기다려야 하는 상황이 발생한다.

 

49.7일 이전에 윈도우즈만 재부팅한다면 이런 것을 걱정할 필요는 없으나, 서버 등 계속 켜놓아야 하는 상황에서는

 

이런 상황이 발생할 수 있다.

 

그래서, 그 대안으로 GetTickCount64() 함수를 쓸 수 있다. 기존 GetTickCount()에서 범위만 커진 것이다.

 

64비트로 확장되었기 때문에, 5억년이 넘는다. 즉, 아무리 PC를 켜놓아아도 위와 같은 문제를 일으킬 일이 없다고 봐도 된다.

 

unsigned __int64 Timer = GetTickCount64();

while(true)
{
	if(GetTickCount64() >= Timer + 1000) //1초가 지났는가?
	{
	    printf("1초 지남");
	    Timer = GetTickCount64();
	}
}

이와 같이 변수 타입과 함수명만 바꾸어주면 되니 매우 간단하다.

 

결론적으로 GetTickCount()를 사용할 경우 상황에 따라, GetTickCount64() 사용하는 것도 고려해야할 것이다.

 

반응형
반응형

안드로이드에서 빌드할 때 INSTALL_FAILED_OLDER_SDK 오류가 발생하는 경우가 있다.

 

보통 이 경우는 안드로이드 스튜디오에서 설정한 안드로이드 SDK 버전과 타겟의 버전 안맞는 경우인데,

 

일반적으로 build.gradle의 minSdkVersion을 낮게 설정하여 해결이 되지만,

 

필자의 경우는 다른 경우였다.

 

build.gradle 파일 내 최하단에 보면 아래와 같은 코드가 있다.

 

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.1'
}

 

필자의 경우는 여기서 appcompat에 대한 버전이 옳지 않아서 발생하는 오류였다.

 

 compile 'com.android.support:appcompat-v7:22.2.1'

 

 compile 'com.android.support:appcompat-v7:22.1.0'으로 수정한 뒤 해당 문제가 해결되었다.

 

반응형
반응형

 

안드로이드 스튜디오에서 AppCompatActivity 를 상속받을 때 해당 클래스를 찾을 수 없다고 발생할 경우의 해결 방법이다.

 

build.gradle 파일을 열면 하단에,

 

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
}

이와 같이 입력되어있을 것이다. 아래와 같이 appcompat의 버전을 바꾸어준다.

 

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.1.0'

}

 

이후 해당 build.gradle을 Sync Now 시켜주면 해결된다.

반응형

+ Recent posts