[03] - 데이터베이스 연동, 캐릭터 생성을 특별한 이벤트로만 가능하게 해보자! [출처] [03] - 데이터베이스 연동, 캐릭터 생성을 특별한 이벤트로만 가능하게 해보자!|작성자 enoch_rvn
안녕하세염! 에노기에염.
이번에 들고온건 뭐 다름아닌 데이터베이스 + 소스와 스크립트를 연동하여
특별한 이벤트(아이템스크립트, 혹은 엔피시 스크립트 등) 으로 캐릭터잠금을 해제하는
그런 시스템을 개발하며 배워볼까합니다.
자 그럼 바로 강의 들어가도록하겠습니다.
일단 데이터베이스를 열어주시고(브라우져)

accounts 오른쪽클릭, Edit Table 에 들어가줍니다. (artlexonline 은 데이터베이스의 이름입니다)

이렇게 설정창이뜨는데, 여기서 추가해주셔야할것은 테이블 이름입니다!
Column Name 부분에 xxx이름 을 작성해주세요.
앞부분은 왜 같게하느냐 하면, 소스부분에서 코딩할때에 사용 자원을 줄이기 위함입니다.
이 부분은 나중에 보기로하고, 이제 DataType, notnull, autoinc, flags, default value, comment 의 역할을 설명해드리도록 할게요!
DataType = 말그대로 데이타의 형식입니다. 형식은 엄청 많이 존재합니다.
아는대로(쓰이는대로) 말씀해드리자면
INTEGER(길이) = 숫자형 테이블. 보통 INTEGER 을 선언하면 -21억4천만... ~ 21억4천만.. 까지의 숫자를 저장할 수 있다. (총 대략 43억)
VARCHAR(길이) = String 형이라고 볼 수 있다. 문자를 집어넣으며, 인코딩을 바르게 설정해주어야 한글이 제대로 들어간다. 스크린샷 하단에보면, Column Details 에서, Column CharSet 이란 메뉴가 있는데, 그 부분에서 euc-kr 을 선택해주어야하며, Default Value에 null을 작성해주어야한다.
(default value 가 없으면 오류남)
TEXT = 길이가 무제한급인 엄청난 용량의 컬럼. 보통 채팅로그나, 임의로 길게 변경될 수 있는 컬럼에 해당한다. (게시판작성 등) VARCHAR 과 속성이 비슷하다.
TINYINT = 정말 작은 값을 사용할때 데이터베이스의 구조를 최소화시키기위해 사용되는 타입.
TINYINT(1) 로 선언해주면, 0과 1 즉 TRUE/FALSE 만 설정하기에 가장 적합한 구조가된다.
하지만 에러로인하여 2자리수가 들어간다고 가정하면 데이터베이스에서 나는 오류인지 몰라
디버깅이 힘들게 될 상황을 우려해서 TINYINT 는 (2) 로 잡아주는게 좋다.
TIMESTAMP = 날짜 계산 함수들이 상용화되며 사라져가고있는 추세다. 날짜를 담아주는 데이터 타입이며, 요즘은 그냥 VARCHAR로 자유성있게 사용한다.
-----------------------------------------------------------------------------------------
NOT NULL = 즉 무조건 값이 있어야한다는 뜻입니다. NOT NULL 을 선택해주면, Default Value 에 값을 넣어주시는걸 추천해드립니다.
-----------------------------------------------------------------------------------------
AUTOINC = 무조건 값이 증가하는 옵션입니다. INTEGER 에서만 사용되며(다른곳에서 사용하긴 하지만 뭐..) 보통 index 를 설정할때 편리하게 사용합니다. (중간에 값이 지워졌을경우 중간의 값을 채워넣지 않고, 계속 값을 증가시킵니다)
-----------------------------------------------------------------------------------------
Flags : UNSIGNED = 앞서 말씀드렸는데 INTEGER 혹은 TINYINT 같은 경우 -부터 값이 시작됩니다.
하지만 -를 삭제(?) 하며 그 값만큼 넓이를 증가시킵니다.
ex) INTEGER : -21억4천만... ~ 21억4천만... 을 0~43억
ex) TINYINT : -255 ~ 255 를 510
이런식으로 어.. 뭐랄까 -값을 안쓰는경우 체크해주시는게 좋아요.
BINARY = 몰랑..
ZEROFILL = 일단, INT(3) 이 컬럼을 보도록합시다.
이것은 0~3 을 표현하는 식이 아니라, 0~999까지를 표현하는겁니당.
즉 3자리 수까지를 표현하라~ 뜻이에요.
INT(5) 면, 당연히 99,999 까지 들어간다는것이죵.
자 그러면 ZEROFILL 은 어떤 설정이냐 하면
INT(3) 으로 설정하고 값에 6이 들어갔어요. 그러면 출력되는 값이
006 이 됩니다. 12가 들어가면 012가 되구요.
이해하셨나용? 다시 INT(5) 로 설정하시고 3을넣으면
00003 이 들어갑니다.
길이의 나머지에 0을 채운다는 뜻이지요.
-----------------------------------------------------------------------------------------
Default Value = 값이 아무것도 들어가지 않았을때 출력되는 초기값.
-----------------------------------------------------------------------------------------
Comment = 아무 역할도 안해요. 이 컬럼이 무엇을 하는지 작성해놓습니당.
아이고 힘들당.
자 앞서 설명때문에 accounts 테이블에 컬럼 만들어주시는거 잊지마세요!
데이터타입은 TINYINT(2), NOT NULL 체크해주시고, Default Value : 0 으로 해주시면되겠스민당.
컬럼명은 예를 한번 들어보겠습니다.
templeKazior
templeEvan
templeAran
알아볼수있지만, 어느 특정 길이까지는 중복있게 해주셔야합니당.
여튼 테이블 수정이 완료되었으면, 이제 소스코드를 짜볼 시간입니다! 짞짞

