전체 글 (135)

728x90

 어제 회의를 통해 무엇을 할 지 정확하게 정했고, 각자 맡은 부분에서 필요한 컬럼과 과제가 컬럼 30개였으니 추가적으로 넣을 컬럼을 고른 다음에서야 데이터를 뽑기 시작해서 데이터를 뽑는 것으로 끝났다.
 각자 티어를 맡아 데이터를 받아오고, 나중에 받아온 데이터들을 cvs 파일로 공유하기로 해서 나는 내 노트북으로는 다이아, 학원에서 내 자리의 컴퓨터로는 브론즈를 받아오기로 했는데 노는 api키가 없어서 브론즈는 오늘 학원에 가서 급하게 조금 받아왔다. (그래서 다이아는 전처리 없이 10만 데이터인데 브론즈는 전처리 없이 3만 데이터였다..내일 마무리 작업 전에 브론즈는 조금 더 받아와야겠다.)

내가 맡은 부분: 
 데이터 티어: 다이아 / 브론즈
 시각 데이터: 닉네임 길이 별 승률 / 퍼블이 가장 많이 나오는 라인
(추가적으로 팀원이랑 PPT 작업도 같이 했다.)

 

1. 연습용: 다이아로만 시각화 해보기

 1-0) 시작 전

더보기
import my_utils as mu
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
import seaborn as sns
from matplotlib.gridspec import GridSpec
  • import

font_path = "C:/Windows/Fonts/gulim.ttc"
font = font_manager.FontProperties(fname=font_path).get_name()
rc('font', family=font) # 윈도우
  • 차트에 한글로 작성 시 깨지지 않게 하기 위한 설정

conn = mu.connect_mysql()
query = 'select * from lol_datas where tier="DIAMOND"'
df = pd.DataFrame(mu.sql_execute_dict(conn,query))
conn.close()
  • DB에 넣어둔 데이터를 불러와 데이터 프레임으로 저장

 

 1-1) 닉네임 길이 별 승률

더보기
tnw_df = df[['tier','summonerName','win']]
tnw_df = pd.DataFrame(tnw_df[tnw_df.summonerName.str.len()!=0])
tnw_df['sNameLen'] = tnw_df['summonerName'].str.len()
tnw_df['cnt'] = 1
tnw_df = tnw_df[['tier','summonerName','sNameLen','win','cnt']]
tnw_df['win'] = tnw_df.apply(lambda x: 1 if x.win=='True' else 0,axis=1)
가린 부분은 유저들 닉네임이다.

tnw_df2 = tnw_df[['sNameLen','win','cnt']].groupby(['sNameLen']).sum()
tnw_df2['oow'] = round((tnw_df2['win']/tnw_df2['cnt'])*100,2)
oow = 승률

list_x = [3,4,5,6,7,8,9,10,11,12,13,14,15,16]
list_y = tnw_df2['oow']
plt.bar(list_x, list_y,
         color='skyblue')
plt.xticks(list_x)
plt.yticks([0,20,50,80])

for i, v in enumerate(list_x):			# 막대 바에 값 입력
    plt.text(v, y[i], y[i],                 # 좌표 (x축 = v, y축 = y[0]..y[1], 표시 = y[0]..y[1])
             fontsize = 9, 
             color='black',
             horizontalalignment='center',  # horizontalalignment (left, center, right)
             verticalalignment='bottom')    # verticalalignment (top, center, bottom)

plt.grid(False)
  • 컬럼을 그룹바이하면서 인덱스로 만들었는데 이걸 푸는 방법을 몰랐어서 직접 적었으나 인덱스를 풀면 컬럼으로 y입력이 가능해서 노가다 없이 편하게 할 수 있다..
  • 인덱스 풀기: 데이터프레임명.reset_index()

 

 1-2) 퍼블이 가장 많이 나오는 라인

더보기
fbl = df[['gameId','championName','teamPosition','firstBloodKill']]
fbl['firstBloodKill'] = fbl.apply(lambda x: 1 if x.firstBloodKill=='True' else 0,axis=1)
가린 부분은 게임 아이디와 유저들 닉네임이다.

