[Android] 서비스 (Service)

참고링크 : https://developer.android.com/guide/components/services?hl=ko


서비스는 백그라운드에서 오래 실행되는 작업을 수행할 수 있는 애플리케이션 구성요소.

사용자 인터페이스 제공안함.


서비스는 본질적으로 두 가지 형식을 취함

  • 시작됨 : startService()를 호출하여 시작되며, 한번 시작되고 나면 백그라운드에서 무기한으로 실행 될 수 있음. 해당 서비스를 시작한 구성 요소가 소멸되었더라도 무관함. 작업을 수행하고 결과를 호출자에게 반환하지 않음
  • 바인드 됨 : bindService()를 호출하여 바인드 되며, 클라이언트-서버 인터페이스를 제공하여 구성 요소가 서비스와 상호작용할 수 있도록 해줌. 바인드된 서비스는 또 다른 애플리케이션 구성 요소가 이를 바인드되어 있는 경우에만 실행됨. 여러 개의 구성 요소가 서비스에 한꺼번에 바인드될 수 있지만, 이 모든 것이 바인딩을 해제하면 서비스가 소멸됨.

서비스는 위 두 가지 방식 모두 취할 수 있음.

서비스는 자신의 호스팅 프로세스의 기본 스레드에서 실행됨.

자신의 스레드를 직접 생성하지 않으며, 별도의 프로세스에서 실행되지도 않음.

기본 스레드 외부에서 작업을 수행해야 하지만, 사용자가 애플리케이션과 상호작용 중인 동안에만 수행하면 되는 경우라면, 서비스가 아니라 그 대신 새 스레드를 생성해야 함.


  • onStartCommand() : 다른 구성요소가 서비스를 시작하도록 요청한 경우.(바인딩만 제공시 이 메서드는 구현하지 않아도 됨.)
  • onBind() : 다른 구성요소가 서비스에 바인드되고자 하는 경우. 클라이언트가 서비스와 통신을 주고받기 위해 사용할 인터페이스를 제공해야 함. IBinder를 반환함.


한 구성 요소가 startService()를 호출하여 서비스를 시작하면(onStartCommand() 호출 발생) 해당 서비스는 스스로 stopSelf()나 다른 구성요소가 stopService()를 호출하기 전까지 실행 중인 상태 유지함.


한 구성 요소가 bindService()를 호출하여 서비스를 시작하면(onStartCommand() 호출 안함) 해당 서비스는 해당 구성 요소가 바인딩된 경우에만 실행됨. 모든 클라이언트로 바인딩 해제되면 소멸됨.


서비스는 기본적으로 메인 스레드에서 실행되므로, 성능에 영향일 미치는 작업은 서비스 내에서 새 스레드를 시작해야 함.


IntentService는 Service의 서브클래스로 기본 작업자 스레드를 생성하여 모든 시작 요청을 처리하되 한번에 하나씩 처리함. 여러 개의 요청을 동시에 처리하지 않아도 되는 경우 최선의 옵션. onHandleIntent()를 구현하면 됨. 시작 요청이 모두 처리된 후 서비스를 중단하므로 stopSelf()를 호출할 필요 없음.


onStartCommand() 메서드의 반환 값

  • START_NOT_STICKY : 서비스 중단되면 재생성 안됨.
  • START_STICKY : 서비스 중단되면 재생성하고 onStartCommand() 호출됨. null 인텐트로 처리됨.
  • START_REDELIVER_INTENT : 서비스 중단되면 재생성하고 onStartCommand() 호출됨. 서비스에 마지막에 전달된 인텐트로 처리됨.


바인드된 서비스를 생성하려면 onBind() 콜백 메서드를 구현하여 서비스와 통신을 위한 인터페이스를 정의하는 IBinder를 반환하도록 해야 함.


바인드된 서비스는 onStartCommand()를 통해 시작된 서비스와 달리 중단시키지 않아도 됨.


여러 클라이언트가 서비스에 한꺼번에 바인딩 된 경우 서비스와 상호작용 완료시 unbindService()를 호출하여 바인딩 해제함. 바인딩된 클라이언트가 없을 경우 서비스는 소멸됨.


