[포스코X코딩온 스마트 팩토리 개발자과정 1기] Final TeamProject 회고록

맨 땅에 개발자 되기·2023년 4월 12일
0
post-thumbnail

💻Chat_program_project

( 사용된 tool : C++, MySQL 연동, socket 통신 )


필수 구현

  1. DB에 미리 기본정보를 저장
  2. 저장된 DB의 아이디와 비번을 입력받아 로그인
  3. 클라이언트가 채팅에 입장했을 때, 이전 메세지 출력

선택 구현

  1. 회원가입 (이름, 닉네임, 아이디, 비번 순으로 DB에 저장)
  2. 회원탈퇴 (아이디로 탈퇴가능)

각 CPP파일의 주요 기능을 살펴보자 !

Server

void create_table() → 테이블 생성

C++에서 테이블을 생성하는 쿼리(CREATE문) 사용하여 MySQL DB에 저장

void create_table() {
	try
	{
		driver = get_driver_instance();
		con = driver->connect(server, username, password);
	}
	catch (sql::SQLException e)
	{
		cout << "Could not connect to server. Error message: " << e.what() << endl;
		system("pause");
		exit(1);
	}

	con->setSchema("chatprogram");

	// message 테이블 생성
	stmt = con->createStatement(); //회원가입 내역 저장 시 워크벤치에서 미리 테이블 생성하기
	stmt->execute("DROP TABLE IF EXISTS message");
	cout << "Finished dropping table (if existed)" << endl;
	stmt->execute("CREATE TABLE message (user_index serial PRIMARY KEY, user_nick_name VARCHAR(50), user_message VARCHAR(100));");
	cout << "Finished creating table" << endl;
}

void recv_msg(int idx) → 테이블 message에 메세지 저장

클라이언트의 메세지를 정상적으로 받을 경우, insert문으로 테이블에 메세지 저장

만약 클라이언트가 탈퇴했을 시, 퇴장 문구 출력하고 채팅인원 감소시킴

void recv_msg(int idx) {	
	korean();

	char buf[MAX_SIZE] = {};
	string msg = "";
	bool not_in=0;
	while (1) {
		ZeroMemory(&buf, MAX_SIZE);
		if (recv(sck_list[idx].sck, buf, MAX_SIZE, 0) > 0) {

			//////////////////////if 문으로 버퍼에 "종료"가 담겨있을 경우 공지 띄우고 del_client
			if (buf == "회원탈퇴로 인한 종료") { del_client(idx); }

			msg = sck_list[idx].user + " : " + buf;
			cout << msg << endl;
			pstmt = con->prepareStatement("INSERT INTO message(user_nick_name, user_message) VALUES(?,?)");
			pstmt->setString(1, sck_list[idx].user);
			pstmt->setString(2, string(buf));
			pstmt->execute();

			send_msg(msg.c_str());			
		}

		else {
			msg = "[공지]" + sck_list[idx].user + "님이 퇴장했습니다.";
			cout << msg << endl;
			send_msg(msg.c_str());
			del_client(idx);
			return;
		}
	}
}

void del_client(int idx) → 서버 종료

클라이언트들이 다 퇴장하여 0명이 되었을 경우, 서버가 종료

void del_client(int idx) {
	closesocket(sck_list[idx].sck);
	client_count--;
	cout << "[공지] 현재 접속자 수 : " << client_count << "명" << endl;
	if (client_count == 0) {
		cout << "접속자 수가 0명이 되어 프로그램을 종료합니다" << endl;
		exit(1);
	}
}

Join

void create_table() → 테이블 information 생성

디폴트값으로 4개의 기존 회원정보를 가지고 시작

void create_table() {

    con->setSchema("chatprogram");
    // information 테이블 생성
    stmt = con->createStatement(); 
    stmt->execute("DROP TABLE IF EXISTS information");
    cout << "Finished dropping table (if existed)" << endl;
    stmt->execute("CREATE TABLE information (nick_name VARCHAR(20) PRIMARY KEY NOT NULL, name VARCHAR(20) NOT NULL, id VARCHAR(20) NOT NULL, pw VARCHAR(20) NOT NULL);");
    cout << "Finished creating table" << endl;
       

    ///////////information Table 디폴트값 추가////////////
    pstmt = con->prepareStatement("INSERT INTO information (nick_name, name, id, pw) VALUES(?,?,?,?)");
    pstmt->setString(1,"Adam"); //닉네임 (중복 불가)
    pstmt->setString(2,"김민지"); //이름
    pstmt->setString(3,"kim0000"); //id (중복 불가)
    pstmt->setString(4,"1234"); // pw
    pstmt->execute();

    pstmt->setString(1, "Alice"); 
    pstmt->setString(2, "이윤정"); 
    pstmt->setString(3, "lee123"); 
    pstmt->setString(4, "4321"); 
    pstmt->execute();

    pstmt->setString(1, "Bunny"); 
    pstmt->setString(2, "송혜교"); 
    pstmt->setString(3, "song77");
    pstmt->setString(4, "6839");
    pstmt->execute();

    pstmt->setString(1, "Amy"); 
    pstmt->setString(2, "박연진");
    pstmt->setString(3, "park44"); 
    pstmt->setString(4, "4444"); 
    pstmt->execute();
}

void information_insert() → 새로운 회원정보 저장