fblC = fbl[['teamPosition','firstBloodKill']].groupby(['teamPosition']).sum()

plt.figure()
wedgeprops={'width': 0.7, 'edgecolor': 'w', 'linewidth': 5}
plt.pie(fblC['firstBloodKill'], labels = ['지워야하는데이터','BOTTOM',' JUNGLE','MIDDLE','TOP','UTILITY'], autopct ='%1.1f%%',
       explode = (0,0,0,0,0,0), colors = ['lightblue','lightpink','#87c1e9','#84c07a','#3a8299','#5b6078'], wedgeprops=wedgeprops)
plt.legend(loc='lower right', bbox_to_anchor=(1.4,0.8))

plt.title('퍼블 라인 파이차트')
plt.grid(True)
  • 전처리를 하지 않았기 때문에 지워야하는 빈 칸의 데이터가 존재했다. (라인이 존재하지 않는 게임)

 

 

2. 시각화 (충분하게 데이터를 가져오지 못했기 때문에 다이아 외엔 데이터가 적은 수로 진행했다.)

 2-0) 시작 전

더보기
import my_utils as mu
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
import seaborn as sns
from matplotlib.gridspec import GridSpec
import numpy as np

font_path = "C:/Windows/Fonts/gulim.ttc"
font = font_manager.FontProperties(fname=font_path).get_name()
rc('font', family=font) # 윈도우

def dfc(tier):
    query = f'select * from lol_datas where tier="{tier}"'
    return pd.DataFrame(mu.sql_execute_dict(conn,query))
conn = mu.connect_mysql()
tiers = ['BRONZE','SILVER','GOLD','PLATINUM','DIAMOND']
br = dfc('BRONZE')
si = dfc('SILVER')
go = dfc('GOLD')
pl = dfc('PLATINUM')
di = dfc('DIAMOND')
conn.close()
  • 가린 부분은 게임 아이디, 게임시간, 게임버전, 유저들 닉네임이다.

 

 2-1) 닉네임 길이 별 승률

  • for문으로 돌리려고 했는데 시행착오를 거쳤음에도 방법을 찾지 못했다..
더보기
brDF = br[['tier','summonerName','win']]
brDF = pd.DataFrame(brDF[brDF.summonerName.str.len()!=0])
brDF['sNameLen'] = brDF['summonerName'].str.len()
brDF['cnt'] = 1
brDF = brDF[['tier','summonerName','sNameLen','win','cnt']]
brDF['win'] = brDF.apply(lambda x: 1 if x.win=='True' else 0,axis=1)
brDF = brDF[['sNameLen','win','cnt']].groupby(['sNameLen']).sum()
brDF['oow'] = round((brDF['win']/brDF['cnt'])*100,2)

siDF = si[['tier','summonerName','win']]
siDF = pd.DataFrame(siDF[siDF.summonerName.str.len()!=0])
siDF['sNameLen'] = siDF['summonerName'].str.len()
siDF['cnt'] = 1
siDF = siDF[['tier','summonerName','sNameLen','win','cnt']]
siDF['win'] = siDF.apply(lambda x: 1 if x.win=='True' else 0,axis=1)
siDF = siDF[['sNameLen','win','cnt']].groupby(['sNameLen']).sum()
siDF['oow'] = round((siDF['win']/siDF['cnt'])*100,2)

goDF = go[['tier','summonerName','win']]
goDF = pd.DataFrame(goDF[goDF.summonerName.str.len()!=0])
goDF['sNameLen'] = goDF['summonerName'].str.len()
goDF['cnt'] = 1
goDF = goDF[['tier','summonerName','sNameLen','win','cnt']]
goDF['win'] = goDF.apply(lambda x: 1 if x.win=='True' else 0,axis=1)
goDF = goDF[['sNameLen','win','cnt']].groupby(['sNameLen']).sum()
goDF['oow'] = round((goDF['win']/goDF['cnt'])*100,2)