포그라운드 서비스 실행시 startForeground()를 호출하며 상태 표시줄에 대한 알림인 Notification과 매개변수로 알림을 식별하는 정수를 사용함.(정수는 0이면 안됨.)

  • Unbounded Service
    • Call to startService()
    • onCreate()
    • onStartCommand()
    • Service running
    • The Service is stopped by itself or a client
    • onDestroy()
    • Service shut down
  • Bounded Service
    • Call to bindService()
    • onCreate()
    • onBind()
    • Clients are bound to service
    • All clients unbind by calling unbindService()
    • onUnbind()
    • onDestroy()
    • Service shut down


우려하던 대로 2019.01.02일자로 또 바뀌었네요. 내용 추가합니다.




앱에서 최신 앱 버전을 체크하기 위해 구글플레이의 링크를 이용해 따시는 경우들이 종종 있습니다. 


서버가 있어 서버에 등록하고 쓴다면 좋겠지만, 앱 업데이트시 마다 변경해야 하고 서버 자체가 없는 경우도 있다보니..


편의상 아래 링크처럼 구글플레이의 앱 링크를 열어 html을 긁어서 사용하는 모양새들인데요.


http://gun0912.tistory.com/8


언제인지는 정확히 모르겠지만... 기존에 알던 html 양식이 바뀌었습니다...;;;; (아마 2018.12월말부터??)


위 블로그에서는 2가지 방식을 권하고 있지요. jsoup을 사용하는 방식과 HttpURLConnection을 사용하는 법이요.


 먼저 jsoup을 사용하는 경우 기존 아래 같은 부분이..


	Elements Version = doc.select(".content");

	for (Element mElement : Version) {
		if (mElement.attr("itemprop").equals("softwareVersion")) {
			return mElement.text().trim();
		}
	}


아래와 같이 바꾸시면 되고요.


	Elements Version = doc.select(".htlgb").eq(3);

	for (Element mElement : Version) {
		return mElement.text().trim();
	}


HttpURLConnection을 사용하는 방식으로 하셨을 경우는 아래의 부분을..

	String startToken = "softwareVersion\">";
	String endToken = "<";


아래와 같이 바꾸시면 됩니다. (2018.04.17 일자 내용 추가)


	String startToken = "<div class="BgcNfc">Current Version</div><span class="htlgb"><div><span class="htlgb">";
        // 2018.04.17일자 이전
	// String startToken = "<div class=\"BgcNfc\">Current Version</div><div><span class=\"htlgb\">";
	String endToken = "</span></div>";


또 바겼습니다. 아래와 같이 바꾸시면 됩니다. (2019.01.04 일자 내용 추가)


	String startToken = "<div class=\"BgcNfc\">Current Version</div><span class=\"htlgb\"><div class=\"IQ1z0d\"><span class=\"htlgb\">";
// 2019.01.04일자 이전 // String startToken = "<div class="BgcNfc">Current Version</div><span class="htlgb"><div><span class="htlgb">"; // 2018.04.17일자 이전 // String startToken = "<div class=\"BgcNfc\">Current Version</div><div><span class=\"htlgb\">"; String endToken = "</span></div>";

다만 위와 같은 방법은 구글플레이 html 양식이 바뀐다면 또 문제가 되겠지요.


가능하시다면 번거럽더라도 다른 방법을 찾는게 맞을듯 싶습니다.


아 추가로 기존에 HttpURLConnection의 메소드 타입을 GET, POST 상관없이 구글플레이 html을 받아올 수 있었는데요.


오늘 확인해보니 POST로 할 경우 html을 받아올 수 없더군요. GET으로 하셔야 합니다.


이상 구글플레이에서 앱 버전 따기 간단히 남겨봅니다.

Docker 정리

Docker 란?

2013년에 등장한 새로운 컨테이너 기반 가상화 도구

계층화된 파일 시스템을 사용해 가상화된 컨테이너의 변경사항을 추적 및 관리

컨테이너 특정 상태를 항상 보존해두고, 필요할 때 언제 어디서나 실행할 수 있도록 도와주는 도구


기존 가상머신

가상 머신은 격리된 환경을 구축해준다는 데서 매력적

실제 배포용으로 쓰기에는 성능 면에서 불리한 도구

운영체제 위에서 또 다른 운영체제를 통째로 돌리는 구조라 리소스를 비효율적으로 활용하게 됨

Docker

어느 플랫폼에서나 재현가능한 어플리케이션 컨테이너를 만들어주는 것을 목표함

LXC(리눅스 컨테이너)라는 개념에서 출발함으로써 특정 리눅스 배포판에서 사용 가능

가상 머신이라고 하기보다는 격리된 환경을 만들어주는 도구

