ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 오늘 뭐 먹지?? ( 메뉴추천 프로그램 )
    심심해서 해본 코드(심심풀이용) 2020. 3. 19. 19:34

    *주의*

    이 글은 JAVA를 기반으로 작성된 코드입니다.

     

    오랜만에 블로그에 글을 쓰네요. 요즘엔 거의 서버 관련 공부를 하고 있어서 코딩 관련 글은 잘 안 쓰게 됐는데 오랜만에 글을 쓰게 되었습니다.

     

    *오늘은 JAVA와 MYSQL을 가지고 프로그램을 제작해봤습니다.(DB정보는 가렸습니다.)*

     

    프로그램 이름은! "오늘 뭐 먹지??" 이고, 이 프로그램에서 디자인적 요소는 들어가 있지 않고, 기본적인 틀로만 이루어져있습니다. 이 프로그램을 왜 만들었냐면 사실 구글링을 하니 메뉴를 추천해주는 프로그램을 짠 코드가 그렇게 많지가 않고, 뭔가를 해결해 줄 만한 코드는 하나도 없었어서 이렇게 간단하게라도 만들게 되었답니다~

     

    그럼 지금부터 코드 설명 들어가겠습니다.

     

    일단 전반적인 코드는 이렇습니다.

     

    index

     

     

     
    package random_choose;
    
    import com.jcraft.jsch.JSch;
    import com.jcraft.jsch.Session;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.Scanner;
    
    public class index {
        static Random random = new Random();
        static int random_data = 0;
        static Scanner menu = new Scanner(System.in);
        static String cate;
        static int lport;
        static String rhost;
        static int rport;
        static String changed;
        static ArrayList<UserBean> menu_list = new ArrayList<UserBean>();
        static String cate_name;
    
        public static void main_Frame(){
            JFrame f = new JFrame("오늘 뭐 먹지?");
            f.setSize(500,200);
            f.setLocationRelativeTo(null);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().setLayout(null);
    
            JButton korea = new JButton("한식");
            JButton china = new JButton("중식");
            JButton japen = new JButton("일식");
            JButton western = new JButton("양식");
    
            Container contentPane = f.getContentPane();
            contentPane.setBackground(Color.pink);
    
            contentPane.setLayout(new GridLayout(1,4));
    
            f.getContentPane().add(korea);
            f.getContentPane().add(china);
            f.getContentPane().add(japen);
            f.getContentPane().add(western);
    
            f.setVisible(true);
    
            korea.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("한식")){
                        cate = "한식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });
            china.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("중식")){
                        cate = "중식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });
            japen.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("일식")){
                        cate = "일식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });
            western.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("양식")){
                        cate = "양식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });
        }
    
        public static void sub_Frame(String cate){
            JFrame f2 = new JFrame("오늘의 " + cate + " 추천 메뉴는 ??");
            JPanel p2 = new JPanel();
            f2.setSize(500,200);
            f2.setLocationRelativeTo(null);
            f2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f2.getContentPane().setLayout(null);
    
            Container contentPane = f2.getContentPane();
            contentPane.setBackground(Color.pink);
    
            contentPane.setLayout(new BorderLayout());
    
            if(cate == "한식"){
                changed = "Korea";
                cate_name = "한식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }
            else if(cate == "중식"){
                changed = "China";
                cate_name = "중식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }
            else if(cate == "일식"){
                changed = "Japen";
                cate_name = "일식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }
            else if(cate == "양식"){
                changed = "Western";
                cate_name = "양식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }
    
            f2.add(p2);
            f2.setVisible(true);
    
        }
    
        public static void go() {
            String user = "서버계정";
            String password = "서버비밀번호";
            String host = "서버아이피";
            int port = ssh포트;
            try {
                JSch jsch = new JSch();
                Session session = jsch.getSession(user, host, port);
                lport = DB포트;
                rhost = "127.0.0.1";
                rport = DB포트;
                session.setPassword(password);
                session.setConfig("StrictHostKeyChecking", "no");
                session.connect();
                int assinged_port = session.setPortForwardingL(lport, rhost, rport);
            } catch (Exception e) {
            }
        }
    
        public static void select() {
            try {
                go();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            Connection con = null;
            String driver = "com.mysql.jdbc.Driver";
            String url = "jdbc:mysql://" + rhost + ":" + lport + "/";
            String db = "스키마 이름";
            String dbUser = "DB아이디";
            String dbPasswd = "DB비밀번호";
            try {
                Class.forName(driver);
                con = DriverManager.getConnection(url + db, dbUser, dbPasswd);
                try {
                    Statement st = con.createStatement();
                    ResultSet rs = null;
                    String sql = "select name from " + changed;
                    rs = st.executeQuery(sql);
    
                    while (rs.next()) {
                        UserBean bean = new UserBean();
                        bean.setname(rs.getString("name"));
                        menu_list.add(bean);
                    }
    
                    random_data = random.nextInt(menu_list.size());
    
                } catch (SQLException s) {
                    System.out.println("SQL statement is not executed!");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
        public static void main(String[] args) {
            main_Frame();
        }
    
    }

     

    UserBean

    package random_choose;
    
    public class UserBean {
        String name;
        public String getname(){
            return name;
        }
        public void setname(String name) {
            this.name = name;
        }
    }
    

     이렇게 두 개의 클래스로 되어있습니다. 일단 index는 DB를 connect 시키고, 이후 jframe을 사용하여 창을 띄웁니다.

    그리고 UserBean클래스를 통해 메뉴 이름을 가져오게 됩니다. 전체적으로는 mybatis는 사용을 하지 않았고, JDBC를 사용해서 DAO(UserBean)로 값을 불러오는 식으로 하였습니다.

     

     

     

    일단 index부터 천천히 설명하도록 하죠

     

    static Random random = new Random();
        static int random_data = 0;
        static Scanner menu = new Scanner(System.in);
        static String cate;
        static int lport;
        static String rhost;
        static int rport;
        static String changed;
        static ArrayList<UserBean> menu_list = new ArrayList<UserBean>();
        static String cate_name;

    일단 모든 변수들은 static처리를 하여 사용하였습니다. 이 변수들은 아래 상제 코드 설명 때 자세히 설명드리겠습니다.

     

    main_Frame

    JFrame f = new JFrame("오늘 뭐 먹지?");
            f.setSize(500,200);
            f.setLocationRelativeTo(null);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().setLayout(null);
    
            JButton korea = new JButton("한식");
            JButton china = new JButton("중식");
            JButton japen = new JButton("일식");
            JButton western = new JButton("양식");
    
            Container contentPane = f.getContentPane();
            contentPane.setBackground(Color.pink);
    
            contentPane.setLayout(new GridLayout(1,4));
    
            f.getContentPane().add(korea);
            f.getContentPane().add(china);
            f.getContentPane().add(japen);
            f.getContentPane().add(western);
    
            f.setVisible(true);
    
            korea.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("한식")){
                        cate = "한식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });
            china.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("중식")){
                        cate = "중식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });
            japen.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("일식")){
                        cate = "일식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });
            western.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("양식")){
                        cate = "양식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });

    일단 Frame은 Jframe을 사용하였고, 사이즈를 지정한 것은 대략 모양을 맞추기 위해 사이즈를 지정하였습니다.

     

    프레임은 종료가 되면 메모리가 초기화 도리 수 있도록

    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    을 사용하였고, 기타 layout은 container를 통해 contentPane이라는 name을 지정하여 설정하였습니다.

     

    이후 버튼으로 작동하는 프로그램을 만들었고, 그러기 위해서는 한식, 중식, 일식, 양식에 대한 버튼을 만들어 줬습니다.

    JButton korea = new JButton("한식");
            JButton china = new JButton("중식");
            JButton japen = new JButton("일식");
            JButton western = new JButton("양식");

    그리고 이 버튼들을 layout틀에 맞춰서 넣어주기 위해 contentPane에 추가를 해주었고,

    f.getContentPane().add(korea);
            f.getContentPane().add(china);
            f.getContentPane().add(japen);
            f.getContentPane().add(western);

    layout은 GridLayout을 사용하였고, 크기는 rows:1, cols:4로 지정하였습니다.

     

    그리고 이것들을 넣어줬으니 main_Frame에 추가해 줬으니 화면을 띄울 수 있게 하였습니다.

    f.setVisible(true);

     

    기능은 동일한 방식으로 작동되어서 한식을 기준으로 설명하겠습니다.

     

    korea(Button Action)

    korea.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JButton btn = (JButton) e.getSource();
                    if(btn.getText().equals("한식")){
                        cate = "한식";
                        sub_Frame(cate);
                        f.dispose();
                    }
                }
            });

    버튼에 대한 값을 Action Listener로 받아와서 검증하는 부분입니다.

    검증은 버튼에 대한 text를 인식하는 것으로 하였고, 버튼의 값이 한식일 경우에 cate(카테고리) 값을 한식이라고 지정을 해주고, subframe을 띄운 후 이 창은 닫히도록 하였습니다.

     

     

    sub_Frame

     

    JFrame f2 = new JFrame("오늘의 " + cate + " 추천 메뉴는 ??");
            JPanel p2 = new JPanel();
            f2.setSize(500,200);
            f2.setLocationRelativeTo(null);
            f2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f2.getContentPane().setLayout(null);
    
            Container contentPane = f2.getContentPane();
            contentPane.setBackground(Color.pink);
    
            contentPane.setLayout(new BorderLayout());
    
            if(cate == "한식"){
                changed = "Korea";
                cate_name = "한식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }
            else if(cate == "중식"){
                changed = "China";
                cate_name = "중식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }
            else if(cate == "일식"){
                changed = "Japen";
                cate_name = "일식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }
            else if(cate == "양식"){
                changed = "Western";
                cate_name = "양식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }
    
            f2.add(p2);
            f2.setVisible(true);

    sub_Frame은 main_Frame과 화면 구현 형식은 비슷하지만 버튼은 사용되지 않았고, JLabel을 사용하여 DB에서 랜덤으로 값을 받아 온 것을 출력해주는 식으로 하였습니다.

     

    이것도 기능에 대한 것은 한식을 시준으로 하겠습니다.

     

    korea

    if(cate == "한식"){
                changed = "Korea";
                cate_name = "한식";
                select();
                JLabel label = new JLabel(menu_list.get(random_data).getname()+" 입니다!");
                p2.add(label);
            }

    일단 한식이 cate인지 double check를 하고, 이 것이 맞다면 changed라는 DB table 이름을 넣어주는 변수에 지정해줍니다.

    그 이후 카테고리 이름은 한식으로 지정해주고 DB를 호출해주는 select 메서드를 호출합니다. 그리고 JLabel을 사용하여 DB에서 호출한 정보를 랜덤 돌려서 하나를 출력해주고 JLabel을 p2라는 Jpanel에 추가하여 frame에 보이도록해줍니다.

     

    go(DB 정보를 저장하는 메서드)

    String user = "서버계정";
            String password = "서버비밀번호";
            String host = "서버아이피";
            int port = 서버포트;
            try {
                JSch jsch = new JSch();
                Session session = jsch.getSession(user, host, port);
                lport = DB포트;
                rhost = "127.0.0.1";
                rport = DB포트;
                session.setPassword(password);
                session.setConfig("StrictHostKeyChecking", "no");
                session.connect();
                int assinged_port = session.setPortForwardingL(lport, rhost, rport);
            } catch (Exception e) {
            }

    go메서드는 DB에 대한 정보를 저장하는 메서드로써 모든 DB에 대한 정보가 조합되는 곳입니다. 

    그리고 ssh를 연결하는 부분이기도 하죠. 왜 DB를 연결하는데 ssh를 연결하냐면, 이 DB connect 방식은 tcp/ip over ssh 방식입니다.

    말 그래로 ssh를 통해 DB를 연결시키는 방법입니다. 

    이렇게 하는 이유는 DB가 centos서버에 있고, 서버에 접속한 후에 DB에 접속해야 하기 때문에 over ssh방식을 선택하였습니다. 

    그리고 over ssh는 jsch라고 적혀있는 jcraft라는 util을 사용하여야 합니다. 

    그래서 jsch를 통해. session에 접속하는 코드입니다.

     

    select

    try {
                go();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            Connection con = null;
            String driver = "com.mysql.jdbc.Driver";
            String url = "jdbc:mysql://" + rhost + ":" + lport + "/";
            String db = "DB이름";
            String dbUser = "DB사용자계정";
            String dbPasswd = "DB사용자 비밀번호";
            try {
                Class.forName(driver);
                con = DriverManager.getConnection(url + db, dbUser, dbPasswd);
                try {
                    Statement st = con.createStatement();
                    ResultSet rs = null;
                    String sql = "select name from " + changed;
                    rs = st.executeQuery(sql);
    
                    while (rs.next()) {
                        UserBean bean = new UserBean();
                        bean.setname(rs.getString("name"));
                        menu_list.add(bean);
                    }
    
                    random_data = random.nextInt(menu_list.size());
    
                } catch (SQLException s) {
                    System.out.println("SQL statement is not executed!");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

    마지막으로 설명드릴 코드는 select입니다. 

    이 코드는 go에서 정보를 받아와서 DB에 connect를 시켜주는 메서드입니다.

     

    try catch finally를 사용하였고, 이것으로 go메서드를 불러와서 검증을 합니다.

    이후 catch로 exception을 처리하고, JDBC에 mysql driver를 사용하여 mysql DB에 연결을 합니다. 

     

    그리고 DB에 대한 정보를 아래에 있는 try에서 con이라는 변수로 재 조합하여 연결은 시키는 또 다른 try로 연결에 대한 검증을 합니다.

    이 과정에서 statement를 하용하여 연결을 시도하고, sql문을 위에서 검증을 거쳐 지정된 changed와 조합하여 작성이 됩니다.

     

    그리고 resultset에 저장되게 되고 이것을 statement를 통해 쿼리를 입력하여 값을 받아오게 됩니다. 이과정에서 bean을 사용하게 되는 것이고, bean에서 메뉴 이름에 대한 값만 불러오게 설정을 하고 menu_list라는 것에 bean에서 불러온 값을 넣고 이후 random_data에 bean에서 불러온 값의 대한 size를 넣어줍니다. 이렇게 되면 random을 돌릴 때 전체 값을 넣어줄 수 있게 됩니다.

     

    UserBean

    String name;
        public String getname(){
            return name;
        }
        public void setname(String name) {
            this.name = name;
        }

     bean파일은 어려운 것은 없습니다 DAO를 사용하기 위해 sql에서 name 값만 불러오겠다는 것을 설정해주는 것입니다.

     

    index(main)

    public static void main(String[] args) {
            main_Frame();
        }

    드디어 마지막이네요. 실행 부분은 간단합니다. 그냥 모든 것이 연결되어있는 main_Frame을 호출해주면 끝입니다.

     

    실행 화면

     

     

    이 코드를 짤 수 있는 방법은 여러 가지 방법이 있습니다. 제 방법 중 잘못되어있는 것이 있다면 댓글을 남겨주시면 감사하겠습니다. 

     

    댓글

Designed by Tistory.