plDF = pl[['tier','summonerName','win']]
plDF = pd.DataFrame(plDF[plDF.summonerName.str.len()!=0])
plDF['sNameLen'] = plDF['summonerName'].str.len()
plDF['cnt'] = 1
plDF = plDF[['tier','summonerName','sNameLen','win','cnt']]
plDF['win'] = plDF.apply(lambda x: 1 if x.win=='True' else 0,axis=1)
plDF = plDF[['sNameLen','win','cnt']].groupby(['sNameLen']).sum()
plDF['oow'] = round((plDF['win']/plDF['cnt'])*100,2)

diDF = di[['tier','summonerName','win']]
diDF = pd.DataFrame(diDF[diDF.summonerName.str.len()!=0])
diDF['sNameLen'] = diDF['summonerName'].str.len()
diDF['cnt'] = 1
diDF = diDF[['tier','summonerName','sNameLen','win','cnt']]
diDF['win'] = diDF.apply(lambda x: 1 if x.win=='True' else 0,axis=1)
diDF = diDF[['sNameLen','win','cnt']].groupby(['sNameLen']).sum()
diDF['oow'] = round((diDF['win']/diDF['cnt'])*100,2)

name = [3,4,5,6,7,8,9,10,11,12,13,14,15,16]
# 그림 사이즈, 바 굵기 조정
fig, ax = plt.subplots(figsize=(12,6))
bar_width = 0.15

# 닉네임 길이 개수
index = np.arange(14)

# 바
b1 = plt.bar(index, brDF['oow'], bar_width, alpha=0.4, color='brown', label='Bronze')
b2 = plt.bar(index + bar_width, siDF['oow'], bar_width, alpha=0.4, color='silver', label='Silver')
b3 = plt.bar(index + 2 * bar_width, goDF['oow'], bar_width, alpha=0.4, color='Gold', label='Gold')
b4 = plt.bar(index + 3 * bar_width, plDF['oow'], bar_width, alpha=0.4, color='#287a86', label='Platinum')
b5 = plt.bar(index + 4 * bar_width, diDF['oow'], bar_width, alpha=0.4, color='#316bd1', label='Diamond')

plt.xticks(np.arange(bar_width, 14 + bar_width, 1), name)
plt.ylim(0,100)

# x축, y축 이름 및 범례 설정
plt.xlabel('닉네임 길이', size = 14)
plt.ylabel('승률', size = 13)
plt.legend(labels=['Bronze','Silver','Gold','Platinum','Diamond'], loc='lower right', bbox_to_anchor=(1.15,0.75))
plt.grid(False)
  • 바에 값을 적는건 어째서인지 자꾸 에러가 나서 지웠더니 에러가 사라졌다..ㅠㅠ

 

 2-2) 퍼블이 가장 많이 나오는 라인

더보기
fbr = br[['gameId','championName','teamPosition','firstBloodKill']]
fbr['firstBloodKill'] = fbr.apply(lambda x: 1 if x.firstBloodKill=='True' else 0,axis=1)
fbr = fbr[['teamPosition','firstBloodKill']].groupby(['teamPosition']).sum()

fsi = si[['gameId','championName','teamPosition','firstBloodKill']]
fsi['firstBloodKill'] = fsi.apply(lambda x: 1 if x.firstBloodKill=='True' else 0,axis=1)
fsi = fsi[['teamPosition','firstBloodKill']].groupby(['teamPosition']).sum()

fgo = go[['gameId','championName','teamPosition','firstBloodKill']]
fgo['firstBloodKill'] = fgo.apply(lambda x: 1 if x.firstBloodKill=='True' else 0,axis=1)
fgo = fgo[['teamPosition','firstBloodKill']].groupby(['teamPosition']).sum()

fpl = pl[['gameId','championName','teamPosition','firstBloodKill']]
fpl['firstBloodKill'] = fpl.apply(lambda x: 1 if x.firstBloodKill=='True' else 0,axis=1)
fpl = fpl[['teamPosition','firstBloodKill']].groupby(['teamPosition']).sum()