컨테이너와 이미지의 차이와 Dockerfile 만든 법 등을 익히는게 중요함

Docker에서 말하는 장점들

  • 유연성 (Flexible) : 가장 복잡한 애플리케이션조차도 컨테이너화할 수 있습니다.
  • 경량 (Lightweight) : 컨테이너는 호스트 커널을 활용하고 공유합니다.
  • 교환 가능 (Interchangeable) : 업데이트 및 업그레이드를 즉시 배포 할 수 있습니다.
  • 휴대성 (Portable) : 로컬로 구축하고, 클라우드에 배치하고, 어디서나 실행할 수 있습니다.
  • 확장성 (Scalable) : 컨테이너 복제본을 늘리고 자동으로 배포 할 수 있습니다.
  • 스태킹 (Stackable) : 서비스를 세로 및 가로로 쌓을 수 있습니다.


Docker 제품군

Community Edition (CE)

Docker를 시작하고 컨테이너 기반 앱을 실험하려는 개발자 및 소규모 팀에 이상적 (무료)

두 가지 업데이트 채널을 가짐

  • Stable : 분기마다 안정적인 업데이트 제공
  • Edge : 매월 새 기능 제공

Enterprise Edition (EE)

업무용 응용 프로그램 제작, 배송 및 실행하는 엔터프라이즈 개발 및 IT팀을 위한 설계 (유료)

