자바로 키오스크 만들기(5.27~ 5.30)

김성수·2023년 5월 30일
0

키오스크

목록 보기
1/4

들어가면서

자바로 키오스크 만들기 개인과제가 주어졌다.
키오스크 프로젝트를 만드는 과정을 기록해보려 한다.

뭐부터 해야할까..

처음 개인과제를 해결해야할 때 많이 막막했다.

뭐부터 손을 대야할까..

고민하다가 일단 문제부터 제대로 이해하기로 결심했다.

문제를 다섯번 정도 읽다보니 전체적인 흐름과 구상이 떠오르기 시작했다.


"이 문제는 이 자료구조를 사용하면 되겠구나",

"이 문제는 이러이러한 방식으로 해결하면 되겠구나"

라는 생각이 들었다.


설계를 먼저해야할까, 작은 기능부터 구현해나가야할까

설계를 해보려 했지만 내 역량으로는 역부족이라고 느껴서 작은 기능부터 만들면서

확장해나가기로 했다.


꾸준하게 알고리즘 문제를 풀었던게 큰 도움이 되었다.

알고리즘을 풀려면 자료구조, 알고리즘, 문제 해결 로직 등을 설계하고 구현해야 하는데,

이러한 경험들이 프로젝트를 만들 때 큰 도움이 되고 있다.


예를 들면, boolean flag를 만들어서 중복 상품명을 출력하지 않게 만든다거나

ArrayList, HashMap 등을 사용해본 경험이 도움이 되었던 것 같다.

package main;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 주문한 상품 객체를 담는 클래스
 * 요구사항 : 주문 클래스도 만들어서 상품 객체를 담을 수 있도록 해주세요.
 */
public class OrderList {
    public ArrayList<ProductMenu> orderLists = new ArrayList<>();
    // 제품 주문 수량
    public Map<String, Integer> productCnt = new HashMap<>();

    // 주문 확인 버튼 클릭 시 장바구니에 값을 담는다.
    public void addProduct(ProductMenu productMenu, int addProductCnt){
        orderLists.add(productMenu);

        productCnt.put(productMenu.name, productCnt.getOrDefault(productMenu.name, 0)+1);

        System.out.println(orderLists.get(addProductCnt-1).name + "가 장바구니에 추가되었습니다.");
        System.out.println();
    }

    // 장바구니에 담긴 값 출력
    public void orderProductList() {
        double total = 0;

        System.out.println("아래와 같이 주문하시겠습니까?");
        System.out.println();
        System.out.println("[ Orders ]");

        // 장바구니 리스트 출력
        // 장바구니에 같은 상품을 여러개 담았을 때 갯수 증가하고, 중복되는 상품명 출력 x
        if(!orderLists.isEmpty()) {
            System.out.println(orderLists.get(0).name + " | Won " + orderLists.get(0).price + " | " + productCnt.get(orderLists.get(0).name) + "개 | " + orderLists.get(0).description);
            total = orderLists.get(0).price;

            for (int i = 1; i < orderLists.size(); i++) {
                boolean flag = true;
                total += orderLists.get(i).price;
                for (int j = i - 1; j >= 0; j--) {
                    if (orderLists.get(i).name == orderLists.get(j).name) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    System.out.println(orderLists.get(i).name + " | Won " + orderLists.get(i).price + " | " + productCnt.get(orderLists.get(i).name) + "개 | " + orderLists.get(i).description);
                }
            }
        }
        System.out.println();

        String resultTotal = String.format("%.1f", total);

        System.out.println("[ Total ]");
        System.out.println("Won " + resultTotal);
        System.out.println();
    }

    // 주문 완료 시 장바구니에 담겨있던 객체 clear()
    // 제품 주문 수량도 초기화
    public void clearOrder(){
        orderLists.clear();
        productCnt.clear();
    }
}

웹 프로젝트 경험이 도움이 되었다.

순수한 Java로 프로젝트를 만드는건 계산기 이후로 처음이었어서 많이 막막했었다.