fdi = di[['gameId','championName','teamPosition','firstBloodKill']]
fdi['firstBloodKill'] = fdi.apply(lambda x: 1 if x.firstBloodKill=='True' else 0,axis=1)
fdi = fdi[['teamPosition','firstBloodKill']].groupby(['teamPosition']).sum()

# 그리드 스펙 설정
gs = GridSpec(3, 3)
# 이미지 사이즈 설정
fig = plt.figure(figsize=(15, 15))

# 크기와 위치가 다른 서브플롯 생성
ax1 = fig.add_subplot(gs[1, 0])
ax2 = fig.add_subplot(gs[1, 1])
ax3 = fig.add_subplot(gs[2, 0])
ax4 = fig.add_subplot(gs[2, 1])
ax5 = fig.add_subplot(gs[2, 2])

wedgeprops={'width': 0.7, 'edgecolor': 'w', 'linewidth': 5} # 파이차트를 부채꼴로 만듦

ax1.pie(fbr['firstBloodKill'], autopct ='%1.1f%%',
       explode = (0,0,0,0,0,0), colors = ['lightblue','lightpink','#87c1e9','#84c07a','#3a8299','#5b6078'], wedgeprops=wedgeprops)
ax2.pie(fsi['firstBloodKill'], autopct ='%1.1f%%',
       explode = (0,0,0,0,0,0), colors = ['lightblue','lightpink','#87c1e9','#84c07a','#3a8299','#5b6078'], wedgeprops=wedgeprops)
ax3.pie(fgo['firstBloodKill'], autopct ='%1.1f%%',
       explode = (0,0,0,0,0,0), colors = ['lightblue','lightpink','#87c1e9','#84c07a','#3a8299','#5b6078'], wedgeprops=wedgeprops)
ax4.pie(fpl['firstBloodKill'], autopct ='%1.1f%%',
       explode = (0,0,0,0,0,0), colors = ['lightblue','lightpink','#87c1e9','#84c07a','#3a8299','#5b6078'], wedgeprops=wedgeprops)
ax5.pie(fdi['firstBloodKill'], autopct ='%1.1f%%',
       explode = (0,0,0,0,0,0), colors = ['lightblue','lightpink','#87c1e9','#84c07a','#3a8299','#5b6078'], wedgeprops=wedgeprops)


ax1.set_title('브론즈')
ax2.set_title('실버')
ax3.set_title('골드')
ax4.set_title('플래티넘')
ax5.set_title('다이아')


plt.legend(labels=['지워야함','BOTTOM','JUNGLE','MIDDLE','TOP','UTILITY'], loc='lower right', bbox_to_anchor=(0.7,1.6))
plt.show()
  • 전처리를 하지 않았기 때문에 지워야하는 빈 칸의 데이터가 존재했다. (라인이 존재하지 않는 게임)

 


 

참고한 글 링크 목록

 


 

728x90

'프로그래밍 > +a' 카테고리의 다른 글

slPro 5차 일지  (0) 2024.01.09
slPro 4차 일지  (1) 2024.01.08
slPro 3차 일지  (0) 2024.01.01
미니 팀 프로젝트 사전 준비 (파이썬)  (2) 2024.01.01
slPro 2차 일지  (0) 2023.12.28
728x90

29일 작업을 오늘에서야 정리해서 올리게 되었다.
새해부터 파이썬, 스프링을 조금씩 깔짝거리면서 일지를 적고있다..!
올해는 열심히 번아웃?없이 코딩 공부할 수 있으면 좋겠다!
Happy New Year!


1차 일지 - [ 설정 ], [ 회원가입 ]
2차 일지 - [ 로그인 ]


3차에 한 것:
세션에 저장된 아이디가 있으면 display none/block하고 p태그 내용 바꾸기
로그아웃

 

1. 세션에 저장된 아이디 확인 후  디스플레이 변경

 1-1) index.jsp > js