Docker CE와 EE 간 비교 이미지 (출처: Docker Docs, https://docs.docker.com/install/)

지원 플랫폼

Desktop

Cloud

Server

Docker EE

Docker CE

Docker 설치하기

Ubuntu의 경우 Docker CE설치시

OS requirements (18년 3월 22일 기준)

Docker CE는 아래 버전 중 하나의 64비트 버전이 필요함

  • Artful 17.10 (Docker CE 17.11 Edge and higher only)
  • Xenial 16.04 (LTS)
  • Trusty 14.04 (LTS)

Docker CE는 Ubuntu에서 x86_64armhfs390x (IBM Z), and ppc64le (IBM Power) 아키텍쳐를 지원함

(ppc64le and s390x limitations: IBM Z 및 Power 아키텍쳐 패키지는 Ubuntu Xenial 이상만 사용 가능)

Docker CE 설치

  • Docker repositories를 설정 후 설치
  • DEB 패키지 다운로드 후 수동 설치
  • 스크립트를 사용하여 설치

Docker Storage를 설정 후 설치 방법

## 패키지 업데이트
    $ sudo apt-get update
    ...
    ## HTTPS를 통해 repository를 사용할 수 있도록 패키지 설치
    $ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
    ...
    ## Docker 공식 GPG 키 추가
    ## Key fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 확인
    $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    $ sudo apt-key fingerprint 0EBFCD88
    pub   4096R/0EBFCD88 2017-02-22
    Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
    uid                  Docker Release (CE deb) <docker@docker.com>
    sub   4096R/F273FCD8 2017-02-22
    ...
    ## stable repository 사용시 아래 커맨드 추가
    ## arch 값을 amd64, armhf, ppc64el, s390x 등으로 맞춰서 사용
    $ sudo add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
       $(lsb_release -cs) \
       stable"
    ...
    ## 패키지 업데이트
    $ sudo apt-get update
    ...
    ## 옵션 1. Docker CE 최신 버전 설치
    $ sudo apt-get install docker-ce
    ...
    ## 옵션 2. Docker CE 특정 버전 설치
    $ apt-cache madison docker-ce
    docker-ce | 17.12.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
    $ sudo apt-get install docker-ce=<VERSION>
    ...
    ## hello-world 이미지를 실행하여 Docker CE가 올바르게 설치되었는지 확인
    $ sudo docker run hello-world

다른 OS에서 Docker 설치

Docker 제거

Docker CE 제거

Docker CE 패키지 제거

$ sudo apt-get purge docker-ce

Image, Container, Volume, 사용자 정의 구성파일 등은 자동으로 제거 안됨.

모든 데이터를 삭제하려면 아래처럼 실행

$ sudo rm -rf /var/lib/docker

Docker Image

이미지는 추상적인 개념이며, 이미지를 기반으로 생성된 컨테이너가 실행됨

이미지는 코드, 런타임, 도서관, 환경 변수 및 구성 파일 등 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하는 실행 가능한 패키지

Docker Image 관련 명령어

docker images

현재 시스템에서 사용 가능한 이미지 리스트

$ docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    hello-world         latest              f2a91732366c        4 months ago        1.85kB

docker pull 

이 명령어를 사용하면 docker.io의 공식 저장소에서 이미지를 다운로드

공식 저장소에 있는 이미지 정보들은 https://hub.docker.com/explore/에서 확인 가능

$ docker pull ubuntu
    Pulling repository ubuntu
    04180f9bd8a6: Download complete
    1e548c932d40: Download complete
    ...

Docker Container

컨테이너는 기본적으로 리눅스에서 실행되며, 다른 컨테이너와 호스트 시스템의 커널을 공유

더 많은 메모리를 사용하지 않고 개별 프로세스를 실행하여 가볍게 만듬

Docker Container 관련 명령어

docker run

특정 이미지로 컨테이너 생성 및 실행

$ docker run -i -t ubuntu:12.04 /bin/bash
    root@8bfd70fe7392:/#

docker ps

실행 중인 컨테이너들을 출력 (전체 볼때는 docker ps -a)

$ docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS
    0fae5858c9c0        ubuntu:12.04        /bin/bash           8 seconds ago       Up 7 seconds

    PORTS               NAMES
    sleepy_nobel

docker start <Container name/id>

생성되어 있는 컨테이너를 실행

$ docker start a37f1348c4c4
    a37f1348c4c4
    $ docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS
    a37f1348c4c4        hello-world         "/hello"            25 minutes ago      Up 7 seconds

    PORTS               NAMES
    sleepy_nobel

docker stop <Container name/id>

실행 중인 컨테이너를 정지

$ docker stop a37f1348c4c4
    a37f1348c4c4
    $ docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS
    a37f1348c4c4        hello-world         "/hello"            25 minutes ago      Exited(0) 25 minutes ago

    PORTS               NAMES
    sleepy_nobel

docker exec -it <Container name/id>

실행 중인 컨테이너에 진입시

쉘이 안떠있는 컨테이너일 경우 : docker exec -it <Container name/id> /bin/bash

$ docker attach e2af613
    root@e2af61348652:/#

docker stop $(docker ps -a -q)

실행 중인 컨테이너들 전체 정지시

$ docker stop $(docker ps -a -q)
    a37f1348c4c4
    e2af6134a1s2
    ...

참고 자료

Docker 공식 문서 : https://docs.docker.com/

nacyout님의 "도커(Docker) 튜토리얼:깐 김에 배포까지" : http://blog.nacyot.com/articles/2014-01-27-easy-deploy-with-docker/

(18년 3월 22일 기준 정리)


신논현역 주변 후쿠오카 함바그 집입니다.

지도 크게 보기
2018.3.18 | 지도 크게 보기 ©  NAVER Corp.


지나다니다 보면 행사 입간판이 자주 붙는 곳이기도 합니다.

저는 7천원짜리 행사메뉴로 먹었습니다.

계란을 밑에 깔고 고기덩어리에 토핑을 얹어 나오는 형태입니다.

밥과 국물 그리고 간단한 반찬과 소스가 곁들여 나옵니다.

고기는 조금씩 덜어 동그란 돌판 위에 익혀서 먹으면 됩니다.

나름 고기 구워먹는 재미가 있지만, 귀찮아하시는 분도 있을 것 같네요.

맛있게 먹었지만, 그리 특색있거나 먼 곳에서 일부러 찾아갈 정도까진 아닌 것 같네요.


우리 동네에도 특색있고 맛있는 집이 생겼다.

봉천동 언덕배기 어딘가에 덮밥인봉천이라는 식당이 생겼네요.

지도 크게 보기
2018.3.18 | 지도 크게 보기 ©  NAVER Corp.


여러가지 덮밥을 파는 곳인데요.

아담한 가게에서 아기자기하게 주변 주민들 상대로 장사를 하시는 느낌이네요.

분위기에 한번 음식 맛에 한번 즐거움을 느끼게 되네요.

저희가 시킨 요리는 토시살 스테이크 덮밥(8,500원)과 명란 우삽겹 덮밥(7,000원)이었습니다.

여유가 필요할때 다시 찾고 싶은 맛집입니다.


가고 싶어도 이젠 갈 수 없는 닭갈비 맛집

강남에서 7천원으로 즐길 수 있는 닭갈비 집이 있었습니다.

지도 크게 보기
2018.3.18 | 지도 크게 보기 ©  NAVER Corp.

닭갈비에 쫄면사리도 넣어주고, 미린다도 서비스로 나오는 집이었죠.

거기다 고기를 다 먹어가면 밥도 볶아주는 좋은 곳이었죠.

언제가도 맛이 좋아 즐겨찾던 곳이었습니다.

어느 순간부터 인터리어 공사를 하더니 이젠 그곳엔 다른 식당이 들어섰답니다.

아쉽지만 이젠 갈 수가 없게 되어버렸네요.



지도 크게 보기
2018.3.18 | 지도 크게 보기 ©  NAVER Corp.

이 메뉴는 지금도 하시는지는 모르겠네요.

약 1년 전쯤에 노랑통닭에서 점심에도 치킨을 먹을 수 있는 메뉴를 내놓아 먹었었죠.

치킨과 밥과 몇가지 반찬 그리고 커피(외산 콜라)가 구성이었습니다.

치킨이란 항상 옳기에 시도를 했지만, 안타깝게도 그리 인상적인 메뉴는 아니었습니다.

지금도 이 메뉴를 하시는지 모르겠지만, 약간 실험적인 메뉴였던 것 같네요.

사진은 2인분이고, 1인분당 7천원이랬죠.

아무튼 추억의 메뉴입니다.


넘쳐나는 부대찌개 가게들 중에서 가성비가 좋은

부대찌개는 직장인들이 즐겨먹는 메뉴이기도 하면서 프랜차이즈도 점점 늘어나는 메뉴이기도 하죠.

이 집은 그런 집 중 기본적인 맛으로 항상 맛있게 먹고 가는 집입니다.

지도 크게 보기
2018.3.18 | 지도 크게 보기 ©  NAVER Corp.

육수국물로 끓여서 칼칼한 국물과 라면, 우동사리와 햄들이 전통적인 부대찌개 맛입니다.

거기다 7천원으로 밥과 라면사리도 무한리필이라니 참 좋지요.

반찬이 많고 좋은 편은 아니지만, 부대찌개라는 메인을 생각하면 그 정도는 감수할만 한 것 같네요.

부대찌개를 즐기시는 분들께는 추천할만 합니다.


백짬뽕이 인상적인 신림 중국집

신림사거리에서 조금 벗어난 곳에 위치한 아리차이라는 중국집입니다.

지도 크게 보기
2018.3.18 | 지도 크게 보기 ©  NAVER Corp.

사실 이 글도 1년 반쯤 먹을때 찍은 사진으로 작성하는 것이라 금액같은 부분은 가물가물하기도 합니다.

백짬뽕은 7천원이었을 겁니다.

탕수육은 얼마였는지 기억이 잘 안나네요. 

그저 맛있었을 뿐..;

제가 아리차이에 가면 즐겨먹는 백짬뽕입니다.

매콤하면서도 깔끔한 맛이 좋습니다.

물론 저 고추를 먹으면 엄청 맵습니다;;

탕수육도 아주 맛있었습니다.

다른 요리들을 먹을때도 기본 이상을 해주는 곳이었습니다.

특히 새우 딤섬이 맛있기도 하죠.

주변에 지인과 만날 일이 있을 때 즐겨가는 곳입니다.

신림에 가실 일이 있으시다면 추천할만한 곳입니다.


1년 반쯤 전에 갔던 설담재라는 구로디지털단지 설렁탕 집입니다.

지도 크게 보기
2018.3.18 | 지도 크게 보기 ©  NAVER Corp.


당시에는 생긴지 얼마 안된지 깔끔한 실내와 간판을 자랑하고 있습니다. 

가격은 떡만두설렁탕이 8천원으로 일반적인 가격이었죠.

만두는 맛이 좋았지만, 국물이 그리 진한 맛은 아니었죠.

조미료를 안쓴듯 한데 이 때문에 입맛에 안맞아 하시는 분들도 있었습니다.

그리고 떡만두설렁탕을 시켰는데 밥은 나오지않습니다.

전 깔끔하게 느꼈으나 내용물이 푸짐한 느낌은 아닙니다. 

김치와 깍두기도 단맛을 많이 안낸 일반적인 맛이라 설렁탕 반찬으로 호불호가 갈릴듯 싶네요.

전체적으로 깔끔하고 건강한 맛인 듯 하지만 푸짐한 느낌은 아쉬웠답니다.


+ Recent posts