C# 포트폴리오 도전기(1-5. 사용자 페이지 구현)

min seung moon·2021년 8월 20일
0

C# 포트폴리오

목록 보기
6/10

1. 사용자 페이지 구현

  • 사용자는 테이블하고 입력이 되어있으니 가장 빠르게 준비하면 좋을 것 같다!
  • 구현을 하면서 테이블과 프로시저 하고 몇몇 기본 코드가 수정이 되었다
  • 솔직히 다 구현하고 나서 작성할려니 뭐가 바뀌었는지 모르겠네ㅎㅎ

01. Main.cs

  • 메인 폼에서 다른 폼을 어떻게 보여줄지랑 각 아이템마다 Form으로 불러올지 고민을 하고 Form과 Dialog로 나눠서 불러오기로 했다

-1. XTR Form

  • 기존 기본 Form에서 Main.cs는 XTR Form으로 변경을 해주었다
    • 기능적으로 MDI 페이지 처리하기도 좋아서 결정했다
    • 사실 회사에서 이렇게 사용하는걸 보고 이게 좋을것 같아서 따라하기로 했다
  • 어제 적용했는지 모르겠지만 Form에 MDI 활성화를 해주어야 한다
  • XtraTabbedMdiManager
    • MDI 자식 양식을 탭으로 표시하고 기본 양식 관리 기능을 제공하는 구성 요소로 고급 탭 UI를 만들려면 DocumentManager 구성 요소를 대신 사용
    • 말하자면 MDI Child Form을 멋지게 구현할 수 있게 도와주는 클래스이다
  • Main_Load
    • 메인 폼이 로드되었을 때 아무것도 안보이게 하는건 좀 그렇기에 첫 화면에 홈 화면이 보이도록 하기 위한 작업입니다
  • ChildFormAdd
    • ChildFormAdd는 로드페이지에 있는데 초기화할 때 넣어주셔도 됩니다, XtraTabbedMdiManager를 초기화하고 설정하는 메서드라고 보이면 됩니다
    • MdiManager_ChildFormAdd 마찬가지 입니다
  • Home
    • 이 메서드는 첫 메인 화면을 불러오는 메서드인데요! MenuRun 메서드에 넣어도 될것 같기도 하고 일단 매개변수 없이 실행하도록 만든거라 만약 별로다 싶으면 MenuRun메서드에 병합할 예정입니다
  • MenuRun
    • 이 메서드는 MDI Child를 생성할 메뉴 아이템을 누르면 메뉴를 확인하고 MDI Child 페이지 인스턴스를 생성해주고 보여줍니다, 만약에 중복되어 있으면 닫고 새롭게 열구요, 솔직히 그냥 리턴할까도 생각했는데 아직 제 실력으로는 비동기를 어떻게 구현하면 좋을까 로직이 안떠올라서 닫고 새로 만들게 했습니다
  • 그리고 사용자의 조회말고는 다이얼로그로 불러오게 작성했습니다
using BookManagementProgram.XtraForm;
using BookManagementProgram.Model;
using  BookManagementProgram.Repository;
using System;
using System.Windows.Forms;
using DevExpress.XtraTabbedMdi;
using System.Reflection;
using BookManagementProgram.UserControls;

namespace BookManagementProgram
{
    public partial class Main : DevExpress.XtraEditors.XtraForm
    {
        User user = BookUserRepository.user;
        XtraTabbedMdiManager mdiManager;

        public Main()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;

            switch(user.authorityNo)
            {
                case 0:
                    user_page.Visible = true;
                    book_page.Visible = true;
                    rental_page.Visible = true;
                    break;
                case 1:
                    book_page.Visible = true;
                    rental_page.Visible = true;
                    break;
                case 2:
                    rental_page.Visible = true;
                    break;
            }
        }

        // 폼 종료
        private void Main_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }

        // 폼 종료 버튼
        private void home_close_btn_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            Application.Exit();
        }

        // 비밀번호 변경 버튼
        private void home_changePassword_btn_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            (new FindByPassword()).ShowDialog();
        }

        // 메인 폼 로드
        private void Main_Load(object sender, EventArgs e)
        {
            ChildFormAdd();

            Home();
        }

        // MID Child Form추가
        private void ChildFormAdd()
        {
            mdiManager = new XtraTabbedMdiManager();
            mdiManager.MdiParent = this;
            mdiManager.HeaderButtons = DevExpress.XtraTab.TabButtons.Close;
            mdiManager.HeaderLocation = DevExpress.XtraTab.TabHeaderLocation.Top;
            mdiManager.PageAdded += MdiManager_ChildFormAdd;
            mdiManager.ClosePageButtonShowMode = DevExpress.XtraTab.ClosePageButtonShowMode.InActiveTabPageAndTabControlHeader;
        }

        // MDI 설정
        private void MdiManager_ChildFormAdd(object sender, MdiTabPageEventArgs e)
        {
            XtraMdiTabPage page = e.Page;
        }

        // 첫 로드할때 보여줄 메인 페이지
        private void Home()
        {

            foreach (Form item in this.MdiChildren)
            {
                if (item.Name == "HOME")  //Notice
                {
                    item.Focus();
                    return;
                }
            }

            Assembly asm = Assembly.GetExecutingAssembly();

            Form frm = (Form)asm.CreateInstance(string.Format("{0}.{1}", "BookManagementProgram.MainControls", "MainPageForm"));

            if (frm != null)
            {
                frm.Text = "메인화면";
                frm.MdiParent = this;
                frm.Dock = DockStyle.Fill;
                frm.Show();

            }
        }

        // 유저 페이지 유저 조회 버튼
        private void user_reset_btn_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            MenuRun("UserSelectForm", user_reset_btn.Hint);
        }

        // 메뉴 아이템에 따라 MID Child 생성
        private void MenuRun(string Menu, string FormTitle)
        {
            string nameSpace;

            foreach (Form item in this.MdiChildren)
            {
                if (Menu == item.Name)
                {
                    item.Close();
                }
            }
            Form frm = null;
            if (Menu.Equals("UserSelectForm"))
            {
                nameSpace = "BookManagementProgram.UserControls";
                System.Reflection.Assembly assembly = System.Reflection.Assembly.Load("BookManagementProgram");
                string FileName = "UserSelectForm";
                frm = (Form)assembly.CreateInstance(string.Format("{0}.{1}", nameSpace, FileName));
            }

            if (frm != null)
            {
                frm.Text = FormTitle;
                frm.MdiParent = this;
                frm.Show();
            }
            else
            {
                MessageBox.Show("개발중이거나 존재하지 않는 화면입니다.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        // 유저 페이지 유저 등록 버튼
        private void user_add_btn_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            (new UserAddForm()).ShowDialog();
        }

        // 유저 페이지 유저 검색 버튼
        private void user_search_btn_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            (new UserSearchForm()).ShowDialog();
        }
    }
}









02. UserControls / UserSelectForm.cs

-1. Controls

  • GridControl
    • 명명도 안해놓고 그냥 Dock Style만 Fill로 해줬습니다
    • 사이즈는 메인폼 MDI 사이즈에 맞춰주었구요
    • 컬럼입력과 데이터는 Repository에서 받아서 처리할 예정입니다