<script type="text/javascript">
	$(()=>{
		console.log('loginId: ${loginId}');
		let id = '${loginId}';
		if (id != ''){
			console.log('로그인 된 아이디 있음')
			document.getElementById("loginOffDiv").style.display = 'none';
			document.getElementById("loginOnDiv").style.display = 'block';
			$('#loginIdTest').html(id+"님");
		}else{
			console.log('로그인 된 아이디 없음')
			document.getElementById("loginOffDiv").style.display = 'block';
			document.getElementById("loginOnDiv").style.display = 'none';
		}
	})
</script>
  • 페이지가 로딩되면 먼저 실행하는 함수
  • 확인용으로 콘솔에 세션에 저장된 loginId를 출력해 확인했다.
  • loginId의 값을 id라는 변수에 저장해두고, if문을 돌려 id가 공란인지 아닌지 확인하여 id가 loginOffDiv와 loginOnDiv인 것을 각 상황에 맞게 display를 none, block해준다.

 

 1-2) index.jsp > body

menu1~4는 헤더 부분이다.

<body>
	<jsp:include page="./header.jsp"></jsp:include>

	<div class="allBigBox">

		<div class="btnDivBox"
			style="width: 200px; height: 140px; float: right; margin: 40px 30px 0px 0px; text-align: center;">
			<div id="loginOffDiv" style="display: block;">
				<div style="display:table; width: 200px; height: 70px; background-color: #f8d77d; border: 1px solid black;"
					onclick="location.href='/member/joinfrm'">
					<button class="btn btn-3 btn-3e"
						style=" text-align: center;">join</button>
				</div>
				<div style="display:table; width: 200px; height: 70px; background-color: #f8d77d; border: 1px solid black;"
					onclick="location.href='/member/loginfrm'">
					<button class="btn btn-3 btn-3e"
						style=" text-align: center;">login</button>
				</div>
			</div>
			<div id="loginOnDiv" style="display: none;">
				<div style="background-color: #f8d77d; text-align: center; border: 1px solid black;">
					<p id="loginIdTest" style="padding: 20px 0px 0px; margin: 0px 0px 6px;">test님</p>
					<p style="padding: 0px 0px 20px; margin: 6px 0px 0px;">환영합니다.</p>
				</div>
				<div>
					<a href="/member/logout" style="padding: 5px 10px 10px 0px;; font-size: smaller; float: right; color: blue;">로그아웃</a>
				</div>
			</div>
		</div>
		
		<div class="main-contents" style="float: left; margin: 40px;">
			<div>
				여기에 뭔가 들어올 예정
			</div>
			<div>
				여기에 뭔가 들어올 예정2
			</div>
		</div>

	</div>
    
</body>
  • (style은 css로 따로 빼야하는데 나중에 천천히 옮기지 않을까 싶다.)
  • loginId가 있을 경우와 아닌 경우를 구분하여 div를 두 개 만들고 각 각 loginOffDiv, LofinOnDiv라는 아이디를 줘서 js로 제어할 수 있도록 한다.

 

 

2. 로그아웃

 2-1) index.jsp

<div id="loginOnDiv" style="display: none;">
	<div style="background-color: #f8d77d; text-align: center; border: 1px solid black;">
		<p id="loginIdTest" style="padding: 20px 0px 0px; margin: 0px 0px 6px;">test님</p>
		<p style="padding: 0px 0px 20px; margin: 6px 0px 0px;">환영합니다.</p>
	</div>
	<div>
		<a href="/member/logout" style="padding: 5px 10px 10px 0px;; font-size: smaller; float: right; color: blue;">로그아웃</a>
	</div>
</div>
  • 위 body 부분의 loginOnDiv
  • a 태그로 /member/logout으로 보낸다.

 

 2-2) MemberController.java

@GetMapping("/member/logout")
public String logout(Model model, HttpSession session) {
	session.removeAttribute("loginId");
	return "redirect:/";
}
  • 세션에 저장해둔 loginId를 삭제하고 index로 반환해준다.

 


 

728x90

