ip 는 찾아갈 건물주소라고 생각하면 된다.
우리학원의 건물주소는 ~~~서울시 ~~동 ~~건물~~ 층의 mbc아카데미 하면 이것이 ip이다.
도메인은 건물 그자체라고 보면 되는데 ,도메인은 외우기 쉽게 한것이다.
도메인 주소를 치면 해당아이피로 이동한다.
dms name server라고 존재하는데
port 는 방번호라고 생각하면 된다.겹치면 안된다.8000번으로 쓰고 있음 마리아디비는 3306 서버를 썻고,
내 자리의 아이피를 아는 방법 2가지가 있는데
검색창 window키 -> 클릭 cmd 입력-> ipconfig 192.000.0.00 과
사설ip 프라이빗ip라고도 하는데 , 외부에서 접근 불가하다.
네이버로 들어가서 공인ip를 검색해볼수 있다.이건 외부에서 접근 가능하다.
10_fastapi_09_member ; #회원가입 코드리뷰를 하기위해 이해가 안되서 제미나이에게 물어봣다.
import logging
from typing import Dict
import sqlalchemy
from fastapi import FastAPI
from starlette.responses import RedirectResponse
from starlette.staticfiles import StaticFiles
from db import get_db
app =FastAPI()
app.mount("/view", StaticFiles(directory="view"))
#Logger 설정
#DEBUG > INFO > WARNING > ERROR > CRITICAL
logging.basicConfig(
level=logging.INFO, #보여줄 정보의 정도
format='%(levelname)s: [%(name)s]%(message)s-%(asctime)s', #출력할 형태(pdf참조)
datefmt='%Y-%m-%d %H:%M:%S' #날짜/시간 보여줄 형태
)
logger = logging.getLogger(__name__) #현재 모듈의 이름으로 로거 생성
@app.get("/")
def main():
return RedirectResponse(url="/view/index.html")
@app.get("/overlay")
def overlay(id:str):
logger.info(f'id:{id}')
# SELECT COUNT(id) AS cnt FROM MEMBER WHERE id = 'admin';
#1. DB 접속
conn = get_db()
cnt =1
try:
#2. 쿼리문 실행
sql = sqlalchemy.text('SELECT COUNT(id) AS cnt FROM MEMBER WHERE id = :id')
# 3. 실행 결과 가져오기
result = conn.execute(sql,{'id':id}).mappings().fetchone()
print(f'result={result}')
cnt = result['cnt']
except Exception as e:
logger.error(f'e:{e}')
finally:
# 4.사용한 DB 닫아주기
conn.close()
return{'use': cnt}
#post로 파라메터를 받을때 받아주는 class 를 만들어 줘야 했다.
#이게 귀찮다면 dictionary로 대체 가능 하다.(별로 권장하진 않는다.)
@app.post("/join")
def join(info:Dict[str,Any]):
logger.info(f'info={info}')
row = 0
# """ 혹은 ''' 는 여러줄 문자열도 수용한다.
sql=sqlalchemy.text('''INSERT INTO member(id,pw,name,age,gender,email)
VALUES(:id,:pw,:name,:age,:gender,:email)''') #1.쿼리문 작성
conn = get_db() #2.DB객체 받아옴
try:
#3.쿼리문 실행
result = conn.execute(sql,info) #select 문이 아니므로 mappings 나 fetch가 필요 없다
row = result.rowcount #영향받은 row의 수
logger.error(f'영향받은 row의 수:{row}')
#fastapi는 auto commit 이 off 되어 있기 때문에 수동 commit 을 해줘야한다.
conn.commit() #성공시 확정
except Exception as e:
logger.error(e)
conn.rollback() #예외 발생시 취소
finally:
conn.close() #4.닫기(자원반납)
return {'row':row}
<html>
<head>
<link rel="icon" href="data:,">
<meta charset="UTF-8">
<title></title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<style>
table,th,td{
border: 1px solid black;
border-collapse: collapse;
}
th,td{
padding: 10px;
}
input[type="text"],input[type="email"],input[type="password"],input[type="range"]{
width: 100%;
}
input[name="user_id"]{
width: 65%;
}
</style>
</head>
<body>
<h1>회원가입</h1>
<hr/>
<table>
<tr>
<th>아이디</th>
<td>
<input name="user_id" type="text"/>
<button onclick="overlay()">ID 중복체크</button>
<div id="overlay"></div>
</td>
</tr>
<tr>
<th>비밀번호</th>
<td>
<input name="user_pw" type="password"/>
</td>
</tr>
<tr>
<th>비밀번호 확인</th>
<td>
<input id="confirm" type="text"/>
<div id="msg"></div>
</td>
</tr>
<tr>
<th>이름</th>
<td><input name="user_name" type="text"/></td>
</tr>
<tr>
<th>이메일</th>
<td><input name="email" type="email"/></td>
</tr>
<tr>
<th>성별</th>
<td>
<input type="radio" name="gender" value="남"/>남자
<input type="radio" name="gender" value="여"/>여자
</td>
</tr>
<tr>
<th>나이</th>
<td>
<input type="number" min="20" max="100" value="20"/>
</td>
</tr>
<tr>
<th colspan="2">
<button onclick="save()">회원가입</button>
</th>
</tr>
</table>
</body>
<script>
async function save(){
let param = {};
param.id = $('input[name="user_id"]').val();
param.pw = $('input[name="user_pw"]').val();
param.name = $('input[name="user_name"]').val();
param.email = $('input[name="email"]').val();
param.age = $('input[type="number"]').val();
param.gender = $('input[name="gender"]:checked').val();
console.log(param);
let {data}= await axios.post('/join',param);
};
//비동기 방식으로 답을 기다리는동안 다른작동을 할수 있게
async function overlay(){
let id = $('input[name="user_id"]').val();
console.log('id : '+id);
// 반환된 값에서 data 부분을 찾아서 넣는다.(obj.data)
// 비구조 할당으로 오브젝트에 데이터를 받아온다
//오버레이 요청리퀘스트 아이디는 파라미터
let {data} = await axios.get('/overlay?id='+id);
console.log(data);
if(data.use == 0){
$('#overlay').html('사용 가능한 아이디 입니다.');
$('#overlay').css({'color':'green'});
}else{
$('#overlay').html('사용 중인 아이디 입니다.');
$('#overlay').css({'color':'red'});
}
}
</script>
</html>
#DB 접속 관련 내용
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
id="web_user"
pw="pass"
host="localhost"
port=3306
database="mydb"
url=f'mysql+pymysql://{id}:{pw}@{host}:{port}/{database}'
#엔진생성
engine=create_engine(
url=url,
echo=True, #echo 쿼리 출력 여부
pool_size=5 #커넥션 풀 사이즈
)
#세션생성
session=sessionmaker(bind=engine)
#데이터베이스 객체 생성
def get_db():
return session()
fastapi
uvicorn
pymysql
sqlalchemy
#pip install -r requirement.txt
우리가 지금 회원가입 페이지를 만들었는데
거기에 두가지 핵심 기능인 아이디 중복확인과 회원정보 저장을 담고 있다.
그런데 제이쿼리와 엑시오스라는 도구를 사용해서 서버와 대화하고 있다고보면된다.
오버레이 는 사용자가 아이디를 입력했을때 이미 누가 쓰고 있는지 확인하는 기능이다.
아이디를 가져오기 위해서 입력창에 유저아이디 타이핑한 글자를 변수 아이디에 담고
서버에 물어본다 이 아이디 쓰는 사람 있냐
답변확인한다. 데이타 유즈로 0 이면 사용가능 그외이면 사용중이다.
세이브는 회원가입 신청서 제출 그러니까 정보를 저장하는역할이다.
파람은 짐싸는것 아이디,비밀번호 성별 나이를 하나의 보따리 인 파라미터에 담어서
파람에이지는 숫자입력창에서 가져오고 파람젠더는 체크된 항목을 가져온다.
로그는 개발자 도구 창에서 데이터가 잘 담겻는지 확인하는 과정
전송하기 엑시오스 포스트 조인 파람을 통해 조인이라는 주소로 이 파람을 보내고
이제 서버가 데이터를 받아서 디비 데이터베이스에 저장을 한다.
자바스크립트 그러니까 프론트엔드의 요청을 받아주는 서버 백엔드의 내용이다.
파이썬의 패스트에이피아이를 통해 작성되었다.
사용자가 보낸 편지,요청을 읽고 창고,디비 에 가서 물건이 있는지 확인하고 새 물건을
저장하는 역할을 한다.
작성하신 코드는 웹사이트의 회원가입 페이지에서 흔히 쓰이는 두 가지 핵심 기능(아이디 중복 확인, 회원 정보 저장)을 담고 있습니다. jQuery와 Axios라는 도구를 사용해 서버와 대화하는 구조예요.
비전공자도 이해할 수 있게 비유를 들어 쉽게 설명해 드릴게요!
overlay() : "이 이름 써도 되나요?" (아이디 중복 체크)
사용자가 아이디를 입력했을 때, 이미 누가 쓰고 있는지 확인하는 기능입니다.
아이디 가져오기: 입력창(user_id)에 타이핑한 글자를 변수 id에 담습니다.
서버에 물어보기: axios.get('/overlay?id=' + id)를 통해 서버에 "이 아이디 쓰는 사람 있어?"라고 질문을 던집니다.
답변 확인 (data.use):
0이면 (사용 가능): 화면에 초록색 글씨로 "사용 가능한 아이디입니다."라고 띄워줍니다.
그 외 (이미 있음): 화면에 빨간색 글씨로 "사용 중인 아이디입니다."라고 경고를 줍니다.
save() : "회원가입 신청서 제출!" (정보 저장)
사용자가 입력한 모든 정보(아이디, 비번, 이름, 이메일 등)를 한데 모아서 서버로 전송하는 기능입니다
짐 싸기 (param): 아이디, 비밀번호, 성별, 나이 등을 하나의 보따리(param)에 차곡차곡 담습니다.
예: param.age는 숫자 입력창에서 값을 가져오고, param.gender는 체크된 항목을 가져옵니다.
확인용 로그: console.log(param)을 통해 개발자 도구창에서 데이터가 잘 담겼는지 슬쩍 확인해 봅니다.
전송하기: axios.post('/join', param)을 통해 서버의 /join이라는 주소로 이 보따리를 보냅니다. 이제 서버가 이 데이터를 받아서 DB(데이터베이스)에 저장하게 됩니다.
@app.get("/overlay") : "아이디 중복 확인 센터"
사용자가 "이 아이디(id) 쓸 수 있나요?"라고 물어볼 때 실행되는 부분입니다.
아이디 확인: 사용자가 보낸 id를 받습니다.
창고(DB) 뒤지기: SELECT COUNT(id)...라는 명령어로 DB에게 "이 아이디랑 똑같은 게 몇 개나 있어?"라고 물어봅니다.
결과 보고: * 이미 있으면 cnt가 1이 되고, 없으면 0이 됩니다.
마지막에 {'use': cnt}라고 답장을 보내줍니다. (앞서 본 JS 코드에서 이 값을 받아 "사용 중"인지 "사용 가능"인지 판단하는 거죠!)
뒷정리: 창고 문(conn.close())은 항상 꼭 닫아야 합니다.
@app.post("/join") : "회원 등록 접수처"
사용자가 입력한 회원가입 정보를 실제로 저장하는 곳입니다.
정보 뭉치 받기: info: Dict[str, Any]를 통해 사용자가 보낸 이름, 나이, 이메일 등이 담긴 보따리를 통째로 받습니다.
저장 명령 준비: INSERT INTO member...라는 명령어를 준비합니다. "이 정보를 회원 명부에 새로 적어 넣어!"라는 뜻입니다.
참고: 현재 코드에는 pass라고 적혀 있어 실제로 저장하는 실행문은 아직 비어 있네요. 여기에 conn.execute(sql, info) 같은 코드가 들어가야 진짜로 저장이 완료됩니다.
@app.get("/"): 누군가 홈페이지 주소로 딱 들어오면, 자동으로 /view/index.html(가입 화면)로 길을 안내(Redirect)해줍니다.
app.mount("/view", ...): "view"라는 폴더 안에 있는 이미지나 HTML 파일들을 웹브라우저가 볼 수 있도록 공개해두는 설정입니다.
| overlay | 아이디 중복 확인 | 도서관에서 "이 자리 비어있나요?" 물어보기 |
| save | 회원가입 완료 | 작성한 가입 신청서를 접수처에 제출하기 |
핵심 요약 (흐름도)
- 사용자: 아이디 입력 후 중복 확인 버튼 클릭!
- JS (브라우저): axios.get('/overlay?id=...') 호출
- Python (서버): /overlay 함수 실행 → DB 조회 → 결과 전송
- 사용자: 회원가입 버튼 클릭!
- JS (브라우저): axios.post('/join', param) 호출
- Python (서버): /join 함수 실행 → DB에 회원 정보 저장 (INSERT)