-2. UserSelectForm.cs

  • 단순 조회 페이지이기 때문에 폼 자체 코드는 어려울게 없습니다
  • GridControl의 GridView만 수정 못하도록 초기화 해준거구요!
using BookManagementProgram.Repository;
using DevExpress.XtraGrid.Views.Grid;
using System.Windows.Forms;

namespace BookManagementProgram.UserControls
{
    public partial class UserSelectForm : Form
    {
        BookUserRepository userRepository = null;

        public UserSelectForm()
        {
            InitializeComponent();
            userRepository = new BookUserRepository();

            InitGridControl();
            this.gridControl1.DataSource = userRepository.GetAllUsers();
        }

        private void InitGridControl()
        {
            GridView gv = this.gridControl1.MainView as GridView;
            gv.OptionsView.ShowGroupPanel = false;
            gv.OptionsBehavior.Editable = false;
        }
    }
}

-3. Repository / IBookRepository.cs

  • 처음보는 추상 메서드가 많으실거에요!
  • 저번까지는 구현하고 작성하고 했다면 오늘은 구현하는데 머리 터질것 같아서 구현에만 신경을 쓰느라 사용자 페이지의 전체 추상 메서드 입니다!
using BookManagementProgram.Model;
using System.Collections.Generic;
using System.Data;

namespace BookManagementProgram.Repository
{
    interface IBookUserRepository
    {
        string Login(string userId, string userPw);

        string FindById(string userNo, string userName);

        bool FindByPassword(string userNo, string userId, string newPassword);

        bool InsertLoginLog();

        DataTable GetAllUsers();

        Dictionary<string, object> GetAuthList();
        Dictionary<string, object> GetGradeList();

        bool AddUser(User user);

        User GetUserByNumber(string userNo);

        bool DeleteUserByNumber(string userNo);

        bool UpdateUserInfo(User user);
    }
}

-4. Repository / BookRepository.cs

  • 전체 메서드라서 밑에서 부터는 사진으로 메서드 설명만 할게요!
  • GetAllUsers
    • 전체 사용자의 정보를 갖고오는 메서드 입니다
    • 크게 어려우실거는 없다고 봐요!
    • 이번에 재미있었던건 조회해온 데이터를 바로 DataTable로 Load할 수 있다는것에 충격
    • 앞으로 데이터를 데이터 테이블에 넣을 때는 미리 DataTable로 변환해서 던져주는게 좋을것 같다라고 생각이 들었습니다
      • 솔직히 Windows Form개발하면 데이터는 대부분 DataTable로 보여주니 그렇게 많이 사용할것 같네요!
using BookManagementProgram.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;

namespace BookManagementProgram.Repository
{
    class BookUserRepository : IBookUserRepository
    {
        private SqlConnection conn = null;
        private SqlCommand cmd = null;
        public static List<User> userList = null;
        public static User user = null;

        public BookUserRepository()
        {
            conn = DBConn.DBConn.getConn();
            cmd = new SqlCommand();
            cmd.Connection = conn;
        }

        // 로그인 로직
        public string Login(string userId, string userPw)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_S1 @USER_ID = '{userId}', @USER_PW = '{Encryption(userPw)}';";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while (SR.Read())
                    {
                        user = new User(
                            SR[0].ToString()
                            , SR[1].ToString()
                            , SR[2].ToString()
                            , SR[3].ToString()
                            , SR[4].ToString()
                            , SR[5].ToString()
                            , SR[6].ToString()
                            , (int)SR[7]
                            , (int)SR[8]
                            );
                    }
                    SR.Close();
                }

                return user.userNo;
            }
            catch(SqlException e)
            {
                return e.Message;
            }
            finally
            {
                conn.Close();
            }
        }

        // 아이디 찾기 로직
        public string FindById(string userNo, string userName)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_S2 @USER_NO = {userNo}, @USER_NAME = '{userName}';";
                string user_id = string.Empty;

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while (SR.Read())
                    {
                        user_id = SR[0].ToString();
                    }
                    SR.Close();
                }

                return $"아이디 : {user_id} 입니다.";
            }
            catch (SqlException e)
            {
                return e.Message;
            }
            finally
            {
                conn.Close();
            }
        }

        // 비밀번호 찾기 로직
        public bool FindByPassword(string userNo, string userId, string newPassword)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_U1 @USER_NO = {userNo}, @USER_ID = '{userId}', @NEW_PW = '{Encryption(newPassword)}';";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }
        }

        // 로그 입력
        public bool InsertLoginLog()
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_I1 @USER_NO = {user.userNo}, @USER_ID = '{user.userId}', @ENTER_IP = '{GetExternalIPAddress()}';";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }
        }

        // 사용자 전체 리스트
        public DataTable GetAllUsers()
        {
            DataTable dt = new DataTable();
            try
            {
                string sql = "EXEC BOOK_LOGIN_S3;";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    dt.Load(SR);
                }
                return dt;
            }
            catch (SqlException e)
            {
                return dt;
            }
            finally
            {
                conn.Close();
            }
        }

        // 권한 리스트
        public Dictionary<string, object> GetAuthList()
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            try
            {
                string sql = "EXEC BOOK_LOGIN_S4;";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while(SR.Read())
                    {
                        dic.Add(SR[1].ToString(), (int)SR[0]);
                    }
                }
                return dic;
            }
            catch (SqlException e)
            {
                return dic;
            }
            finally
            {
                conn.Close();
            }
        }

        // 등급 리스트
        public Dictionary<string, object> GetGradeList()
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            try
            {
                string sql = "EXEC BOOK_LOGIN_S5;";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while (SR.Read())
                    {
                        dic.Add(SR[1].ToString(), (int)SR[0]);
                    }
                }
                return dic;
            }
            catch (SqlException e)
            {
                return dic;
            }
            finally
            {
                conn.Close();
            }
        }

        // 사용자 등록
        public bool AddUser(User user)
        {
            try
            {
                string pw = Encryption(user.userPw);
                string sql = $"EXEC BOOK_LOGIN_I2 @USER_NAME = '{user.userName}', @USER_ADDR = '{user.userAddress}', @USER_BIRTH='{user.userBirth}', @USER_ID='{user.userId}', @USER_PW='{pw}', @USER_AUTH={user.authorityNo}, @USER_GRADE={user.gradeNo};";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }

        }

        // 유저 조회
        public User GetUserByNumber(string userNo)
        {
            User user = new User();
            try
            {
                string sql = $"EXEC BOOK_LOGIN_S6 @USER_NO = {userNo};";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    SR.Read();
                    user.userNo = SR[0].ToString();
                    user.userName = SR[1].ToString();
                    user.userAddress = SR[2].ToString();
                    user.userBirth = SR[3].ToString();
                    user.userId = SR[4].ToString();
                    user.userPw = SR[5].ToString();
                    user.registerDate = SR[6].ToString();
                    user.deregisterDate = SR[7].ToString();
                    user.authorityNo = (int)SR[8];
                    user.gradeNo = (int)SR[9];
                }
                return user;
            }
            catch (SqlException e)
            {
                return user;
            }
            finally
            {
                conn.Close();
            }
        }

        // 사용자 삭제
        public bool DeleteUserByNumber(string userNo)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_D1 @USER_NO = {userNo};";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }
        }

        // 사용자 정보 수정
        public bool UpdateUserInfo(User user)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_U2 @USER_NO = {user.userNo}, @USER_NAME = '{user.userName}', @USER_ADDR = '{user.userAddress}', @USER_BIRTH = '{user.userBirth}', @USER_ID = '{user.userId}', @AUTH_NO = {user.authorityNo}, @GRADE_NO = {user.gradeNo};";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }
        }

        // SHA256 암호화 메서드
        public static string Encryption(string data)
        {
            SHA256 sha = new SHA256Managed();
            byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(data));
            StringBuilder stringBuilder = new StringBuilder();
            foreach (byte b in hash)
            {
                stringBuilder.AppendFormat("{0:x2}", b);
            }
            return stringBuilder.ToString();
        }

        // 외부 IP
        public static string GetExternalIPAddress()
        {
            string externalip = new WebClient().DownloadString("http://ipinfo.io/ip").Trim();

            return externalip ?? GetInternalIPAddress();//null경우 내부 IP 반환;
        }

        // 내부
        // DNS, 단순 도메인 이름 확인 기능이 제공
        // GetGostEntity, 호스트 이름 또는 IP 주소를 IPHostEntry 인스턴스로 확인
        // GetHostName, 로컬 컴퓨터의 호스트 이름을 가져온다
        public static string GetInternalIPAddress()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());

            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }

            throw new Exception("인터넷 연결 없음");
        }
    }
}