'프로그래밍 > +a' 카테고리의 다른 글

slPro 4차 일지  (1) 2024.01.08
미니 팀 프로젝트 중간 과정 (파이썬)  (1) 2024.01.03
미니 팀 프로젝트 사전 준비 (파이썬)  (2) 2024.01.01
slPro 2차 일지  (0) 2023.12.28
slPro 1차 일지  (1) 2023.12.27
728x90

lol 데이터를 이용해 미니 팀 프로젝트를 진행한다고 하셔서 하기에 앞서 내가 맡은 부분이 제대로 정보를 뽑을 수 있는 내용인지 대충이나마 확인하기 위해 혼자 대충 정보를 뽑아봤다.

확인만 한 것이기 때문에 완벽하게 끝낸 것이 아니라 사전 작업만 해둔 것이다.

 

1. 사전 준비

 1-1) import

import requests
import pandas as pd
from tqdm import tqdm
  • 확인용 테스트이기 때문에 따로 함수들을 빼두진 않았다.
  • 받아오기 위한 requests
  • 데이터프레임을 만들기 위한 pandas(알리어스를 이용해 pd로 바꿈)
  • 체크용 tqdm(간략화하여 사용하기 위해 from ~ import를 사용하여 import했다.)

 

 

 1-2) 정보 받아오기

api = '(본인의 api key)'
  • lol 데이터를 받아오기 위해서는 riot api key가 필요한데, 이건 Riot Developer Portal 사이트에서 로그인(riot 계정이 없다면 회원가입해야함) 후 요청하면 1~2일 내로 되는 것 허락해주는 것 같다.
 

Riot Developer Portal

About the Riot Games API With this site we hope to provide the League of Legends developer community with access to game data in a secure and reliable way. This is just part of our ongoing effort to respond to players' and developers' requests for data and

developer.riotgames.com

  • 나의 경우에는 다음 날 확인해보니 바로 허락해주면서 api key를 받을 수 있었다.

 

tiers = ['CHALLENGER','GRANDMASTER','MASTER','DIAMOND']
page = 1
top_tiers= []
top_nick_WL = []
  • tiers에는 정보를 상위 티어로만 가지고 올 것이라 티어 이름을 저장했다.
  • page는 가지고 올 정보의 페이지 수? 같은 것이라고 생각하고 있다. (정보의 양)
  • top_tiers, top_nick_WL은 각 각 모든 정보, 혹은 몇개의 정보를 담아두기 위해 만들어 두었다. (사실 이 부분은 모든 정보만 담아두고 따로 빼면 됐는데 당시에는 정보를 뽑는 것에 급급해 생각하지 못했다.)

 

for tier in tqdm(tiers):
    for p in range(page):
        print(tier)
        url = f'https://kr.api.riotgames.com/lol/league-exp/v4/entries/RANKED_SOLO_5x5/{tier}/I?page={p+1}&api_key={api}'
        req = requests.get(url).json()
        if req == '[]':
            print('pass')
            pass
        else:
            if len(req)>4:
                for i in range(len(req)):
                    top_tiers.append(req[i])
                    top_nick_WL.append([req[i]['tier'],req[i]['summonerName'],req[i]['wins'],req[i]['losses']])
  • url은 지금 상황에선 첫번째 for문에서 선언해도 되지만, 페이지 수가 달라질 경우를 대비하여 두번째 for문에서 위치하도록 했다.
  • 첫번째 for문은 미리 만들어둔 tiers에서 하나씩 꺼내도록 했고, 두번째 for문은 페이지 수 만큼 돌도록 했다.
  • 확인용으로 print를 이용하여 tier를 출력하도록 했다.
  • requests.get()을 통해 url에 저장한 링크에서 정보를 받아와 req에 저장했다. 뒤의 .json()을 통해 json으로 받아올 수 있었다.
  • 혹시라도 빈 값을 가져올 수도 있으니, 만약 req가 '[]'라면(비어있다면) pass를 출력하고 넘어가도록 했다.
  • 빈 값이 아니라면 다시 req의 사이즈가 4를 초과하는 경우만 걸렀다. (위의 if문으로 안 걸러지는건지 아닌지 이 if문이 없으면 에러가 났다. ㅠㅠ)
  • req의 사이즈만큼 for문을 돌려 미리 만들어둔 top_tiers, top_nick_WL에 각 각 담을 정보를 꺼내어 담았다.

 

 1-3) 데이터 프레임으로 만들기