회원 가입시, 새로운 회원에 대한 정보를 테이블 information에 저장

void information_insert(string nick_name, string name, string id, string pw){
    try
    {
        driver = get_driver_instance();
        con = driver->connect(server, username, password);
    }
    catch (sql::SQLException e)
    {
        cout << "Could not connect to server. Error message: " << e.what() << endl;
        system("pause");
        exit(1);
    }
    korean();

  //information insert
    pstmt = con->prepareStatement("INSERT INTO information(nick_name,name,id,pw) VALUES(?,?,?,?)");
    pstmt->setString(1, nick_name); //닉네임 (중복 불가)
    pstmt->setString(2, name); //이름
    pstmt->setString(3, id); //id (중복 불가)
    pstmt->setString(4, pw); // pw
    pstmt->execute();
    cout << "One row inserted." << endl;

void duplicate() → 회원 가입 시, 기존 정보와의 중복 검사

회원 가입시, 기존 회원의 ID와 PW이 같은지 확인을 통해 같으면 다른 ID와 PW을 사용할 수 있도록 안내함

void duplicate(string input, string *creat_input,string *find_id, string query) {
    while (1) {
        cout << "생성할" << input << ((input == "id") ? "를" : "을") << " 입력하세요 : " << endl;
        cin >> *creat_input;

        con->setSchema("chatprogram");
        pstmt = con->prepareStatement(query);
        result = pstmt->executeQuery();

        while (result->next()) {
            *find_id = result->getString(input);
            if (find_id == creat_input) { break; }
        }
        if (find_id == creat_input) {
            cout << input <<"가 중복되었습니다." << endl << "다시 입력하세요" << endl;
            continue;
        }
        break;
    }
}

void drop_out_duplicate() → 회원 탈퇴 시, 입력한 ID 삭제

탈퇴하고자 하는 회원의 ID를 입력했을 경우, ID에 해당되는 모든 속성이 삭제

void drop_out_duplicate(string *id, string *find_id) { ///////////회원 탈퇴/////////////////
    korean();
    while(1){        
        cout << "아이디를 입력해주세요 : ";
        cin >> *id;

        con->setSchema("chatprogram");
        pstmt = con->prepareStatement("SELECT id FROM information;");
        result = pstmt->executeQuery();

        while (result->next()) {
            *find_id = result->getString("id");
            if (*find_id == *id) { break; }
            else { *find_id = "NONE"; }
        }

        if (*find_id != *id) {
            cout << "ID가 존재하지 않습니다." << endl << "다시 입력하세요" << endl;
            continue;
        }
        //drop
        pstmt = con->prepareStatement("DELETE FROM information WHERE id = ?");
        pstmt->setString(1, *id);
        result = pstmt->executeQuery();
        cout << *id << "님 회원 탈퇴 되었습니다" << endl;
        break;
    }
}

Client

void recv_prev_msg() → 이전 메세지들 출력

클라이언트가 채팅방에 입장하게 되면, select문으로 이전 채팅의 기록들을 모두 출력

void recv_prev_msg() {     // 이전 메세지들 출력

	string find_user, find_msg;

	cout << "server의 기록을 출력합니다" << endl;
	con->setSchema("chatprogram");
	pstmt = con->prepareStatement("SELECT user_nick_name,user_message FROM message;");
	result = pstmt->executeQuery();

	while (result->next()) {
		find_user = result->getString("user_nick_name");
		find_msg = result->getString("user_message");
		cout << find_user << " : " << find_msg << endl;
	}
	cout << "------------------------------------------" << endl;
}

void duplicate_login → 로그인 할 때, ID랑 PW 일치하는 검사

: ID 입력이 틀리면 다시 입력하도록 문구가 출력되고 맞으면 PW를 입력,

마찬가지로 PW 입력이 틀리면 다시 입력하도록 출려되고 맞으면 로그인 성공!

void duplicate_login(string input, string query, bool check, string* create_input) {

	string find;

	while (check == 1) {

		check = 1;

		cout << input << "를 입력하세요 -> \n";
		cin >> *create_input;

		// ID 확인 -> check_id == 0;
		con->setSchema("chatprogram");
		pstmt = con->prepareStatement(query);
		result = pstmt->executeQuery();

		while (result->next()) {
			find = result->getString(input);
			if (find == *create_input) {
				check = 0;
			}
		}
		if (check == 1) { cout << "잘못된 " << input << "입니다." << endl << "다시 입력하세요" << endl; }
	}
}

프로젝트를 끝내며...

스마트 팩토리 개발자 과정의 대미를 장식할 마지막 팀프로젝트 발표를 모두 완료할 수 있었다!! 우리반 에이스 민지님과 함께 할 수 있어서 감사하고🙇‍♀️우리 사이의 실력의 갭이 커서 미안했다🙍‍♀️

특히, 프로젝트 협업을 위해 git을 사용하였는데... 와 미치는줄 알았다... 나름 조심해서 git push하고, git pull받았는데 자꾸 충돌이 일어나고... 세어봤더니 프로젝트하는 5일동안 35번의 merging을 했었다😂

자 다시 기억해내보자...
협업할 때는 git branch에서 git push 👍
merging할 때, 수정된 부분에 멘트 & 확인 멘트 남기기👍
수정본 받을 때는 git main에서 git pull👍

profile
완전초보 PLC / HMI / Intouch / C++ / SQL

0개의 댓글