그래도 포기하지 않고 문제를 해결하려고 하다보니 view와 Domain 클래스가 없을 뿐 웹 개발과 별 다를게 없다는걸 깨달았다.

덕분에 수월하게 문제를 해결해나갈 수 있었다.


메인 메뉴에서는 버거, 디저트, 음료, 치킨 4개의 메뉴를 보여주는데,

이 중 원하는 메뉴를 선택하면 상세 상품으로 들어갈 수 있도록 해야한다.


메인 메뉴에서는 사용자가 입력하는 역할만 수행하도록 하고, 실제 기능(비즈니스 로직)은 각 객체별로 분리하여

결합도를 낮추고, 응집도를 높여보는 시도를 했다.

나중에 튜터님께 피드백을 받아보는 시간을 가져보려 한다.

(더 객체지향적으로 구현하고 싶은 욕심이 있다.)


  while (true) {

            // 메인 메뉴리스트를 출력합니다.
            // 메인 메뉴가 변경될 때마다 main.MainMenu 클래스를 변경되지 않도록 클래스를 분리하여 결합도를 낮춥니다.
            MainMenuList mainMenuList = new MainMenuList();
            mainMenuList.mainMenuList(menuName);

            // 메인 메뉴판 초이스 버거, 디저트, 음료, 치킨 중...
            int choiceMenu = in.nextInt();

            // 화면 전환 효과를 위해 공백을 입력합니다.
            T.clearScreen();

            // 상세 메뉴를 추상화한 Product
            // Product 객체를 통해 case 문마다 객체를 갈아끼워주지 않아도 됨.
            Product product;

            switch (choiceMenu) {
                case 1:
                    product = new Product(new Buger());

                    System.out.println("롯데리아에 오신걸 환영합니다.");
                    System.out.println("아래 상품메뉴판을 보시고 상품을 골라 입력해주세요.");
                    System.out.println();

                    // 상세 상품 메뉴를 출력합니다.
                    product.detailMenu();

                    // 상세 상품 선택
                    choiceDetailMenu = in.nextInt();

                    T.clearScreen();

                    // 메뉴를 선택합니다.
                    choiceProduct = product.choiceProduct(choiceDetailMenu);

                    // 장바구니에 담을지 말지 결정합니다.
                    // 1. 확인   2. 취소
                    orderOrCancel = in.nextInt();

                    T.clearScreen();

                    // 확인 버튼 클릭 시 장바구니에 상품 메뉴가 담긴다.
                    // 취소 버튼 클릭 시 장바구니에 상품이 담기지 않고 메인 메뉴로 돌아간다.
                    if (orderOrCancel == 1) {
                        // 선택한 상품 추가
                        addProductCnt++;
                        orderList.addProduct(choiceProduct, addProductCnt);
                    } // case Buger end
                    break;

테스트 코드도 작성하였다.

아직 테스트 코드를 작성하는게 많이 어렵다.

테스트 코드를 작성하는 것 보다 메인 메뉴에서 직접 코드를 삽입하고 실행해보면서

정상 작동되는지, 어떤 문제가 있지는 않은지 확인하는 것이 더 명확하고 빠르다고 느끼고 있다.

아직 테스트 코드를 작성하는 실력이 많이 부족하기 때문이라고 생각한다.

public class BugerTest {
    public static void main(String[] args) {
        Buger buger = new Buger();
        OrderList orderList = new OrderList();
        Scanner in = new Scanner(System.in);
        buger.detailMenu();

        int detailChoice = in.nextInt();

        ProductMenu productMenu = buger.choiceProduct(detailChoice);

        int addProduct = in.nextInt();
        int addProductCnt = 0;

        if(addProduct == 1){
            addProductCnt++;
            orderList.addProduct(productMenu, addProductCnt);
        }

        orderList.orderProductList();
    }
}

Abstract 사용하기

Java 강의를 들으면서 Abstract를 배웠다.

abstract를 직접 사용해서 Product 부모 객체를 통해 자식 객체들을 갈아끼우기만하면

메서드 호출은 동일하도록 하여 다형성과 유지보수성을 높였다.

  case 1:
                    product = new Product(new Buger());

                    System.out.println("롯데리아에 오신걸 환영합니다.");
                    System.out.println("아래 상품메뉴판을 보시고 상품을 골라 입력해주세요.");
                    System.out.println();

                    // 상세 상품 메뉴를 출력합니다.
                    product.detailMenu();

                    // 상세 상품 선택
                    choiceDetailMenu = in.nextInt();

                    T.clearScreen();

                    // 메뉴를 선택합니다.
                    choiceProduct = product.choiceProduct(choiceDetailMenu);

                    // 장바구니에 담을지 말지 결정합니다.
                    // 1. 확인   2. 취소
                    orderOrCancel = in.nextInt();

                    T.clearScreen();

                    // 확인 버튼 클릭 시 장바구니에 상품 메뉴가 담긴다.
                    // 취소 버튼 클릭 시 장바구니에 상품이 담기지 않고 메인 메뉴로 돌아간다.
                    if (orderOrCancel == 1) {
                        // 선택한 상품 추가
                        addProductCnt++;
                        orderList.addProduct(choiceProduct, addProductCnt);
                    } // case Buger end
                    break;
                case 2:
                    product = new Product(new Dessert());

                    System.out.println("롯데리아에 오신걸 환영합니다.");
                    System.out.println("아래 상품메뉴판을 보시고 상품을 골라 입력해주세요.");
                    System.out.println();

                    product.detailMenu();

                    choiceDetailMenu = in.nextInt();

                    T.clearScreen();

                    choiceProduct = product.choiceProduct(choiceDetailMenu);

                    orderOrCancel = in.nextInt();

                    T.clearScreen();

                    if (orderOrCancel == 1) {
                        addProductCnt++;
                        orderList.addProduct(choiceProduct, addProductCnt);
                    } // case Dessert end
                    break;

현재는 case 별로 메뉴 선택을 나눠놨는데 나중에는 case 내부에 구현된 반복되는 코드를 제거하고 싶은 마음이 있다.

github 사용하기

github을 꾸준하게 사용하고 있다.

예전에는 인텔리제이에서 제공하는 commit 기능만 주구장창 썼었는데,

gitbash를 배우고 나서 gitbash로만 github을 사용하고 있다.

dev branch를 만들어서 기능 구현을 따로 분리하고, 실질적으로 정상 작동할 시에만

main에 병합(merge)하는 방식으로 버전관리를 하고 있다.

느낀점

프로젝트를 만들고 유지보수하는 과정이 너무 재밌다.

나만의 프로젝트를 만들고 프로젝트가 더 단단하고 견고해질 수 있도록 부품을 교체하고, 손질하고, 관리해주는 과정에서 재미를 느낀다.

마치 레고 성을 만들고 유지보수하는 느낌이랄까?


Java 언어를 사용해서 실제 사용될 수 있는 프로젝트를 내가 만들어나간다는게 가끔은 신기하게 느껴지기도 한다.

"내가 이런걸 만들 수 있다고?" 이런 생각을 종종하면서 스스로에게 감탄한다


서론

나의 목표는 깊이 있는 소프트웨어 개발자가 되는 것이다.

언어나, 프레임워크 등에 종속되지 않고 소프트웨어 개발을 깊이 있게 이해하고 대체할 수 없는

개발자가 되고 싶다.

끝으로

아직 키오스크 프로그램을 완성하지 않았다.

애초에 프로그램에 완성이란게 없다고 생각한다.

언제나 리팩토링할 것이 있고,

더 나아질 수 있는 개선의 여지가 있다고 생각한다.

기본 요구사항은 모두 구현하였고, 선택 요구사항을 구현하고 있다.

선택 요구사항을 구현하고, 시간적으로 여유가 있다면 리팩토링하는 시간을 가져보고 싶다.

profile
깊이 있는 소프트웨어 개발자가 되고 싶습니다.

0개의 댓글