all_df = pd.DataFrame(top_tiers)
tnw_df = pd.DataFrame(top_nick_WL, columns=['tier','summonerName','win','loss'])
  • top_tiers, top_nick_WL에 담아둔 데이터를 각 각 데이터 프레임으로 만들어 준다.
더보기
혹시 몰라서 데이터 일부는 모자이크 처리를 해두었다.
혹시 몰라서 데이터 일부는 모자이크 처리를 해두었다.
  • 만든 데이터 프레임은 이런 식으로 나온다.

 

 1-4) 컬럼 추가 후 값 입력

tnw_df['suNameLen'] = tnw_df['summonerName'].str.len()
tnw_df = tnw_df[['tier','summonerName','suNameLen','win','loss']]
  • 컬럼을 추가하면서 컬럼의 값을 입력해줬다.
  • tnw_df['summonerName'].str.len()은 summonerName 컬럼 값의 문자열 길이를 나타낸다.
더보기
혹시 몰라서 데이터 일부는 모자이크 처리를 해두었다.
  • 결과는 이렇게 나온다.

 

정보들이 제대로 뽑히는 것을 확인 했으니 사전 작업은 끝났다!

 


 

728x90

'프로그래밍 > +a' 카테고리의 다른 글

미니 팀 프로젝트 중간 과정 (파이썬)  (1) 2024.01.03
slPro 3차 일지  (0) 2024.01.01
slPro 2차 일지  (0) 2023.12.28
slPro 1차 일지  (1) 2023.12.27
Java_주말 복습: 문제 다시 풀어보기  (0) 2023.10.01
728x90

 

내가 이것들을 써먹을 수 있을진 모르겠지만 언젠가를 위해 저장용으로 작성한다..!
나중에 천천히 추가할 예정

보통 무료지만 유료가 있을 수 있다.

 

 

아이콘

 

Font Awesome

 

Font Awesome

The internet's icon library + toolkit. Used by millions of designers, devs, & content creators. Open-source. Always free. Always awesome.

fontawesome.com

 

 

 


 

얼럿(alert) 창

 

sweetalert

 

SweetAlert2

SweetAlert2 - a beautiful, responsive, customizable and accessible (WAI-ARIA) replacement for JavaScript's popup boxes

sweetalert2.github.io

 

Dark Theme

  • 샘플도 있고, 테마 변경도 해볼 수 있다.

 

 


 

테마 / 템플릿

 

 

TEMPLATED - Free HTML and CSS Website Templates

Free HTML5 and CSS3 website templates. Our beautiful site templates are fully responsive and can be used for commercial purposes. Download now!

templated.co

 

  • 회원가입 필요없음!

 

 

 

Free HTML Website Templates - Freebiesbug

A curated selection of the best 119 free HTML website templates. Landing pages, portfolios, e-commerce, and much more.

freebiesbug.com

 

  • 회원가입 필요없음!

 

 

웹쟁이

 

웹쟁이 | 모든 웹 작품과 리소스가 한 곳에

웹쟁이 | 모든 웹 작품과 리소스가 한 곳에

www.webjangi.com

 

  • 다운받으려면 로그인 필요!

 

 


728x90

'프로그래밍 > +++++' 카테고리의 다른 글

단축키  (1) 2023.09.14
수업 시작 전 프로그램  (0) 2023.09.14
728x90

 오늘은 로그인까지만 시도했다.


1차 일지 - [ 설정 ], [ 회원가입 ]


23/12/29) 수정!

 

1. 로그인

로그인 창

 1-1) body

더보기

login.jsp