-5. DB / Procedure / EXEC BOOK_LOGIN_S3

  • 사용자 정보를 불러오는 쿼리이다 보니 굳이 조건을 주거나 할 필요가 없어서 안넣었구요
  • 단순 쿼리만 무식하게 있죠!
USE [BookManagement]
GO
/****** Object:  StoredProcedure [dbo].[BOOK_LOGIN_S3]    Script Date: 2021-08-20 오후 7:10:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.08.20>
-- Description:	<도서관리프로그램, 전체 사용자 조회>
-- =============================================
ALTER PROCEDURE [dbo].[BOOK_LOGIN_S3]
AS
BEGIN
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
	
	SELECT	l.user_no as '사용자번호', i.user_name as '사용자이름', i.user_address as '사용자주소', CONVERT(char(10), i.user_birth, 102) as '생년월일'
		, l.user_id as '아이디', l.user_pw as '비밀번호' , l.register_date as '가입일', l.deregister_date as '탈퇴일'
		, a.authority_name  as '권한', g.grade_name as '등급'
	FROM			Book_User_LogIn	as l
	INNER JOIN		Book_User_Info	as i
	ON				l.user_no = i.user_no
	INNER JOIN		Book_User_Auth	as a
	ON				l.authority_no = a.authority_no
	INNER JOIN		Book_User_Grade	as g
	ON				l.grade_no = g.grade_no
	ORDER BY		l.user_no;
END

-5. Model / User.cs

  • 깜빡할 뻔 했네요!
  • 전체 조회를 하면서 탈퇴일하고 권한 등급을 이름으로 받아오기 위해서 변수를 추가하고 생성자도 하나 추가했습니다
    • 권한 이름, 등급 이름, 탈퇴일을 받아올 변수를 추가했습니다
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BookManagementProgram.Model
{
    class User
    {
        private string user_no;
        private string user_name;
        private string user_address;
        private string user_birth;
        private string user_id;
        private string user_pw;
        private string register_date;
        private string deregister_date;
        private int authority_no;
        private string authority_name;
        private int grade_no;
        private string grade_name;

        public string userNo { get { return user_no; } set { user_no = value; } }
        public string userName { get { return user_name; } set { user_name = value; } }
        public string userAddress { get { return user_address; } set { user_address = value; } }
        public string userBirth { get { return user_birth; } set { user_birth = value; } }
        public string userId { get { return user_id; } set { user_id = value; } }
        public string userPw { get { return user_pw; } set { user_pw = value; } }
        public string registerDate { get { return register_date; } set { register_date = value; } }
        public string deregisterDate { get { return deregister_date; } set { deregister_date = value; } }
        public int authorityNo { get { return authority_no; } set { authority_no = value; } }
        public string authorityName { get { return authority_name; } set { authority_name = value; } }
        public int gradeNo { get { return grade_no; } set { grade_no = value; } }
        public string gradeName { get { return grade_name; } set { grade_name = value; } }

        // 로그인 시 사용되는 생성자
        public User(string user_no, string user_name, string user_address, string user_birth, string user_id, string user_pw, string register_date, int authority_no, int grade_no)
        {
            this.user_no = user_no;
            this.user_name = user_name;
            this.user_address = user_address;
            this.user_birth = user_birth;
            this.user_id = user_id;
            this.user_pw = user_pw;
            this.register_date = register_date;
            this.authority_no = authority_no;
            this.grade_no = grade_no;
        }

        // 전체 사용자 조회때 사용되는 생성자
        public User(string user_no, string user_name, string user_address, string user_birth, string user_id, string user_pw, string register_date, string deregister_date, string authority_name, string grade_name)
        {
            this.user_no = user_no;
            this.user_name = user_name;
            this.user_address = user_address;
            this.user_birth = user_birth;
            this.user_id = user_id;
            this.user_pw = user_pw;
            this.register_date = register_date;
            this.deregister_date = deregister_date;
            this.authority_name = authority_name;
            this.grade_name = grade_name;
        }

        public User()
        {
        }
    }
}



03. UserControls / UserAddForm.cs

-1. Controls

  • 유저 등록 폼입니다
    • 솔직히 라벨마다 focusing 할려다가 너무 많고 귀찮아서 pass 했습니다. 죄송합니다!
  • UI로 보면 확인하기 어렵지만 회원등록 버튼은 현재 Enable = false인 상태 입니다
    • 인증번호 확인하고 활성화 시킬 예정입니다!
  • Label
    • 딱히 이름 지정 안해줘서 Pass
    • 아! timer Label은 timer_lbl
  • TextBox(가능하면 maxlength 걸어주세요)
    • user_name_txt
    • user_address_txt
    • user_birth_txt
    • user_id_txt
    • user_password_txt
    • user_phone_txt
    • auth_number_txt
  • ComboBox
    • user_auth_cmb
    • user_grade_cmb
  • Button
    • auth_btn
    • auth_check_btn
    • add_user_btn
    • cancel_btn
  • Timer

-2. Code

  • 신입에게 큰것을 바라지는 말아주세요~!
  • UserAddForm 생성자
    • 여기서 권한 콤보박스와 등급 콤보 막스를 초기화 해준다고 보시면 됩니다
  • auth_btn_Click
    • 권한 전송 버튼을 누를시 텍스트박스에 값이 들어있는지 확인 후 입력한 전화번호로 Twilo를 이용해서 인증번호 발송합니다!
    • Twilo 사용할 때 Nuget Package 다운받아주세요
  • auth_check_btn_Click
    • 인증번호 확인해서 확인되면 초기화해줄거 초기화 해주고 등록하고 창닫고
    • 아니면 잘못되었다고 하고 인증번호 텍스트박스에 포커싱
  • add_user_btn_Click
    • 이제 정보 보내서 잘 되면 등록 안되면 실패
  • CreateUserInstance
    • 이건 add_user_btn_Click에서 처리해도 되는데 너무 복잡해서 빼둔거라고 보시면 됩니다
    • 사용자 객체 생성하는 메서드죠
  • CheckInput
    • 텍스트박스를 전체적으로 검사해주구요!
    • if문에서 바로 return 해줘도 되구요! 저도 평소에 그렇게 하다가 이번에는 else if기 때문에 처리 끝나고 return 해주는걸로 했어요
  • CheckBirthPattern * CheckPhonePattern
    • 여러분 구글링하시면 되요!
    • 생년월일 8자리와 휴대폰번호 확인입니다!
  • TwiloRun & SpendSMSTwilo
    • 실제로 SMS 보내는 메서드죠!
    • 어려우실건 없을거에요!
    • 규칙이기 때문에 트와일로에서 발급받은 SID, Token, phonenumber만 입력해주시면 됩니다
      • HOST가 PHONE Number 입니다
  • 나머지는 계속 봐왔기 때문에 Pass
using BookManagementProgram.Model;
using BookManagementProgram.Repository;
using System;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using Twilio;
using Twilio.Rest.Api.V2010.Account;

namespace BookManagementProgram.UserControls
{
    public partial class UserAddForm : Form
    {
        BookUserRepository userRepository = null;
        private int _duration = 0;  // 타이머 라벨에 표시할 숫자 변수
        private string _auth_code = "";  // 인증번호

        public UserAddForm()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterParent;
            userRepository = new BookUserRepository();

            // 권한 콤보 박스 초기화
            user_auth_cmb.DataSource = new BindingSource(userRepository.GetAuthList(), null);
            user_auth_cmb.DisplayMember = "Key";
            user_auth_cmb.ValueMember = "Value";

            // 등급 콤보박스 초기화
            user_grade_cmb.DataSource = new BindingSource(userRepository.GetGradeList(), null);
            user_grade_cmb.DisplayMember = "Key";
            user_grade_cmb.ValueMember = "Value";
        }

        // 취소버튼
        private void cancel_btn_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        // 인증번호 전송 버튼
        private void auth_btn_Click(object sender, EventArgs e)
        {
            if (CheckInput())
            {
                TwiloRun();
            }
        }

        // 인증번호 확인
        private void auth_check_btn_Click(object sender, EventArgs e)
        {
            if(auth_number_txt.Text == _auth_code)
            {
                ResetTimerAndCode();
                MessageBox.Show("인증에 성공하였습니다.");
                add_user_btn.Enabled = true;
                return;
            }
            MessageBox.Show("다시 확인해주세요.");
            auth_number_txt.Focus();
        }

        // 사용자 등록
        private void add_user_btn_Click(object sender, EventArgs e)
        {
            if(userRepository.AddUser(CreateUserInstance()))
            {
                MessageBox.Show("사용자 등록에 성공하였습니다.");
                this.Close();
                return;
            }
            MessageBox.Show("사용자 등록에 실패했습니다.");
        }

        private User CreateUserInstance()
        {
            User user = new User();
            user.userName = user_name_txt.Text;
            user.userAddress = user_address_txt.Text;
            user.userBirth = user_birth_txt.Text;
            user.userId = user_id_txt.Text;
            user.userPw = user_password_txt.Text;
            user.authorityNo = (int)user_auth_cmb.SelectedValue;
            user.gradeNo = (int)user_grade_cmb.SelectedValue;
            return user;
        }

        // 텍스트박스 입력 확인
        private bool CheckInput()
        {
            bool check = false;

            if (string.IsNullOrEmpty(user_name_txt.Text))
            {
                MessageBox.Show("성함을 입력해주세요.");
                user_name_txt.Focus();
            }
            else if (string.IsNullOrEmpty(user_address_txt.Text))
            {
                MessageBox.Show("주소를 입력해주세요.");
                user_address_txt.Focus();
            }
            else if (string.IsNullOrEmpty(user_birth_txt.Text) || CheckBirthPattern(user_birth_txt.Text))
            {
                MessageBox.Show("생년월일을 입력해주세요.(2021.01.01)");
                user_birth_txt.Focus();
            }
            else if (string.IsNullOrEmpty(user_id_txt.Text))
            {
                MessageBox.Show("아아디를 입력해주세요.");
                user_id_txt.Focus();
            }
            else if (string.IsNullOrEmpty(user_password_txt.Text))
            {
                MessageBox.Show("비밀번호를 입력해주세요.");
                user_password_txt.Focus();
            }
            else if (string.IsNullOrEmpty(user_phone_txt.Text) || CheckPhonePattern(user_phone_txt.Text))
            {
                MessageBox.Show("휴대폰번호를 입력해주세요.(01012341234)");
                user_address_txt.Focus();
            }
            else
            {
                check = true;
            }

            return check;
        }
        

        // 생년월일 확인 정규식
        private bool CheckBirthPattern(string birth)
        {
            string pattern = @"^(19[0-9][0-9]|20\d{2})\.(0[0-9]|1[0-2])\.(0[1-9]|[1-2][0-9]|3[0-1])$";
            if (!Regex.IsMatch(birth, pattern))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        // 휴대폰번호 정규식
        private bool CheckPhonePattern(string phone)
        {
            string pattern = @"^\d{3}\d{3,4}\d{4}$";
            if (!Regex.IsMatch(phone, pattern))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        // Twiolog
        private async void TwiloRun()
        {
            string phone = user_phone_txt.Text;
            // 타이머 초기화 및 인증번호 생성
            _duration = 60;
            _auth_code = GetRandomCode();
            timer1.Stop();
            timer1 = new Timer();
            timer1.Tick += new EventHandler(CountDown);
            timer1.Interval = 1000;
            timer1.Start();

            await Task.Run(() => SpendSMSTwilo(phone));
        }

        private void SpendSMSTwilo(string phone)
        {
            // twilo
            try
            {
                string accountSid = Properties.Settings.Default.TwiloSID;
                string authToken = Properties.Settings.Default.TwiloToken;

                TwilioClient.Init(accountSid, authToken);

                var message = MessageResource.Create(
                    body: $"인증번호 : {_auth_code}",
                    from: new Twilio.Types.PhoneNumber(Properties.Settings.Default.TwiloHost),
                    to: new Twilio.Types.PhoneNumber($"+82{phone}")
                );
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        // 타이머 카운트 다운
        private void CountDown(object sender, EventArgs e)
        {
            if (_duration == 0 || _duration < 0)
            {
                ResetTimerAndCode();
                MessageBox.Show("인증 시간이 초과되었습니다.");
                return;
            }
            _duration--;
            timer_lbl.Text = _duration.ToString();
        }

        // 랜덤 코드 생성
        private string GetRandomCode()
        {
            Random rand = new Random();
            string input = "abcdefghijklmnopqrstuvxyz0123456789";

            var chars = Enumerable.Range(0, 6).Select(x => input[rand.Next(0, input.Length)]);

            return new string(chars.ToArray());
        }

        // 타이머 및 코드 초기화
        private void ResetTimerAndCode()
        {
            timer1.Stop();
            timer1.Dispose();
            _auth_code = "";
        }
    }
}






-3. Repository / BookUserRepository.cs

  • 코드는 위에 있으니 사진으로 설명할게요!
  • GetAuthList
    • 이 메서드에서 고민이 된 점은 객체를 만들어서 객체로 받아올까도 싶었지만 굳이?라는 생각이 들어서 선택한 것이 Dictionary 입니다
    • 사용하기 어렵지도 않아서 굿 초이스였구요
    • 뭐 갖고 오는 형식이 Key : Value 형식으로 사용할거라서 알 맞았던것 같아요!
  • GetGradeList
    • GetAuthList와 동일하다고 보시면 됩니다
  • AddUser
    • 옆으로 길~~~죠 아무래도 등록이다 보니 많은 데이터가 넘어갑니다ㅎㅎ
    • DB에 넘겨주기 전에 어제 입력한 암호화 메서드 활용해야 겠죠!


-4. DB / Procedure / BOOK_LOGIN_S4

  • 권한 갖고 오는 프로시저
    • 사용자 전체 수정 빼고는 조건 넣는 경우는 없을것 같아요!
USE [BookManagement]
GO
/****** Object:  StoredProcedure [dbo].[BOOK_LOGIN_S4]    Script Date: 2021-08-20 오후 6:57:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.08.20>
-- Description:	<도서관리프로그램, 권한 조회>
-- =============================================
ALTER PROCEDURE [dbo].[BOOK_LOGIN_S4]
AS
BEGIN
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
	
	SELECT * FROM Book_User_Auth;
END

-5. DB / Procedure / BOOK_LOGIN_S5

  • 등급 조회 프로시저
USE [BookManagement]
GO
/****** Object:  StoredProcedure [dbo].[BOOK_LOGIN_S5]    Script Date: 2021-08-20 오후 6:58:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.08-20>
-- Description:	<도서관리프로그램, 등급 조회>
-- =============================================
ALTER PROCEDURE [dbo].[BOOK_LOGIN_S5]
AS
BEGIN
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
	
	SELECT * FROM Book_User_Grade;
END

-6. DB / Procedure / BOOK_LOGIN_S5

  • 사용자 등록 프로시저
USE [BookManagement]
GO
/****** Object:  StoredProcedure [dbo].[BOOK_LOGIN_I2]    Script Date: 2021-08-20 오후 6:58:32 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.08.20>
-- Description:	<도서관리프로그램, 사용자 등록>
-- =============================================
ALTER PROCEDURE [dbo].[BOOK_LOGIN_I2]
	@USER_NAME		NVARCHAR(20)
	,@USER_ADDR		NVARCHAR(50)
	,@USER_BIRTH	DATETIME
	,@USER_ID		NVARCHAR(20)
	,@USER_PW		NVARCHAR(20)
	,@USER_AUTH		INT
	,@USER_GRADE	INT
AS
BEGIN
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

	INSERT INTO Book_User_Info(user_name, user_address, user_birth) VALUES(@USER_NAME, @USER_ADDR, @USER_BIRTH);
	INSERT INTO Book_User_LogIn(user_id, user_pw, register_date, authority_no, grade_no) VALUES(@USER_ID, CONVERT(varbinary(256), @USER_PW), GETDATE(), @USER_AUTH, @USER_GRADE); -- admin
END








04. UserControls / UserSearchForm.cs

  • 오늘 한 것중 가장 프로시저 호출이많을거에요!

-1. Controls

  • AddForm도 SimpleButton으로 할걸싶네요, 바꿔도 되지만 퇴근시간이라
    • 나는 곧 무직이 된다 하루 빨리 뭐든 완성해서 재취업을 하자!
  • 가입일과 탈퇴일은 read-only로 해주었습니다. 굳이 따로 사용할곳은 없으니까요 해줄 필요는 없으니까요
  • Label
    • 여기서는 진짜 아무일도 안하기에 Pass
  • TextBox
    • user_no_txt
    • user_name_txt
    • user_address_txt
    • user_birth_txt
    • user_id_txt
    • user_registerdate_txt
    • user_deregisterdate_txt
  • ComboBox
    • user_auth_cmb
    • user_grade_cmb
  • SimpleBuoon
    • user_update_btn
    • user_delete_btn
    • reset_btn
    • cancel_btn
  • button
    • user_select_btn
  • GroupBox

-2. Code

  • UserSearchForm 생성자

    • 여기서는 등록과 마찬가지로 권한과 등급 콤보 박스 초기화를 해줍니다
  • user_select_btn_Click

    • 사용자 번호를 받아서 해당하는 사용자의 정보를 받아오는 메서드이며 번호가 있는지 없는지 확인하고
    • 조회한 데이터가 없으면 없다라고 알려주고 있다면 사용자 번호는 read-only = true로 변경해주셔서 고정시키고 다른 값들을 입력해줍니다
      • 초기화 버튼 누르면 번호도 다시 입력할 수 있으니 잠가 둘게요!
  • reset_btn_Click

    • 초기화 버튼은 텍스트박스 초기화 및 번호 조회 read-only를 false로 바꿔줍니다
  • user_delete_btn_Click

    • 유저 삭제 버튼과 수정 버튼은 유저를 먼저 조회했는지 확인 후 실행이 됩니다
    • 그리고 한번더 번호가 있는지 확인을 하고 삭제를 해줍니다
    • 삭제가 정상적으로 되면 성공 아니면 실패
  • user_update_btn_Click

    • 유저 삭제 버튼 메서드와 동일한데 수정이다 보니 텍스트 박스를 전체 조회 합니다!
    • 이번에는 메서드로 추출안해서 길죠! 이런 케이스와 저런 케이스가 있다는 걸 보여드리기도 하고 현재 이 Form에서는 재사용 안하니 넣어도 되서 넣었습니다
    • 수정을 할지 물어보고 수정을 한다고 하면 객체를 만들어서 그 객체를 넘겨 줍니다
    • 수정이 된다면 수정 완료, 아니면 실패
using BookManagementProgram.Model;
using BookManagementProgram.Repository;
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace BookManagementProgram.UserControls
{
    public partial class UserSearchForm : Form
    {
        BookUserRepository userRepository = null;

        public UserSearchForm()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterParent;
            userRepository = new BookUserRepository();

            user_auth_cmb.DataSource = new BindingSource(userRepository.GetAuthList(), null);
            user_auth_cmb.DisplayMember = "Key";
            user_auth_cmb.ValueMember = "Value";

            user_grade_cmb.DataSource = new BindingSource(userRepository.GetGradeList(), null);
            user_grade_cmb.DisplayMember = "Key";
            user_grade_cmb.ValueMember = "Value";
        }

        // 취소버튼
        private void cancel_btn_Click(object sender, EventArgs e)
        {
            this.Close();
        }


        // 유저 조회 버튼
        private void user_select_btn_Click(object sender, EventArgs e)
        {
            if(string.IsNullOrEmpty(user_no_txt.Text))
            {
                MessageBox.Show("사용자 번호를 입력해주세요.");
                user_no_txt.Focus();
                return;
            }

            User user = userRepository.GetUserByNumber(user_no_txt.Text);

            if(user == null)
            {
                MessageBox.Show("사용자 번호를 확인해주세요!");
                user_no_txt.Focus();
                return;
            }

            user_no_txt.ReadOnly = true;

            user_name_txt.Text = user.userName;
            user_address_txt.Text = user.userAddress;
            user_birth_txt.Text = user.userBirth;
            user_id_txt.Text = user.userId;
            user_registerdate_txt.Text = user.registerDate;
            user_deregisterdate_txt.Text = user.deregisterDate;
            user_auth_cmb.SelectedValue = user.authorityNo;
            user_grade_cmb.SelectedValue = user.gradeNo;
        }

        // 초기화 버튼
        private void reset_btn_Click(object sender, EventArgs e)
        {
            user_no_txt.ReadOnly = false;

            user_name_txt.Text = string.Empty;
            user_address_txt.Text = string.Empty;
            user_birth_txt.Text = string.Empty;
            user_id_txt.Text = string.Empty;
            user_registerdate_txt.Text = string.Empty;
            user_deregisterdate_txt.Text = string.Empty;
            user_auth_cmb.SelectedIndex = 0;
            user_grade_cmb.SelectedIndex = 0;
        }

        // 유저 삭제 버튼
        private void user_delete_btn_Click(object sender, EventArgs e)
        {
            if (!user_no_txt.ReadOnly)
            {
                MessageBox.Show("사용자 조회를 하고 수정해주세요.");

            }
            if (MessageBox.Show($"{user_no_txt.Text}번의 사용자를 정말 삭제하시겠습니까?", null, MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                if(userRepository.DeleteUserByNumber(user_no_txt.Text))
                {
                    MessageBox.Show("정상적으로 삭제 되었습니다.");
                    this.Close();
                    return;
                }
                MessageBox.Show("없는 사용자 이거나 번호를 확인해주세요.");
                return;
            }
            MessageBox.Show("취소 하셨습니다.");
        }

        // 유저 수정 버튼
        private void user_update_btn_Click(object sender, EventArgs e)
        {
            if(!user_no_txt.ReadOnly)
            {
                MessageBox.Show("사용자 조회를 하고 수정해주세요.");
            }

            if(string.IsNullOrEmpty(user_no_txt.Text))
            {
                MessageBox.Show("사용자 번호를 입력해주세요.");
                user_no_txt.Focus();
                return;
            }
            if (string.IsNullOrEmpty(user_name_txt.Text))
            {
                MessageBox.Show("사용자 이름을 입력해주세요.");
                user_name_txt.Focus();
                return;
            }
            if (string.IsNullOrEmpty(user_address_txt.Text))
            {
                MessageBox.Show("사용자 주소를 입력해주세요.");
                user_address_txt.Focus();
                return;
            }
            if (string.IsNullOrEmpty(user_birth_txt.Text) || CheckBirthPattern(user_birth_txt.Text))
            {
                MessageBox.Show("생년월일을 입력해주세요.");
                user_birth_txt.Focus();
                return;
            }
            if (string.IsNullOrEmpty(user_id_txt.Text))
            {
                MessageBox.Show("아이디를 입력해주세요.");
                user_id_txt.Focus();
                return;
            }

            if (MessageBox.Show($"{user_no_txt.Text}번의 사용자를 수정하시겠습니까?", null, MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                User user = new User();
                user.userNo = user_no_txt.Text;
                user.userName = user_name_txt.Text;
                user.userAddress = user_address_txt.Text;
                user.userBirth = user_birth_txt.Text;
                user.userId = user_id_txt.Text;
                user.authorityNo = (int)user_auth_cmb.SelectedValue;
                user.gradeNo = (int)user_grade_cmb.SelectedValue;

                if (userRepository.UpdateUserInfo(user))
                {
                    MessageBox.Show("정상적으로 수정 되었습니다.");
                    this.Close();
                    return;
                }
                MessageBox.Show("없는 사용자 이거나 번호를 확인해주세요.");
                return;
            }
            MessageBox.Show("취소 하셨습니다.");
        }

        // 생년월일 확인 정규식
        private bool CheckBirthPattern(string birth)
        {
            string pattern = @"^(19[0-9][0-9]|20\d{2})\.(0[0-9]|1[0-2])\.(0[1-9]|[1-2][0-9]|3[0-1])$";
            if (!Regex.IsMatch(birth, pattern))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}





-3. Repository / BookUserRepository.cs

  • GetUserByNumber
    • 유저 조회는 가입과 달리 admin만 조회할 수 있기에 번호로만 조회 합니다
    • DataTable로 받아와서 사용해두 되구요! 저처럼 객체를 사용해도 됩니다!
  • *DeleteUserByNumber
    • 사용자 삭제도 admin만 가능하기에 번호만으로도 삭제 가능하며 그렇기에 재차 메시지 박스로 물어보고 결정할 수있게 했습니다
  • UpdateUserInfo
    • 수정은 등록과 마찬가지로 대량의 데이터를 넘겨준다고 보시면 되구요
    • 비밀번호는 넣을까하다가 어차피 홈에 비밀번호 변경 버튼이 있기에 비밀번호는 제외했습니다
    • 그리고 수정에서는 제가 권한을 하나 추가했는데 admin, staff, 손님, dormant로 탈퇴희망 유저 이며 삭제를 안하고 탈퇴만 하고 권한을 안부여하게 할 예정입니다!
      - 어차피 dormant는 메인에서 권한을 안주었구요, dormant면 탈퇴시간만 추가해주면 됩니다
      - 만약에 dormant가 아니면 탈퇴시간 추가하면 안되겠죠!
      - 여기서 조건문 IF문을 사용하게 됩니다


-4. DB / Procedure / BOOK_LOGIN_S6

  • 사용자 번호로 사용자 조회 프로시저
USE [BookManagement]
GO
/****** Object:  StoredProcedure [dbo].[BOOK_LOGIN_S6]    Script Date: 2021-08-20 오후 7:42:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.08.20>
-- Description:	<도서관리 프로그램, 사용자번호로 사용자 조회>
-- =============================================
ALTER PROCEDURE [dbo].[BOOK_LOGIN_S6]
	@USER_NO		INT
AS
BEGIN
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
	
	SELECT	l.user_no, i.user_name, i.user_address, CONVERT(char(10), i.user_birth, 102), l.user_id, l.user_pw, l.register_date, l.deregister_date, a.authority_no, g.grade_no
	FROM			Book_User_LogIn	as l
	INNER JOIN		Book_User_Info	as i
	ON				l.user_no = i.user_no
	INNER JOIN		Book_User_Auth	as a
	ON				l.authority_no = a.authority_no
	INNER JOIN		Book_User_Grade	as g
	ON				l.grade_no = g.grade_no
	WHERE			l.user_no	=	@USER_NO;
END

-5. DB / Procedure / BOOK_LOGIN_D1

  • 회원번호로 회원 삭제 프로시저
USE [BookManagement]
GO
/****** Object:  StoredProcedure [dbo].[BOOK_LOGIN_D1]    Script Date: 2021-08-20 오후 7:40:05 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.08.20>
-- Description:	<도서관리프로그램, 사용자 삭제>
-- =============================================
ALTER PROCEDURE [dbo].[BOOK_LOGIN_D1]
	@USER_NO	INT
AS
BEGIN
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

	DELETE FROM Book_User_LogIn WHERE user_no = @USER_NO;
	DELETE FROM Book_User_Info WHERE user_no = @USER_NO;
END

-6. DB / Procedure / BOOK_LOGIN_U2

  • 사용자 정보 수정 프로시저
USE [BookManagement]
GO
/****** Object:  StoredProcedure [dbo].[BOOK_LOGIN_U2]    Script Date: 2021-08-20 오후 7:40:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.08.20>
-- Description:	<도서관리프로그램, 사용자 정보 수정>
-- =============================================
ALTER PROCEDURE [dbo].[BOOK_LOGIN_U2]
	@USER_NO		INT
	,@USER_NAME		NVARCHAR(20)
	,@USER_ADDR		NVARCHAR(50)
	,@USER_BIRTH	NVARCHAR(20)
	,@USER_ID		NVARCHAR(20)
	,@AUTH_NO		INT
	,@GRADE_NO		INT
AS
BEGIN
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

	
	UPDATE	Book_User_Info
	SET		user_name = @USER_NAME
			,user_address = @USER_ADDR
			,user_birth = @USER_BIRTH
	WHERE	user_no = @USER_NO;

	IF(@AUTH_NO = 3)
		UPDATE	Book_User_LogIn
		SET		user_id = @USER_ID
				,authority_no = @AUTH_NO
				,grade_no = @GRADE_NO
				,deregister_date = GETDATE()
		WHERE	user_no = @USER_NO;
	ELSE
		UPDATE	Book_User_LogIn
		SET		user_id = @USER_ID
				,authority_no = @AUTH_NO
				,grade_no = @GRADE_NO
				,deregister_date = NULL
		WHERE	user_no = @USER_NO;
	
END













수정사항

-1. UserSearchForm.cs

  • 삭제와 수정 버튼을 누르고 조회했는지 확인하는 부분에서 return을 안해줘서 다음 로직이 실행되네요! return 추가했습니다!
using BookManagementProgram.Model;
using BookManagementProgram.Repository;
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace BookManagementProgram.UserControls
{
    public partial class UserSearchForm : Form
    {
        BookUserRepository userRepository = null;

        public UserSearchForm()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterParent;
            userRepository = new BookUserRepository();

            user_auth_cmb.DataSource = new BindingSource(userRepository.GetAuthList(), null);
            user_auth_cmb.DisplayMember = "Key";
            user_auth_cmb.ValueMember = "Value";

            user_grade_cmb.DataSource = new BindingSource(userRepository.GetGradeList(), null);
            user_grade_cmb.DisplayMember = "Key";
            user_grade_cmb.ValueMember = "Value";
        }

        // 취소버튼
        private void cancel_btn_Click(object sender, EventArgs e)
        {
            this.Close();
        }


        // 유저 조회 버튼
        private void user_select_btn_Click(object sender, EventArgs e)
        {
            if(string.IsNullOrEmpty(user_no_txt.Text))
            {
                MessageBox.Show("사용자 번호를 입력해주세요.");
                user_no_txt.Focus();
                return;
            }

            User user = userRepository.GetUserByNumber(user_no_txt.Text);

            if(user == null)
            {
                MessageBox.Show("사용자 번호를 확인해주세요!");
                user_no_txt.Focus();
                return;
            }

            user_no_txt.ReadOnly = true;

            user_name_txt.Text = user.userName;
            user_address_txt.Text = user.userAddress;
            user_birth_txt.Text = user.userBirth;
            user_id_txt.Text = user.userId;
            user_registerdate_txt.Text = user.registerDate;
            user_deregisterdate_txt.Text = user.deregisterDate;
            user_auth_cmb.SelectedValue = user.authorityNo;
            user_grade_cmb.SelectedValue = user.gradeNo;
        }

        // 초기화 버튼
        private void reset_btn_Click(object sender, EventArgs e)
        {
            user_no_txt.ReadOnly = false;

            user_name_txt.Text = string.Empty;
            user_address_txt.Text = string.Empty;
            user_birth_txt.Text = string.Empty;
            user_id_txt.Text = string.Empty;
            user_registerdate_txt.Text = string.Empty;
            user_deregisterdate_txt.Text = string.Empty;
            user_auth_cmb.SelectedIndex = 0;
            user_grade_cmb.SelectedIndex = 0;
        }

        // 유저 삭제 버튼
        private void user_delete_btn_Click(object sender, EventArgs e)
        {
            if (!user_no_txt.ReadOnly)
            {
                MessageBox.Show("사용자 조회를 하고 삭제해주세요.");
                return;
            }
            if (MessageBox.Show($"{user_no_txt.Text}번의 사용자를 정말 삭제하시겠습니까?", null, MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                if(userRepository.DeleteUserByNumber(user_no_txt.Text))
                {
                    MessageBox.Show("정상적으로 삭제 되었습니다.");
                    this.Close();
                    return;
                }
                MessageBox.Show("없는 사용자 이거나 번호를 확인해주세요.");
                return;
            }
            MessageBox.Show("취소 하셨습니다.");
        }

        // 유저 수정 버튼
        private void user_update_btn_Click(object sender, EventArgs e)
        {
            if(!user_no_txt.ReadOnly)
            {
                MessageBox.Show("사용자 조회를 하고 수정해주세요.");
                return;
            }

            if(string.IsNullOrEmpty(user_no_txt.Text))
            {
                MessageBox.Show("사용자 번호를 입력해주세요.");
                user_no_txt.Focus();
                return;
            }
            if (string.IsNullOrEmpty(user_name_txt.Text))
            {
                MessageBox.Show("사용자 이름을 입력해주세요.");
                user_name_txt.Focus();
                return;
            }
            if (string.IsNullOrEmpty(user_address_txt.Text))
            {
                MessageBox.Show("사용자 주소를 입력해주세요.");
                user_address_txt.Focus();
                return;
            }
            if (string.IsNullOrEmpty(user_birth_txt.Text) || CheckBirthPattern(user_birth_txt.Text))
            {
                MessageBox.Show("생년월일을 입력해주세요.");
                user_birth_txt.Focus();
                return;
            }
            if (string.IsNullOrEmpty(user_id_txt.Text))
            {
                MessageBox.Show("아이디를 입력해주세요.");
                user_id_txt.Focus();
                return;
            }

            if (MessageBox.Show($"{user_no_txt.Text}번의 사용자를 수정하시겠습니까?", null, MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                User user = new User();
                user.userNo = user_no_txt.Text;
                user.userName = user_name_txt.Text;
                user.userAddress = user_address_txt.Text;
                user.userBirth = user_birth_txt.Text;
                user.userId = user_id_txt.Text;
                user.authorityNo = (int)user_auth_cmb.SelectedValue;
                user.gradeNo = (int)user_grade_cmb.SelectedValue;

                if (userRepository.UpdateUserInfo(user))
                {
                    MessageBox.Show("정상적으로 수정 되었습니다.");
                    this.Close();
                    return;
                }
                MessageBox.Show("없는 사용자 이거나 번호를 확인해주세요.");
                return;
            }
            MessageBox.Show("취소 하셨습니다.");
        }

        // 생년월일 확인 정규식
        private bool CheckBirthPattern(string birth)
        {
            string pattern = @"^(19[0-9][0-9]|20\d{2})\.(0[0-9]|1[0-2])\.(0[1-9]|[1-2][0-9]|3[0-1])$";
            if (!Regex.IsMatch(birth, pattern))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

-2. BookUserRepository.cs

  • 사용자 번호로 조회하는 소스에서 결과값이 없는데도 값을 받을려고 해서 에러가 발생해서 While로 했는데 if로 하셔도 됩니다.
  • 그리고 미리 User를 초기화해서 null이 아닌 값이 들어가기 때문에 결과가 있을 때 user 생성으로 변경하였습니다
using BookManagementProgram.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;

namespace BookManagementProgram.Repository
{
    class BookUserRepository : IBookUserRepository
    {
        private SqlConnection conn = null;
        private SqlCommand cmd = null;
        public static List<User> userList = null;
        public static User user = null;

        public BookUserRepository()
        {
            conn = DBConn.DBConn.getConn();
            cmd = new SqlCommand();
            cmd.Connection = conn;
        }

        // 로그인 로직
        public string Login(string userId, string userPw)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_S1 @USER_ID = '{userId}', @USER_PW = '{Encryption(userPw)}';";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while (SR.Read())
                    {
                        user = new User(
                            SR[0].ToString()
                            , SR[1].ToString()
                            , SR[2].ToString()
                            , SR[3].ToString()
                            , SR[4].ToString()
                            , SR[5].ToString()
                            , SR[6].ToString()
                            , (int)SR[7]
                            , (int)SR[8]
                            );
                    }
                    SR.Close();
                }

                return user.userNo;
            }
            catch(SqlException e)
            {
                return e.Message;
            }
            finally
            {
                conn.Close();
            }
        }

        // 아이디 찾기 로직
        public string FindById(string userNo, string userName)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_S2 @USER_NO = {userNo}, @USER_NAME = '{userName}';";
                string user_id = string.Empty;

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while (SR.Read())
                    {
                        user_id = SR[0].ToString();
                    }
                    SR.Close();
                }

                return $"아이디 : {user_id} 입니다.";
            }
            catch (SqlException e)
            {
                return e.Message;
            }
            finally
            {
                conn.Close();
            }
        }

        // 비밀번호 찾기 로직
        public bool FindByPassword(string userNo, string userId, string newPassword)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_U1 @USER_NO = {userNo}, @USER_ID = '{userId}', @NEW_PW = '{Encryption(newPassword)}';";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }
        }

        // 로그 입력
        public bool InsertLoginLog()
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_I1 @USER_NO = {user.userNo}, @USER_ID = '{user.userId}', @ENTER_IP = '{GetExternalIPAddress()}';";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }
        }

        // 사용자 전체 리스트
        public DataTable GetAllUsers()
        {
            DataTable dt = new DataTable();
            try
            {
                string sql = "EXEC BOOK_LOGIN_S3;";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    dt.Load(SR);
                }
                return dt;
            }
            catch (SqlException e)
            {
                return dt;
            }
            finally
            {
                conn.Close();
            }
        }

        // 권한 리스트
        public Dictionary<string, object> GetAuthList()
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            try
            {
                string sql = "EXEC BOOK_LOGIN_S4;";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while(SR.Read())
                    {
                        dic.Add(SR[1].ToString(), (int)SR[0]);
                    }
                }
                return dic;
            }
            catch (SqlException e)
            {
                return dic;
            }
            finally
            {
                conn.Close();
            }
        }

        // 등급 리스트
        public Dictionary<string, object> GetGradeList()
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            try
            {
                string sql = "EXEC BOOK_LOGIN_S5;";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while (SR.Read())
                    {
                        dic.Add(SR[1].ToString(), (int)SR[0]);
                    }
                }
                return dic;
            }
            catch (SqlException e)
            {
                return dic;
            }
            finally
            {
                conn.Close();
            }
        }

        // 사용자 등록
        public bool AddUser(User user)
        {
            try
            {
                string pw = Encryption(user.userPw);
                string sql = $"EXEC BOOK_LOGIN_I2 @USER_NAME = '{user.userName}', @USER_ADDR = '{user.userAddress}', @USER_BIRTH='{user.userBirth}', @USER_ID='{user.userId}', @USER_PW='{pw}', @USER_AUTH={user.authorityNo}, @USER_GRADE={user.gradeNo};";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }

        }

        // 유저 조회
        public User GetUserByNumber(string userNo)
        {
            User user = null;
            try
            {
                string sql = $"EXEC BOOK_LOGIN_S6 @USER_NO = {userNo};";

                cmd.CommandText = sql;
                conn.Open();

                // 데이터 출력
                using (SqlDataReader SR = cmd.ExecuteReader())
                {
                    while(SR.Read())
                    {
                        user = new User();
                        user.userNo = SR[0].ToString();
                        user.userName = SR[1].ToString();
                        user.userAddress = SR[2].ToString();
                        user.userBirth = SR[3].ToString();
                        user.userId = SR[4].ToString();
                        user.userPw = SR[5].ToString();
                        user.registerDate = SR[6].ToString();
                        user.deregisterDate = SR[7].ToString();
                        user.authorityNo = (int)SR[8];
                        user.gradeNo = (int)SR[9];
                    }
                }
                return user;
            }
            catch (SqlException e)
            {
                return user;
            }
            finally
            {
                conn.Close();
            }
        }

        // 사용자 삭제
        public bool DeleteUserByNumber(string userNo)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_D1 @USER_NO = {userNo};";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }
        }

        // 사용자 정보 수정
        public bool UpdateUserInfo(User user)
        {
            try
            {
                string sql = $"EXEC BOOK_LOGIN_U2 @USER_NO = {user.userNo}, @USER_NAME = '{user.userName}', @USER_ADDR = '{user.userAddress}', @USER_BIRTH = '{user.userBirth}', @USER_ID = '{user.userId}', @AUTH_NO = {user.authorityNo}, @GRADE_NO = {user.gradeNo};";

                cmd.CommandText = sql;
                conn.Open();

                return cmd.ExecuteNonQuery() > 0 ? true : false;
            }
            catch (SqlException e)
            {
                return false;
            }
            finally
            {
                conn.Close();
            }
        }

        // SHA256 암호화 메서드
        public static string Encryption(string data)
        {
            SHA256 sha = new SHA256Managed();
            byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(data));
            StringBuilder stringBuilder = new StringBuilder();
            foreach (byte b in hash)
            {
                stringBuilder.AppendFormat("{0:x2}", b);
            }
            return stringBuilder.ToString();
        }

        // 외부 IP
        public static string GetExternalIPAddress()
        {
            string externalip = new WebClient().DownloadString("http://ipinfo.io/ip").Trim();

            return externalip ?? GetInternalIPAddress();//null경우 내부 IP 반환;
        }

        // 내부
        // DNS, 단순 도메인 이름 확인 기능이 제공
        // GetGostEntity, 호스트 이름 또는 IP 주소를 IPHostEntry 인스턴스로 확인
        // GetHostName, 로컬 컴퓨터의 호스트 이름을 가져온다
        public static string GetInternalIPAddress()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());

            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }

            throw new Exception("인터넷 연결 없음");
        }
    }
}
profile
아직까지는 코린이!

0개의 댓글