오늘은 DB의 구성을 왜 잘 해야하는가에 대해 깨닫는 하루였습니다. 각각 맡은 부분을 하면서 각자 컴퓨터에 SQL 테이블을 작성했는데 컬럼이 달라서 하나하나 수정하고 맞춰가며 작업을 진행하다보니 시간도 많이 잡아먹고, 하나하나 찾는게 정말 쉽지 않았습니다. 페이지 종류가 많아지면서 코드는 점점 복잡해지는데 꼬이고 오류 뜨고 어디서부터 해결해야 할지 감조차 잡히지 않습니다.
이걸 하나하나 해결해나가는 동기들을 보면 참 대단하다 싶습니다. 도움이 되고 싶어 뭐라도 아득바득 해보려 하는데, 뱁새가 황새를 따라가려는 것처럼 다리만 찟어지고 아픕니다. 너무 많은 분야를 한번에 공부하려니 머리만 아프고 답답하네요. 다음 프로젝트에서는 이런일이 없었으면 좋겠습니다. 더욱 분발해야죠. 그 때는 이렇게 일기 쓰는 프로젝트 진행 상황이 아닌 어떤 문제와 해결해 나가는 과정을 다뤄보도록 하겠습니다. 이번 미니 프로젝트에서는 너그러히 바주십사 부탁드립니다. ㅎㅎ
SQL 공부를 하고, 데이터 베이스와 친해질 겸 DB 내용에 중복 등 문제 제거 작업을 진행했습니다. 또한 이미 데이터 베이스는 마련이 되었고, flask까지 연결을 마쳤으니 이제 남은건 기능들을 추가하는 것입니다. 사실 이번에는 저 포함 조원들이 파이썬, SQL, Flask에 대해 아는 것이 거의 없다 시피해서 우리 멋진 조장님께서 큰 틀에대해 설명해줬고, 이 프로젝트는 SQL과 flask를 사용해 원활한 서비스를 하는 것이므로 디자인은 크게 신경쓰지 않는 방향으로 진행하기로 했습니다.
이번 추가 안건은 검색 페이지에 아래와 같이 목록을 미리 정할 수 있도록 하면 어떨지입니다. 얼른 따라가야할텐데 명령어 숙지부터 이 내용을 따라가기가 벅차다는 느낌이 들기도 하네요...
오늘은 MySQL을 다운로드 받고 이전에 제작한 html과 DB를 연결해 로그인 기능을 구현하려 했습니다. 해당 내용을 구현하기 위해 해당 페이지를 참고했으나 제작하는 과정에서 오류가 많이 나와 오늘은 미완성인 채로 아쉽게 마무리 되었습니다. 이전에 중구난방으로 html과 css를 제작했었으나 이번에는 각각 폴더를 지정해 몰아 넣어 정리했습니다. 하지만, 저는 오늘 건강관계상 같이 토론은 못하고 내용을 전달받고 이 코드가 무슨뜻인지 주석을 달아주는 것 밖에 못했습니다. DB랑 연결해서 실험을 해봐야하는데, 오늘은 이렇게 가볍게 마치고 이번 주말에 더 공부해볼 생각입니다.
다음은 코드와 무슨 뜻인지 정리되어있으니 참고할 수 있을 것으로 생각됩니다. 참고로 html의 주석은 <!-- -->, 파이썬의 주석은 #, sql의 주석은 -- 입니다. 이 때 html의 주석의 내용은 <!----> 이 빨간 부분에 작성하게 됩니다.
<!DOCTYPE html> <!-- HTML5 문서 유형 선언 --> <html lang="en"> <!-- 문서 언어 설정 --> <head> <!-- head 태그 시작 --> <meta charset="UTF-8"> <!-- 문자 인코딩 설정 --> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 반응형 웹 설정 --> <title>Document</title> <!-- 문서 제목 --> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700&display=swap" rel="stylesheet"> <!-- 구글 폰트 링크 --> <script src="https://kit.fontawesome.com/53a8c415f1.js" crossorigin="anonymous"></script> <!-- Font Awesome 아이콘 링크 --> <link rel="stylesheet" href="{{ url_for('static', filename='login.css')}}"> <!-- CSS 파일 링크 --> </head> <!-- head 태그 종료 --> <body> <div class="wrap"> <div class="login"> <h2>Log-in</h2> <div class="loginaction"> <!-- 로그인 폼 --> <form action="{{ url_for('login')}}" method="post" autocomplete="off"> <!-- 메시지 출력 --> <div class="msg">{{ msg }}</div> <!-- 아이디 입력 --> <div class="login_id"> <h4>ID</h4> <input type="text" name="" id="" placeholder="ID"> </div> <!-- 비밀번호 입력 --> <div class="login_pw"> <h4>Password</h4> <input type="password" name="" id="" placeholder="Password"> </div> <!-- 기타 옵션 --> <div class="login_etc"> <!-- 아이디 저장 체크박스 --> <div class="checkbox"> <input type="checkbox" name="" id=""> 아이디 저장 </div> <!-- 비밀번호 찾기 링크 --> <div class="forgot_pw"> <a href="">비밀번호 찾기</a> </div> </div> <!-- 로그인 버튼 --> <div class="submit"> <input type="submit" value="login"> </div> </form> </div> <!-- 회원가입 버튼 --> <div class="submit"> <a href="/signup"> <input type="submit" value="Sign Up"> </a> </div> </div> </div> </body> </html>
4. sginup.html : 회원가입 페이지
<!DOCTYPE html> <!-- HTML5 문서 유형 선언 --> <html lang="en"> <!-- 문서 언어 설정 --> <head> <!-- head 태그 시작 --> <meta charset="UTF-8"> <!-- 문자 인코딩 설정 --> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 반응형 웹 설정 --> <title>Document</title> <!-- 문서 제목 --> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700&display=swap" rel="stylesheet"> <!-- 구글 폰트 링크 --> <script src="https://kit.fontawesome.com/53a8c415f1.js" crossorigin="anonymous"></script> <!-- Font Awesome 아이콘 링크 --> <link rel="stylesheet" href="{{ url_for('static', filename='login.css')}}"> <!-- CSS 파일 링크 --> </head> <!-- head 태그 종료 --> <body> <div class="wrap"> <div class="login"> <h2>Log-in</h2> <div class="loginaction"> <!-- 로그인 폼 --> <form action="{{ url_for('login')}}" method="post" autocomplete="off"> <!-- 메시지 출력 --> <div class="msg">{{ msg }}</div> <!-- 아이디 입력 --> <div class="login_id"> <h4>ID</h4> <input type="text" name="" id="" placeholder="ID"> </div> <!-- 비밀번호 입력 --> <div class="login_pw"> <h4>Password</h4> <input type="password" name="" id="" placeholder="Password"> </div> <!-- 기타 옵션 --> <div class="login_etc"> <!-- 아이디 저장 체크박스 --> <div class="checkbox"> <input type="checkbox" name="" id=""> 아이디 저장 </div> <!-- 비밀번호 찾기 링크 --> <div class="forgot_pw"> <a href="">비밀번호 찾기</a> </div> </div> <!-- 로그인 버튼 --> <div class="submit"> <input type="submit" value="login"> </div> </form> </div> <!-- 회원가입 버튼 --> <div class="submit"> <a href="/signup"> <input type="submit" value="Sign Up"> </a> </div> </div> </div> </body> </html>
5. app.py : flask를 DB와 파이썬 연결
from flask import Flask, render_template, request, redirect, url_for, session # Flask, render_template, request, redirect, url_for, session 모듈 import from flask_mysqldb import MySQL # Flask MySQL 모듈 import import MySQLdb.cursors # MySQLdb.cursors 모듈 import import re # re 모듈 import app = Flask(__name__, static_folder='static') # Flask 객체 생성 app.secret_key = 'your secret key' # 세션 보안을 위한 secret key 설정 app.config['MYSQL_HOST'] = 'localhost' # MySQL 호스트 설정 app.config['MYSQL_USER'] = 'root' # MySQL 유저 설정 app.config['MYSQL_PASSWORD'] = '1234' # MySQL 비밀번호 설정 app.config['MYSQL_DB'] = 'ebook' # MySQL 데이터베이스 설정 mysql = MySQL(app) # MySQL 객체 생성 # 홈페이지 @app.route('/') # '/' 경로로 들어왔을 때 실행되는 함수 def home(): return render_template('main.html') # 'main.html' 파일을 렌더링하여 반환 # 로그인 페이지 @app.route('/login', methods=['GET', 'POST']) def login(): msg = '' if request.method == 'POST' and 'account' in request.form and 'password' in request.form: # 만약 요청 방식이 POST이고, 폼 데이터에 'account'와 'password'가 모두 있다면 account = request.form['account'] # POST 요청에서 account 값을 가져옴 password = request.form['password'] # POST 요청에서 password 값을 가져옴 cursor = mysql.connection.cursor( MySQLdb.cursors.DictCursor) # MySQLdb 모듈을 사용하여 커서 생성 cursor.execute( 'SELECT * FROM user WHERE account = % s \ AND password = % s', (account, password, )) # SQL 쿼리 실행 user = cursor.fetchone() # 쿼리 결과를 가져옴 if user: # 쿼리 결과가 있으면 session['loggedin'] = True # 로그인 상태를 True로 변경 session['account'] = user['account'] # 세션에 account 값을 저장 session['password'] = user['password'] # 세션에 password 값을 저장 msg = 'Logged in successfully !' # 로그인 성공 메시지 return render_template('main.html', msg=msg) # main.html 페이지를 렌더링하며 msg 값을 전달 else: # 쿼리 결과가 없으면 msg = 'Incorrect username / password !' # 로그인 실패 메시지 return render_template('login.html', msg=msg) # login.html 페이지를 렌더링하며 msg 값을 전달
# 로그아웃 @app.route('/logout') def logout(): session.pop('loggedin', None) # 'loggedin' 세션 삭제 session.pop('account', None) # 'account' 세션 삭제 session.pop('password', None) # 'password' 세션 삭제 return redirect(url_for('login')) # login 페이지로 리다이렉트 # 회원가입 페이지 @app.route('/signup', methods=['GET', 'POST']) def signup(): msg = '' # 다음 코드는 POST 요청이 들어왔을 때, 모든 필드가 채워졌는지 확인하고, 채워졌다면 해당 값을 변수에 저장한다. if request.method == 'POST' \ and 'account' in request.form \ and 'password' in request.form \ and 'username' in request.form \ and 'email' in request.form \ and 'gender' in request.form \ and 'birth' in request.form \ and 'phonenumber' in request.form: account = request.form['account'] password = request.form['password'] username = request.form['username'] email = request.form['email'] gender = request.form['gender'] birth = request.form['birth'] phonenumber = request.form['phonenumber'] # 다음 코드는 MySQL 데이터베이스에 연결하고, 입력한 계정이 이미 존재하는지 확인한다. cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor) cursor.execute( 'SELECT * FROM user WHERE account = % s', (account, )) user = cursor.fetchone() # 다음 코드는 이미 존재하는 계정이라면 에러 메시지를 출력한다. if user: msg = '이미 존재하는 계정입니다 !' # 다음 코드는 이메일 형식이 올바르지 않다면 에러 메시지를 출력한다. elif not re.match(r'[^@]+@[^@]+\.[^@]+', email): msg = 'Email 형식에 맞지 않습니다 !' # 다음 코드는 이름이 올바른 형식이 아니라면 에러 메시지를 출력한다. elif not re.match(r'[A-Za-z0-9]+', username): msg = 'name must contain only characters and numbers !' # 다음 코드는 모든 조건을 만족한다면, 데이터베이스에 새로운 사용자 정보를 추가한다. else: cursor.execute('INSERT INTO user VALUES \ (% s, % s, % s, % s, % s, % s, % s)', (account, password, username, email, gender, birth, phonenumber)) mysql.connection.commit() msg = '가입을 환영합니다 !' # 다음 코드는 POST 요청이 들어왔지만, 필드가 채워지지 않았다면 에러 메시지를 출력한다. elif request.method == 'POST': msg = 'Please fill out the form !' # 다음 코드는 GET 요청이 들어왔을 때, 회원가입 페이지를 렌더링한다. return render_template('signup.html', msg=msg) # 메인 페이지 @app.route("/main") def index(): if 'loggedin' in session: # 로그인 여부를 세션에서 확인 return render_template("main.html") # 로그인 되어 있으면 main.html 페이지 렌더링 return redirect(url_for('login')) # 로그인 되어 있지 않으면 login 페이지로 리다이렉트 # 마이페이지 @app.route('/mypage.html') # '/mypage.html' 경로로 요청이 들어오면 def mypage(): # mypage 함수 실행 return render_template('mypage.html') # mypage.html 파일을 렌더링하여 반환
if __name__ == '__main__': # 현재 파일이 실행되는 메인 파일일 경우 app.run(debug=True) # Flask 애플리케이션을 debug 모드로 실행
6. user.sql : DB
create database ebook default character set utf8 collate utf8_general_ci; -- ebook 데이터베이스 생성 및 문자 인코딩 설정 use ebook -- ebook 데이터베이스 사용 create table user ( -- user 테이블 생성 account char(30) not null, -- 계정(아이디) 열 생성, null 값 불가능 password varchar(255) not null, -- 비밀번호 열 생성, null 값 불가능 username varchar(50) not null, -- 사용자 이름 열 생성, null 값 불가능 email varchar(100) not null, -- 이메일 열 생성, null 값 불가능 gender varchar(10) not null, -- 성별 열 생성, null 값 불가능 birth date not null, -- 생년월일 열 생성, null 값 불가능 phonenumber varchar(30), -- 전화번호 열 생성, null 값 가능 primary key(account) -- account 열을 기본키로 설정 ) engine=InnoDB default charset=utf8; -- InnoDB 스토리지 엔진 사용 및 문자 인코딩 설정
프로젝트 4일차에 프론트쪽은 거의 완성되가는 느낌입니다. 이외의 작업은 DB를 연결하고 기타 기능들도 구현을 해야했으나, 강사님께서 진행하는 속도보다 훨씬 빠른 속도로 진행이 되어버렸기 때문에 DB 부분은 잠시 쉬어가고 아래 페이지들을 조금씩 다듬었는데, 소소한 문제들이 계속 나와서 어떻게 해야될지 머리를 싸매 고민하고 있습니다.
잘하는 친구들이 있어 공부를 하는 방향성에 대해서 조금씩 듣고 있는데 개발을 처음부터 끝까지 한다는 것 자체가 쉽지 않다는 것을 깨달아 가고 있습니다. 왜 이걸 통틀어 하는 직업군은 없고 DB 전문가, 프론트엔드 전문가, 백엔드 전문가들이 나뉘어 한 프로젝트에 수십, 많으면 수백명이 달려드는지 알 수 있었습니다.
웹페이지를 하나 만드는데 html로 페이지의 뼈대를 만들고, css로 디테일한 디자인을 다듬고, JAVA등을 이용해 기능을 구현합니다. 또 DB에 연결을 하고, 책들에 대한 정보를 고객에게 보여주는데, 보안도 신경써야하고... 서버를 구현해야하기에 하드웨어도 신경써야합니다.
최근 생성형 AI가 엄청나게 개발되고 있는데 그게 아니였다면 이렇게 빠르게 만들 수 있었을까 싶기도 합니다. 원래 대학교 수준에서 웹페이지를 서비스하려고 하면 프론트 엔드만 2~3주 잡기도 한다는 말을 듣고 소름이 끼치더군요. 단순한 코딩작업을 생성형 AI가 도와주니 좋다고 생각이 들다가 최근 생성형 AI가 생각보다 개발을 잘해줘서 개발자들이 자리가 없어지는 것 아니냐고 고민하는 말들이 슬프게 들리기도 합니다.
프로젝트 진행에 대해 적어야하는데 공부가 부족해 일기를 쓰는 느낌이 되어버린 것 같아 웃기면서 조금 슬프기도 하네요. 얼른 또 공부를 하러 가봐야겠습니다. 개발자들의 고뇌를 조금이나마 깨닫게 되는 시간이었습니다.
초안을 간단한 툴들로 만들었습니다. html과 css로 타이핑해서 만드는 것도 좋지만, 요즘은 툴들이 너무 잘나와서 언어 몰라도 프로그래밍 할 수 있다는게 조금씩 무슨 말인지 알 것 같습니다. ChatGPT같은 생성형 AI가 짜주는 코드들도 잘 활용하면 멋진 작품이 탄생할 것 같다는 생각이 듭니다.
이미지를 넣어보려고 하는데 너무 뒤죽박죽으로 적용되고, 어디서부터 찾아나가야할지 조금더 알아봐야겠습니다. 뭔가 틀들이 잡혀나가는 모습을 보니 점점 재미있어지네요. 오늘은 이렇게 간단히 짚고 넘어가겠습니다.