<div>
	<form id="loginfrm" method="post" action="/member/login">
		<div class="frm_item">아이디
			<input type="text" name="mId" class="input" placeholder="아이디를 입력하세요" maxlength="20" autocapitalize="off">
		</div>
		<div class="frm_item">비밀번호
			<input type="password" name="mPw" class="input" placeholder="비밀번호를 입력하세요" maxlength="20" autocapitalize="off">
		</div>
		<br>
		<button type="button" onclick="location.href='/'">메인화면</button>
		<button type="button" onclick="location.href='/member/joinfrm'">회원가입하러가기</button>
		<button type="submit" class="btn btn-3 btn-3e" id="loginSubBtn" style="text-align: center;">login!</button>
	</form>
</div>
  • div 아이디나 클래스명 지어주는 것을 잊어먹었다..
  • 버튼을 통해 메인화면으로, 혹은 회원가입하러 갈 수 있도록 해놨다.

 

 1-2) js

더보기

login.jsp

<script type="text/javascript">
	let m = "${msgFl}"
	if(m!=""){
		alert(m);
	}
</script>
  • 로그인에 실패하면 문구를 띄울 수 있도록 js를 추가했다.

 

 1-3) controller

더보기

MemberController

@GetMapping("/member/loginfrm")
public String login() {
	log.info("==> GetMapping - loginfrm 요청 <==");
	return "login";
}
@PostMapping("/member/login")
public String logrin(MemberDto mDto, RedirectAttributes ra, HttpSession session, Model model) {
	boolean result = mSer.login(mDto);
	if(result) {
		ra.addFlashAttribute("msgFl","로그인 성공!");
		session.setAttribute("loginId",mDto.getMId());
		return "redirect:/";
	}
	ra.addFlashAttribute("msgFl","로그인 실패");
	return "redirect:/member/loginfrm";
}
  • MemberService를 통해 login 메소드를 실행하고 성공여부를 boolean으로 받아와, if문을 돌린다.

 

 1-4) service

더보기

MemberService

public boolean login(MemberDto mDto) {
	log.info("===> mSer login 요청 <===");
	BCryptPasswordEncoder pwEn = new BCryptPasswordEncoder();
	String mPw = mDao.login(mDto.getMId());
	if(pwEn.matches(mDto.getMPw(), mPw)) {
		return true;
	}
	return false;
}
  • 인코딩했던 비밀번호를 디코딩할 수 없지만 비교할 수는 있다고 해서 다시 BCryptPasswordEncoder을 통해 입력받은 비밀번호와 아이디를 통해 검색해온 인코딩된 비밀번호가 같은지 비교하여 true, 아니면 false를 리턴해준다.

 

 1-5) dao

더보기
String login(String mId);
  • MemberDao

 

<select id="login" parameterType="String" resultType="String">
	select mPw from member where mId=#{mId}
</select>
  • MemberDao의 xml 파일 (mappers)

 

 

2. 결과

더보기
  • 로그인 실패 시

동기통신을 하며 얼럿창을 띄운다. (근데 이거 비동기로 확인하고 보내는 것도 나쁘지 않을듯..하다..아무것도 없는 화면에 저 얼럿창만 덜렁 나와있으니 뭔가..별로다ㅠㅠ)

 


 

틀리거나 헷갈렸던 점 메모

  • session에 아이디를 저장하는 방법을 실패한 것 같다..나중에 다시 해보기!
  • controller에서 Model을 안 받아와서 실패했었다. 넣어주니 잘 저장해옴..

 


 

728x90

'프로그래밍 > +a' 카테고리의 다른 글

slPro 3차 일지  (0) 2024.01.01
미니 팀 프로젝트 사전 준비 (파이썬)  (2) 2024.01.01
slPro 1차 일지  (1) 2023.12.27
Java_주말 복습: 문제 다시 풀어보기  (0) 2023.10.01
Java_주말 복습: 문제 다시 풀어보기  (0) 2023.10.01
1 2 3 4 5 6 ··· 27