키오스크 오픈소스 - kioseukeu opeunsoseu

개요

일반 Linux OS 와 Chrome browser 의 Kiosk 모드를 활용하는 방식은 많이 사용하고 있능 방식입니다. 본 글에서는 무료 키오스크 전용 OS 인 Porteus Kiosk (https://porteus-kiosk.org) 를 이용하여 키오스크를 구축하는 방법을 설명하고자 합니다. Porteus Kiosk 는 Linux OS 기반으로 만들어졌고, 오픈 소스로 공개적으로 사용이 가능한 방식으로 배포하고 있어서 누구나 쉽게 무료로 사용이 가능합니다.

장점

  • 최소한의 OS 와 응용 프로그램 패키지를 구비한 Browser 기반의 키오스크임
  • 수정 자동 잠김 – 한 번 배포한 키오스크의 경우, 해당 장비에서의 수정/변경이 불가능함. 원격 관리
  • 또는 설치 OS를 이용하여 직접 수동 설치해야만 함.
  • 필요한 응용 프로그램 패키지의 추가/삭제가 쉬움
  • 원격에서의 다수 키오스크 장비 관리 가능한 기능 제공
  • 패키지 크기가 작고, H/W 사양이 낮아도 설치/운영에 문제는 없음.
  • Online/Offline 운용이 가능

단점

  • 커스터마이즈 하는 것이 쉽지 않음
  • 추가 응용 프로그램 패키지의 설치가 쉽지 않음.

준비물

  • Porteus Kiosk 최신 버전
  • 키오스크 설치용 USB 메모리 스틱 2GB 이상
  • Win32 Disk Imager
  • 키오스크용 PC (Intel x86_64 만 지원함)  ( 최소 Memory 1GB / Disk 1 GB )
  • 터치 가능한 모니터

기본 설치 방법

기본 설치는 Porteus 정식 배포 버전의 이미지 파일을 다운로드 받아서 진행 가능하면 되는데 원 배포처의 Quick Installation 가이드가 잘 되어 있으니 깊게 설명하지 않겠습니다.

AD

  1. Porteus 웹 사이트의 다운로드 페이지(https://porteus-kiosk.org/download.html)에서 “Porteus Kiosk 4.9.0” ( 2019.11 현재 최신 버전 ) 를 다운로드 받음.
  2. 다운받은 이미지 파일을 Win32 Disk Imager (https://sourceforge.net/projects/win32diskimager/files/latest/download) 를 이용하여 USB 메모리 스틱에 Porteus Kiosk 이미지 파일 내용 설치. 메모리 스틱 용량은 2GB 정도면 충분.
  3. 실제 키오스크 시스템을 설치하고자 하는 장비에서 USB 부팅을 이용하여 부팅
  4. 자동적으로 Kiosk 설치 마법사 프로그램을 다운로드 받고, 설치를 진행함.
    이 과정에서는 인터넷 연결이 꼭 필요하므로 사전에 인터넷이 가능한 상태에서 작업을 해야 함.
  5. 설치 마법사를 종료하면 설정한 내용대로 설치 대상 장비 하드에 이미지 파일 형태로 설치가 진행됨.
  6. 설치용 USB 메모니 스틱을 제거하고 Reboot 해서 Kiosk 화면이 나타나면 성공

이미 설치한 키오스크의 설정 내용을 변경하려면 처음부터 설치 마법사 과정을 반복해야 합니다. Porteus Kiosk 는 인터넷을 통한 설치 마법사 다운로드를 통해서 설치가 이루어지기 때문에 동일한 형태의 키오스크 시스템을 다수 준비해야 하는 경우에 적용하기 적합한 방식은 아니다.

Photo by Ricardo Cruz on Unsplash

AD

Softonic은 당사의 플랫폼에서 호스트되는 모든 파일을 스캔하여 평가하고 기기에 잠재적으로 영향을 줄 수 있는 위험을 방지합니다. 당사 팀은 새 파일이 업로드될 때마다 검사를 수행하고 주기적으로 파일을 검토하여 파일 상태를 확인하거나 업데이트합니다. 이 종합적인 프로세스를 통해 다운로드 가능한 모든 파일의 상태를 다음과 같이 설정할 수 있습니다.

깨끗함

이 소프트웨어 프로그램은 깨끗할 가능성이 매우 높습니다.

이것은 무엇을 의미하나요?

당사는 50여 개가 넘는 세계의 유수한 안티바이러스 서비스에서 이 소프트웨어 프로그램과 연결된 파일 및 URL을 스캔했으며, 잠재적인 위협은 감지되지 않았습니다.

경고

이 소프트웨어 프로그램은 잠재적으로 악성이거나 필요 없는 번들 소프트웨어를 포함할 수 있습니다.

소프트웨어 프로그램이 아직도 제공되는 이유는 무엇입니까?

당사의 스캔 시스템에 기반하여, 이러한 플래그가 긍정 오류일 수 있다고 판단하였습니다.

긍정 오류란?

양성 프로그램이 안티바이러스 프로그램에 사용된 너무 광범위한 탐지 시그니처나 알고리즘으로 인해 악성으로 잘못 플래그 지정되었다는 것을 의미합니다.

차단됨

이 소프트웨어 프로그램은 악성이거나 필요 없는 번들 소프트웨어가 있을 가능성이 높습니다.

이 소프트웨어 프로그램이 더 이상 카탈로그에서 제공되지 않는 이유는 무엇입니까?

당사의 스캔 시스템에 기반하여 이러한 플래그가 실제 긍정일 가능성이 높다고 판단하였습니다.

프로젝트 주제

: 객체 이용한 “ 피자가게 키오스크 주문 프로그램 ” 만들기.

< 메인 클래스 >

package **main;**

import employee.Emp;
import kiosk.Kiosk;
import order.Order;

public class Main {
	
	public static Emp emp = new Emp("아이유 : ");
 ** // ✨클래스 변수 :** 

	public static void main(String[] args) {

		System.out.println("===== 피자가게 =====");
		
		//직원이 인사
		emp.saywelcome();
		
		//키오스크 사용하여, 주문 내용 얻기
		Kiosk kiosk = new Kiosk();
		Order order = kiosk.useKiosk();//타입이 Order 타입
		kiosk.calc(order); // **어려웠던 부분3️⃣ : total 가격 시간 나오게 함!**
		System.out.println(order);
		
	}

}

출력결과===================================================

===== 피자가게 =====
아이유 : 환영합니다~^^ 주문은 키오스크에서 진행해주세요
포장하시겠습니까?
y
====== 도우 ======
1. 일반 도우
2. 치즈 크러스트
3. 골드
4. 바이트
5. 리치골드
2
====== 토핑 ======
1. 콤비네이션
2. 페페로니
3. 치즈
4. 포테이토
5. 불고기
6. 고구마
7. 쉬림프
1
====== 사이드 ======
1. 스파게티
2. 감자튀김
3.3. 사이드 없음
2
====== 음료 ======
1. 사이다
2. 콜라
3. 환타
4. 음료 없음
2
Order [isTakeOut=true, dough=2, topping=1, side=2, drink=2, price=12000, time=11]

< employee 클래스 >

package employee;

import main.Main;

public class Emp {
	
	
	public Emp(String nick) {
		this.nick = nick;
	}

	private String nick;
	
	public void saywelcome() {
		System.out.println( nick +"환영합니다~^^ 주문은 키오스크에서 진행해주세요");
	}
	
	

}

< 키오스크 클래스>

package **kiosk**;

import java.util.Scanner;

import menu.Menu;
import menu.dough.Bite;
import menu.dough.Cheese;
import menu.dough.Gold;
import menu.dough.Normal;
import menu.dough.RichGold;
import menu.drink.Coke;
import menu.drink.Fanta;
import menu.drink.Sprite;
import menu.side.Spaghetti;
import menu.side.Wing;
import menu.topping.Potato;
import menu.topping.Shirimp;
import order.Order;

public class Kiosk { //사용자의 동작에 대해서 만든 클래스
	
	private Scanner sc = new Scanner(System.in);
	
	//주문 쭉 받기
	public Order useKiosk() {
		boolean isTakeOut = checkTakeOut();
		int dough = selectDough();
		int topping = selectTopping();
		int side = selectSide();
		int drink = selectDrink();
		int price = 0;
		int time = 0;		
		Order order = new Order(isTakeOut,dough,topping, side, drink, price, time);
		return order;
	}
	
	**//비용, 시간 계산하기 : 어려웠던 부분 1️⃣**
	public void calc(Order o){
	
		
		// 도우 선택지에 따른 가격, 시간 구하고 ,,, 주문 내역서에 더하기
		calcDough(o);
		// 토핑 선택지에 따른 가격, 시간 구하고 ,,, 주문 내역서에 더하기
		calcTopping(o);
		// 사이드 선택지에 따른 가격, 시간 구하고 ,,, 주문 내역서에 더하기
		calcSide(o);
		// 음료 선택지에 따른 가격, 시간 구하고 ,,, 주문 내역서에 더하기
		calcDrink(o);
	}
	
	
	private void calcDrink(Order o) {
		int drink = o.getDrink();
		if( drink == 1) {
			Menu m = new Coke();
			**o.addPrice(m.getPrice());
			o.addTime(m.getTime());  //어려웠던 부분2️⃣ : get~ ()에 인자값 대입!!**
			//o.calc(new Normal()); 한 줄로 처리할 수 있음!!!!!
		}else if( drink == 2) {
			Menu m =new Sprite();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if( drink == 3) {
			Menu m =new Fanta();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}
	}

	private void calcSide(Order o) {
		int side = o.getSide();
		if( side == 1) {
			Menu m = new menu.side.Potato();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if( side == 2) {
			Menu m = new Spaghetti();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if( side == 3) {
			Menu m = new Wing();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}
	}

	private void calcTopping(Order o) {
		int topping = o.getTopping();
		if(topping == 1) {
			Menu m = new menu.topping.Cheese();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if(topping == 2) {
			Menu m =new Potato();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if(topping == 3) {
			Menu m =new Shirimp();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}
	}

	private void calcDough(Order o) {
		int dough = o.getDough();
		if(dough == 1) {
			Menu m =new Normal();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if(dough == 2) {
			Menu m =new Cheese();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if(dough == 3) {
			Menu m =new Gold();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if(dough == 4) {
			Menu m =new Bite();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}else if(dough == 5) {
			Menu m =new RichGold();
			o.addPrice(m.getPrice());
			o.addTime(m.getTime());
		}
	}

	//포장여부 묻기
	private **boolean** checkTakeOut() { //포장여부(boolean) 물어보고 문자열 입력 후 리턴, 
                                     **리턴값은 boolean 타입!!**
		System.out.println("포장하시겠습니까?");
		
		String result = sc.nextLine();
	
		if(result.equalsIgnoreCase("Y")) {
			return true;
		}else {
			return false;
		}
		
	}
	
	//도우 선택
	private int selectDough() {
		//선택지 보여주기
		System.out.println("====== 도우 ======");
		System.out.println("1. 일반 도우");
		System.out.println("2. 치즈 크러스트");
		System.out.println("3. 골드");
		System.out.println("4. 바이트");
		System.out.println("5. 리치골드");
		
		String result = sc.nextLine();
		return Integer.parseInt(result);
		
//		int result = sc.nextInt();
//		sc.nextLine(); // 엔터키 제거
	}
	
	
	//토핑 선택
	private int selectTopping() {
		System.out.println("====== 토핑 ======");
		System.out.println("1. 콤비네이션");
		System.out.println("2. 페페로니");
		System.out.println("3. 치즈");
		System.out.println("4. 포테이토");
		System.out.println("5. 불고기");
		System.out.println("6. 고구마");
		System.out.println("7. 쉬림프");
		
		String result = sc.nextLine();
		return Integer.parseInt(result);
		
		
	}
	
	
	//사이드 선택
	private int selectSide() {
		System.out.println("====== 사이드 ======");
		System.out.println("1. 스파게티");
		System.out.println("2. 감자튀김");
		System.out.println("3. 윙");
		System.out.println("3. 사이드 없음");
		
		String result = sc.nextLine();
		return Integer.parseInt(result);
		
		
	}
	//음료 선택
	private int selectDrink() {
		System.out.println("====== 음료 ======");
		System.out.println("1. 사이다");
		System.out.println("2. 콜라");
		System.out.println("3. 환타");
		System.out.println("4. 음료 없음");
		
		String result = sc.nextLine();
		return Integer.parseInt(result);
		
		
	}
}

< 메뉴 클래스 >

: menu 클래스를 부모 클래스로 이용!

package **menu;**

public class Menu {
	
	public Menu(int price, int time) {
		this.price = price;
		this.time = time;
	}
	
	private int price;
	private int time;
	
	public int getPrice() {
		return price;
	}
	public int getTime() {
		return time;
	}

}

: (자식 클래스 중 일부 발췌) menu 클래스를 상속 받아 자식 클래스에서 이용!

package menu.**dough**;

import menu.Menu;

public class Cheese extends Menu{
	
	public Cheese() {
		**super(2000,2); // 생성자 만들어준 뒤 부모클래스에 인자값을 대입해줌.**
	}

}