자 메이플클라이언트.java 부분입니다!
뭐 메서드명은 알아서 해주시고, int 형 메서드를 만들어보겠습니당.
public int canCreateTempler(int Type) {
// 0 = 아란
// 1 = 에반
// 2 = 은월
// 3 = 카이저
// 4 = 엔젤릭
String temple = "";
int result = 0;
switch (Type) {
case 0:
temple = "templerWarrior";
break;
case 1:
temple = "templerDragon";
break;
case 2:
temple = "templerWolf";
break;
case 3:
temple = "templerKaizer";
break;
case 4:
temple = "templerAngel";
break;
default:
System.out.println("[디버깅] 인자값이 잘못됨 canCreateTempler()");
break;
}
try {
Connection con = MYSQL.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT a." + temple + " FROM accounts a INNER JOIN characters c ON a.id = c.accountid WHERE a.id = ?");
ps.setInt(1, accId);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
result = rs.getInt(temple);
}
rs.close();
ps.close();
} catch (SQLException e) {
System.err.println("error loading characters internal" + e);
}
return result;
}
대충 이해가 가시나요?
이번 소스코드는 두 구역을 나누어서 강좌하도록 하겠습니다.
String temple = "";
int result = 0;
switch (Type) {
case 0:
temple = "templerWarrior";
break;
case 1:
temple = "templerDragon";
break;
case 2:
temple = "templerWolf";
break;
case 3:
temple = "templerKaizer";
break;
case 4:
temple = "templerAngel";
break;
default:
System.out.println("[디버깅] 인자값이 잘못됨 canCreateTempler()");
break;
}
첫번째는 이구역인데요, 바로 Switch Case 문이 나옵니다!
이 부분은 뭐냐, Switch 인자값으로 들어간 변수에 특정한 값이 있으면 이벤트 처리, 혹은 설정된 특정한 값 이외의 값이 있으면 이외의 값대로 묶어서 처리하는 개 꿀 함수임니덩.
오 이것만 들으셔도 이해하셨을 머리라고 생각합니다. Type 는 인자값이였고,
Case 0 이면 인자값에 0이들어오면 Temple 이란 String 형 변수에 값을 넣네.
응? 근데 저 temple 변수에 들어가는 값 이름이 어디서 많이 본것같은데.. 하시면 잘 생각하셨습니다. 저 변수에 들어가는것은 방금 저희가 테이블에 추가시킨 컬럼 이름입니다.
왜 굳이 저런짓을하느냐 하면, 데이터베이스는 굉장히 예민한부분이기때문에 한번에 많은 명령문을 호출하게되면 자원 소모량이 엄청나게됩니다. 따라서 자신의 상황이 어떤 상황인지 먼저 판단하여 쿼리문을 최소화시켜 전송하는게 가장 중요한것이라고 생각하시면됩니다.
자 뭐 default 는 딱 봐도 아시겠지만 0~4 이외의 값이 들어오면 잘못됬다고 에러띄워주는거구용!!!
----------------------------------------------------------------------------------------
이제 그분이 오셨습니다.
try {
Connection con = MYSQL.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT a." + temple + " FROM accounts a INNER JOIN characters c ON a.id = c.accountid WHERE a.id = ?");
ps.setInt(1, accId);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
result = rs.getInt(temple);
}
rs.close();
ps.close();
} catch (SQLException e) {
System.err.println("error loading characters internal" + e);
}
return result;
}
여기서 잠깐, try { } catch () { 가 뭘까요?
바로, 예외가 발생하여도~ 라는 뜻입니다.
데이터베이스 작업할때에는 많은 예외상황들이 존재합니다.
그렇기때문에 데이터베이스 작업에는 무조건적인 try catch 문법으로 묶어줘야합니다(?)
try { 소스 } 부분에는, 그냥 평소대로 진행합니다. 소스코드를.
하지만 catch 부분에서는 , try 안에 묶여있는 소스에 예외적인 오류가 발생했을때 에러를 띄워주고 함수를 중지시킵니다. 그냥 그렇게 알구이써염 ㅋ
이제 Connection con = MYSQL.getConnection(); 부분을 보실까요.
볼 필요 없습니다. 그냥 con 이란 변수는 마이쿼리의 연결자라고 보시면되요.
PreparedStatement os = con.pre... 볼 필요 없습니다.
어차피 복붙하실거잖아요. (찡긋) 당신들으 봐야할것은 여기에 나오는 쿼리 문법입니다.
("SELECT a." + temple + " FROM accounts a INNER JOIN characters c ON a.id = c.accountid WHERE a.id = ?");
왜이렇게 복잡하게 해두셨지? 뭐지 저건? 이러시는분들 많을것같은데.. 음 예외상황이 발생할것같아서 캐릭터 테이블이랑 연결시켜놨었습니다.
아래로 수정해주세요.
("SELECT " + temple + " FROM accounts WHERE id = ?");
오 졸라간단하죠?
SELECT 는 참고하다, 보다 이런겁니다. 어디서? FROM accounts 즉 어카운트 테이블에서 본데요. 어떤 컬럼을? temple 변수에 저장되있는 컬럼을 본답니다.
어 그럼 누구껄? id가 ?인것.
응 ?가 뭔데요?
ps.setInt(1, accId);
네 ?는 계정아이디입니다.
("SELECT ? FROM accounts WHERE id = ?");
ps.setInt(1, temple);
ps.setInt(2, accId);
이렇게 하셔도 무방합니다. '?' 의 뜻을 아시겠나요?
ResultSet rs = ps.executeQuery();
while (rs.next()) {
result = rs.getInt(temple);
}
rs.close();
ps.close();
rs 는 ps의 담겨있는 쿼리문을 실행하고 값을 받아오는 역할을합니다.
while (rs.next()) { 는 rs에 받아온값이 더이상 없을때까지 반복
result = rs.getInt(temple); 는 result 에다가 temple 변수에 담겨있는 컬럼명의 값을 INT 형으로 받아온 값을 담는 부분임다.
rs.close();
ps.close();
con.close();
rs와 ps, 그리고 커넥션이 열려있으니 닫아주셔야죠!
이 부분을 닫아주지않아, (닫히지않아) 투매니 커넥션이 발생하던 점이 있었습니다. (65 팩들 기준)
꼭 닫으세요.
허허 이제 canCreateTempler() 란 메서드를 MapleClient.java 에 만들어두었군요!
음, 이제 다음편에서 계속됩니다!
[출처] [03] - 데이터베이스 연동, 캐릭터 생성을 특별한 이벤트로만 가능하게 해보자!|작성자enoch_rvn

원나소년 님의 최근 댓글
초보 개발자도 가능합니까? 아직 개발의 ㄱ자도 모르긴하는데.. 2016 06.07 구축하기 쉬운가용? 2016 06.02 흑 ㅜㅜ 팩을 구하고싶은데 ㅠㅠ 구글링하면 나오려나요?... 2016 06.02 라피스 해보고싶네요 정말 어떻게못하나요... 2016 05.31 하핳... 그런게임들은 프리서버 못하는건가요? 2016 05.31