출처 : PHPSCHOOL
<html>
<head>
<script language="javascript">
function init(){
var oRow = tbl.insertRow();
var oCell1 = oRow.insertCell();
oCell1.rowSpan="2";
var oCell2 = oRow.insertCell();
var oRow2 = tbl.insertRow();
var oCell3=oRow2.insertCell();
oCell1.innerHTML = "aaaa";
oCell2.innerHTML = "bbbb";
oCell3.innerHTML = "cccc";
}
</script>
</head>
<body onload="javascript:init();">
<table id="tbl" border=1>
<tr>
<td rowspan="2">rowspan2</td>
<td>1111</td>
</tr>
<tr>
<td>2222</td>
</tr>
</table>
</body>
</html>
2010년 11월 25일 목요일
2010년 11월 24일 수요일
[PHP] php에서 숫자표현할때 소수점 둘째자리까지만 나오게하는 방법은?
출처 : http://www.happyjung.com/gnuboard/bbs/board.php?bo_table=lecture&wr_id=275&sca=&sfl=&stx=&sst=wr_1&sod=desc&sop=&page=10
[ 방법1 ]
<?
$a=4.99*10;
echo sprintf("%2.2f" ,$a);
?>
%2.2f 부분이 실수형을 00.00식으로 표현하게 해줍니다.
%2.3f 는 00.000이겠죠?
[ 방법2 ]
숫자형으로 출력시 소수점과 1000단위 컴마 표시법
<?
$number = 1234.56;
// english notation (default)
$english_format_number = number_format($number);
// 1,234
// French notation
$nombre_format_francais = number_format($number, 2, ',', ' ');
// 1 234,56
$number = 1234.5678;
// english notation without thousands seperator
$english_format_number = number_format($number, 2, '.', '');
// 1234.57
?>
[ 방법1 ]
<?
$a=4.99*10;
echo sprintf("%2.2f" ,$a);
?>
%2.2f 부분이 실수형을 00.00식으로 표현하게 해줍니다.
%2.3f 는 00.000이겠죠?
[ 방법2 ]
숫자형으로 출력시 소수점과 1000단위 컴마 표시법
<?
$number = 1234.56;
// english notation (default)
$english_format_number = number_format($number);
// 1,234
// French notation
$nombre_format_francais = number_format($number, 2, ',', ' ');
// 1 234,56
$number = 1234.5678;
// english notation without thousands seperator
$english_format_number = number_format($number, 2, '.', '');
// 1234.57
?>
2010년 11월 12일 금요일
[자바스크립트] 문자열 자르기 (배열)
자바스크립트에서.. split 을 쓸경우..
var s_data = "2005-03-25"; // 잘라야 되는 값..
var array_data = s_data.split("-"); // split 함수사용..
var s_year = array_data[0]; // 잘라진 값 배열..
var s_month = array_data[1];
var s_day = array_data[2];
var s_data = "2005-03-25"; // 잘라야 되는 값..
var array_data = s_data.split("-"); // split 함수사용..
var s_year = array_data[0]; // 잘라진 값 배열..
var s_month = array_data[1];
var s_day = array_data[2];
2010년 11월 11일 목요일
PHP Ajax MySQL 로그인 중복체크
중복 중복 중복 ㅠㅠ;;
로그인 중복체크가 이렇게 어려울줄이야~~ 여러가지로 검색을 해보아도 나오지가 않아서 저 나름데로 짜집기(?)를 하여 중복체크 성공을하게되었습니다.
혹여나~ 다른곳에서 찾아헤메지마시고~ 제가 쓴방법을 한번 써보시기 바랄께요~~
p.s - 완벽하지는 않습니다. ㅡ,.ㅡ;;
웹 사용환경
서버 : CentOS 5.5
APM : Apache 2.2.14, PHP5.2.12, MySQL5.1.41
사용언어 : PHP, Ajax
아래에 붙여질 소스코드에 대해서는 제가 사용하는 환경의 소스를 그대로 올리도록 하겠습니다.
클래스화 시켜 사용하던건데 일일이 풀기가 애매하네요.. 기억도 안나고 ㅎㅎ;;;
기능 1 - 로그인전이면 새로 데이터를 입력한다. → 로그인처리
기능 2 - 로그인된상태일때 다른곳에서 로그인이되면 먼저 로그인된 페이지는 자동 로그아웃된다.
기능 3 - 같은 브라우져에서 로그인을 중복해서하게되면 로그인정보의 시간만 업데이트가된다.
1. 중복체크를할 테이블 생성
Table: smstmember_session
저는 위의 형식으로 테이블을 생성하였습니다. ^^
2. 로그인 처리페이지 소스 추가 (ex> login_ok.php)
또한 같은 세션ID일때 로그인을 다시하게되면 로그인 시간이 업데이트됩니다.
3. 로그아웃 처리하기 (ex> logout.php)
4. 중복 로그인 체크페이지 (ex> outlogin_check_session.php)
이 페이지에서는 세션DB의 값과 비교하기위한 정보들을 담고 있는다.
header 페이지나 footer 페이지 즉, 항상 웹페이지에 표시되는 부분에 추가하면 되겠다.
5. 중복 로그인 체크값 추출 (ex> login_check_tender.php)
다음으로 설명된 js 파일에서 위의 페이지에서 생성된 xml 코드를 참조하여 로그인여부를 체크하게된다.
6. 중복로그인 체크 및 처리하기 (ex> login_check.js)
다른곳에서 로그인이 이루어졌는지를 판단 및 처리를하게되는 스크립트이다.
다른곳 또는 다른 웹브라우저로 로그인을하게되면 기존에 로그인된 웹페이지는 자동적으로 로그아웃이 이루어지게된다.
여기까지 섭군이가 대충 짜집기한 중복로그인 방지 소스코드였습니다.
실질적으로 구상은 쉽게되는데 짜맞추려니... 여간 힘든게 아니네요 ㅠㅠ;;
질문은 않받을래요~ 머리가 뽀개질꺼 같거든요 ㅎㅎ;;;
로그인 중복체크가 이렇게 어려울줄이야~~ 여러가지로 검색을 해보아도 나오지가 않아서 저 나름데로 짜집기(?)를 하여 중복체크 성공을하게되었습니다.
혹여나~ 다른곳에서 찾아헤메지마시고~ 제가 쓴방법을 한번 써보시기 바랄께요~~
p.s - 완벽하지는 않습니다. ㅡ,.ㅡ;;
웹 사용환경
서버 : CentOS 5.5
APM : Apache 2.2.14, PHP5.2.12, MySQL5.1.41
사용언어 : PHP, Ajax
아래에 붙여질 소스코드에 대해서는 제가 사용하는 환경의 소스를 그대로 올리도록 하겠습니다.
클래스화 시켜 사용하던건데 일일이 풀기가 애매하네요.. 기억도 안나고 ㅎㅎ;;;
기능 1 - 로그인전이면 새로 데이터를 입력한다. → 로그인처리
기능 2 - 로그인된상태일때 다른곳에서 로그인이되면 먼저 로그인된 페이지는 자동 로그아웃된다.
기능 3 - 같은 브라우져에서 로그인을 중복해서하게되면 로그인정보의 시간만 업데이트가된다.
1. 중복체크를할 테이블 생성
Table: smstmember_session
Field | Type | Comment |
sesskey | varchar(50) NOT NULL | |
expiry | int(10) NOT NULL | |
sessvalue | varchar(50) NOT NULL | |
sessid | varchar(30) NOT NULL | |
security | int(1) NOT NULL | |
remoteip | varchar(20) NULL |
2. 로그인 처리페이지 소스 추가 (ex> login_ok.php)
소스보기
session_start();
$sesskey = session_id();
$expiry = time();
$value = "ID:".$id." _ Login OK";
$sessid = $id;
$security = 0;
$remoteip = $_SERVER['REMOTE_ADDR'];
$que = " SELECT sesskey, expiry, sessvalue, sessid, security, remoteip, NOW() as now_expiry FROM smstmember_session WHERE sessid='".$sessid."' ORDER BY expiry DESC ";
$lala3->query($que);
$LogSum = $lala3->nf();
$sessOutLogin = false; // 로그인 정보 삭제여부
$sessUpdate = false; // 로그인 시간 업데이트 처리여부
$sessInsert = false; // 로그인 처리여부
if ( $LogSum ) { // 로그인된 기록이 있다면
for ( $i=0; $i<$LogSum; $i++ ) {
$lala3->seek($i);
$lala3->next_record();
$tmpSid = Trim($lala3->f(sessid));
$tmpSkey = Trim($lala3->f(sesskey));
$tmpIp = Trim($lala3->f(remoteip));
$tmpExpiry = Trim($lala3->f(expiry));
$tmpNowExpiry = Trim($lala3->f(now_expiry));
// DBssid==ssid, DBip==ip - LoginTime Update
if ( $tmpSkey == Trim($sesskey) && $tmpSid == Trim($sessid) && $tmpIp == Trim($remoteip) ) { $sessUpdate = true; }
// DBssid==ssid, DBip!=ip - LogInfo Delete, Loginfo Insert
else if ( $tmpSkey == Trim($sesskey) && $tmpIp != Trim($remoteip) ) { $sessOutLogin = true; }
// DBssid!=ssid, DBip==ip - LogInfo Delete, Loginfo Insert
else if ( $tmpSkey != Trim($sesskey) && $tmpIp == Trim($remoteip) ) { $sessOutLogin = true; }
// DBssid!=ssid, DBip!=ip - LogInfo Delete, Loginfo Insert
else if ( $tmpSkey != Trim($sesskey) && $tmpIp != Trim($remoteip) ) { $sessOutLogin = true; }
} // end for
} else { // 로그인된 기록이 없다면
$sessInsert = true;
}
$lala3->free();
// 로그인 처리 - DB입력
if ( $sessInsert == true ) {
$que = " INSERT INTO smstmember_session (sesskey, expiry, sessvalue, sessid, security, remoteip) VALUES ('".$sesskey."', '".$expiry."', '".$value."', '".$sessid."', '".$security."', '".$remoteip."') ";
$lala3->query($que);
$lala3->free();
}
// 로그인 정보 삭제 - DB삭제
if ( $sessOutLogin == true ) {
$que = " DELETE FROM smstmember_session WHERE sessid='".$sessid."' ";
$lala3->query($que);
$lala3->free();
$que = " INSERT INTO smstmember_session (sesskey, expiry, sessvalue, sessid, security, remoteip) VALUES ('".$sesskey."', '".$expiry."', '".$value."', '".$sessid."', '".$security."', '".$remoteip."') ";
$lala3->query($que);
$lala3->free();
}
// 로그인 시간 업데이트
if ( $sessUpdate == true ) {
$que = " UPDATE smstmember_session SET expiry=UNIX_TIMESTAMP(NOW()) WHERE sessid='".$sessid."' AND sesskey='".$sesskey."' ";
$lala3->query($que);
$lala3->free();
}
$que = " SELECT * FROM smstmember_session WHERE sessid='".$sessid."' AND sesskey='".$sesskey."' ORDER BY expiry DESC LIMIT 1 ";
$lala3->query($que);
$lala3->next_record();
$lala3->free();
소스와같이 세션DB에 로그인했을때의 세션ID와 사용자 ID 로그인 시간등을 입력하게됩니다.$sesskey = session_id();
$expiry = time();
$value = "ID:".$id." _ Login OK";
$sessid = $id;
$security = 0;
$remoteip = $_SERVER['REMOTE_ADDR'];
$que = " SELECT sesskey, expiry, sessvalue, sessid, security, remoteip, NOW() as now_expiry FROM smstmember_session WHERE sessid='".$sessid."' ORDER BY expiry DESC ";
$lala3->query($que);
$LogSum = $lala3->nf();
$sessOutLogin = false; // 로그인 정보 삭제여부
$sessUpdate = false; // 로그인 시간 업데이트 처리여부
$sessInsert = false; // 로그인 처리여부
if ( $LogSum ) { // 로그인된 기록이 있다면
for ( $i=0; $i<$LogSum; $i++ ) {
$lala3->seek($i);
$lala3->next_record();
$tmpSid = Trim($lala3->f(sessid));
$tmpSkey = Trim($lala3->f(sesskey));
$tmpIp = Trim($lala3->f(remoteip));
$tmpExpiry = Trim($lala3->f(expiry));
$tmpNowExpiry = Trim($lala3->f(now_expiry));
// DBssid==ssid, DBip==ip - LoginTime Update
if ( $tmpSkey == Trim($sesskey) && $tmpSid == Trim($sessid) && $tmpIp == Trim($remoteip) ) { $sessUpdate = true; }
// DBssid==ssid, DBip!=ip - LogInfo Delete, Loginfo Insert
else if ( $tmpSkey == Trim($sesskey) && $tmpIp != Trim($remoteip) ) { $sessOutLogin = true; }
// DBssid!=ssid, DBip==ip - LogInfo Delete, Loginfo Insert
else if ( $tmpSkey != Trim($sesskey) && $tmpIp == Trim($remoteip) ) { $sessOutLogin = true; }
// DBssid!=ssid, DBip!=ip - LogInfo Delete, Loginfo Insert
else if ( $tmpSkey != Trim($sesskey) && $tmpIp != Trim($remoteip) ) { $sessOutLogin = true; }
} // end for
} else { // 로그인된 기록이 없다면
$sessInsert = true;
}
$lala3->free();
// 로그인 처리 - DB입력
if ( $sessInsert == true ) {
$que = " INSERT INTO smstmember_session (sesskey, expiry, sessvalue, sessid, security, remoteip) VALUES ('".$sesskey."', '".$expiry."', '".$value."', '".$sessid."', '".$security."', '".$remoteip."') ";
$lala3->query($que);
$lala3->free();
}
// 로그인 정보 삭제 - DB삭제
if ( $sessOutLogin == true ) {
$que = " DELETE FROM smstmember_session WHERE sessid='".$sessid."' ";
$lala3->query($que);
$lala3->free();
$que = " INSERT INTO smstmember_session (sesskey, expiry, sessvalue, sessid, security, remoteip) VALUES ('".$sesskey."', '".$expiry."', '".$value."', '".$sessid."', '".$security."', '".$remoteip."') ";
$lala3->query($que);
$lala3->free();
}
// 로그인 시간 업데이트
if ( $sessUpdate == true ) {
$que = " UPDATE smstmember_session SET expiry=UNIX_TIMESTAMP(NOW()) WHERE sessid='".$sessid."' AND sesskey='".$sesskey."' ";
$lala3->query($que);
$lala3->free();
}
$que = " SELECT * FROM smstmember_session WHERE sessid='".$sessid."' AND sesskey='".$sesskey."' ORDER BY expiry DESC LIMIT 1 ";
$lala3->query($que);
$lala3->next_record();
$lala3->free();
또한 같은 세션ID일때 로그인을 다시하게되면 로그인 시간이 업데이트됩니다.
3. 로그아웃 처리하기 (ex> logout.php)
소스보기
$mode = "mode" 변수값 받아오기
session_start();
$sesskey = session_id();
if ( $mode == "outlogin" ) {
$que = " DELETE FROM smstmember_session WHERE sessid='".$GLOBALS["C_id"]."' AND sesskey='".$sesskey."' ";
$lala3->query($que);
$lala3->free();
session_destroy();
echo "LogOut Success!!";
} else {
$que = " DELETE FROM smstmember_session WHERE sessid='".$GLOBALS["C_id"]."' ";
$lala3->query($que);
$lala3->free();
session_destroy();
echo "LogOut Success!!";
}
로그아웃 페이지에서는 세션을 클리어하는것은 물론이고, 로그인하면서 DB에 입력되어있던 로그인정보를 삭제하게됩니다.session_start();
$sesskey = session_id();
if ( $mode == "outlogin" ) {
$que = " DELETE FROM smstmember_session WHERE sessid='".$GLOBALS["C_id"]."' AND sesskey='".$sesskey."' ";
$lala3->query($que);
$lala3->free();
session_destroy();
echo "LogOut Success!!";
} else {
$que = " DELETE FROM smstmember_session WHERE sessid='".$GLOBALS["C_id"]."' ";
$lala3->query($que);
$lala3->free();
session_destroy();
echo "LogOut Success!!";
}
4. 중복 로그인 체크페이지 (ex> outlogin_check_session.php)
소스보기
<script type="text/javascript" src='login_check.js'></script>
<?php
$sessid = userid;
?>
<form name="regLoginCheck" id="regLoginCheck" method="post">
<input type="hidden" name="mode" id="mode" value="" />
<input type="hidden" name="sessid" id="sessid" value="<?=$sessid?>" />
</form>
다른곳에서 중복로그인이 되었는지 체크하는 페이지이다.<?php
$sessid = userid;
?>
<form name="regLoginCheck" id="regLoginCheck" method="post">
<input type="hidden" name="mode" id="mode" value="" />
<input type="hidden" name="sessid" id="sessid" value="<?=$sessid?>" />
</form>
이 페이지에서는 세션DB의 값과 비교하기위한 정보들을 담고 있는다.
header 페이지나 footer 페이지 즉, 항상 웹페이지에 표시되는 부분에 추가하면 되겠다.
5. 중복 로그인 체크값 추출 (ex> login_check_tender.php)
소스보기
session_start();
$sessid = userid 변수값(GET,POST);
$sesskey = session_id();
$que = " SELECT sesskey, expiry, sessid, remoteip FROM smstmember_session WHERE sessid='".$sessid."' AND sesskey='".$sesskey."' ";
$lala3->query($que);
$LogSum = $lala3->nf();
if ( $LogSum ) {
$code = "success";
} else {
$code= "failed";
}
?>
<result><code><?=$code?></code><data><![CDATA[[<?
if( $LogSum ) {
$lala3->next_record();
$DBsesskey = Trim($lala3->f(sesskey));
$sesskey = Trim($sesskey);
if ( $DBsesskey == $sesskey ) { $sess_same = "success"; }
else { $sess_same = "failed"; }
?>{sC:'<?=$sess_same?>',sK:'<?=$DBsesskey?>'}<?
} else {
?>{sC:'<?=$code?>'}<?
}
?>]]]></data></result>
지금보이는 코드는 xml 형식으로 데이터를 추출하게되는 부분이다.$sessid = userid 변수값(GET,POST);
$sesskey = session_id();
$que = " SELECT sesskey, expiry, sessid, remoteip FROM smstmember_session WHERE sessid='".$sessid."' AND sesskey='".$sesskey."' ";
$lala3->query($que);
$LogSum = $lala3->nf();
if ( $LogSum ) {
$code = "success";
} else {
$code= "failed";
}
?>
<result><code><?=$code?></code><data><![CDATA[[<?
if( $LogSum ) {
$lala3->next_record();
$DBsesskey = Trim($lala3->f(sesskey));
$sesskey = Trim($sesskey);
if ( $DBsesskey == $sesskey ) { $sess_same = "success"; }
else { $sess_same = "failed"; }
?>{sC:'<?=$sess_same?>',sK:'<?=$DBsesskey?>'}<?
} else {
?>{sC:'<?=$code?>'}<?
}
?>]]]></data></result>
다음으로 설명된 js 파일에서 위의 페이지에서 생성된 xml 코드를 참조하여 로그인여부를 체크하게된다.
6. 중복로그인 체크 및 처리하기 (ex> login_check.js)
소스보기
var stateCnt = 0;
if ( window.addEventListener ) { // 최초 웹 로딩시 불려지는 함수
window.addEventListener( "load", startTimeout_loginCheck_update, false )
} else {
window.attachEvent( "onload", startTimeout_loginCheck_update )
}
function startTimeout_loginCheck_update () { // 최초불려짐
chkTimeout_loginCheck_update ( self );
}
function chkTimeout_loginCheck_update ( self ) { // 매초마다 실행
LoginCheckTender();
self.t1 = setTimeout(function(){ chkTimeout_loginCheck_update ( self ); }, 1000); // 1초마다 데이터 참조
}
function LoginCheckTender() { // xml 형식 코드를 생성하도록 호출
new ajax.xhr.Request("login_check_tender.php", "sessid="+$("sessid").value, CheckLoginTender, 'GET');
stateCnt++;
}
function CheckLoginTender( xmlDoc ) { // xml 형식의 코드를 참조
var code = getNodeValue( xmlDoc.getElementsByTagName( 'code' ) );
if (code == 'success') { // 데이터 로딩 성공시 (로그인후)
var loaddata = eval( "(" + getNodeValue( xmlDoc.getElementsByTagName ( 'data' ) ) + ")" );
if ( loaddata.length > 0) {
for(var i = loaddata.length-1; i >= 0; i--) {
makeLoginCheck(loaddata[i], i);
}
}
} else { // 데이터 로딩 실패시 (외부에서 로그인이 되었을때)
var loaddata = eval( "(" + getNodeValue( xmlDoc.getElementsByTagName ( 'data' ) ) + ")" );
if ( loaddata.length > 0) {
for(var i = loaddata.length-1; i >= 0; i--) {
makeLoginFailed(loaddata[i], i);
}
}
}
}
function makeLoginCheck(data, i) { // 데이터 추출 확인
//if ( $("txtsesskey2") != null ) $("txtsesskey2").innerHTML = data.sK;
//if ( $("txtState") != null ) $("txtState").innerHTML = data.sC;
//if ( $("txtCnt") != null ) $("txtCnt").innerHTML = stateCnt;
}
function makeLoginFailed(data, i) { // 외부로그인이 되었을때
if ( $("sessid").value != "" && data.sC == "failed" ) {
//경고창
alert(" 외부에서의 로그인이 이루어졌습니다.\n 로그아웃을 합니다.");
//실행
Logout_Session("outlogin");
}
}
function Logout_Session(mode) { // 로그아웃 처리
$("mode").value = mode;
$("regLoginCheck").target = "_top";
$("regLoginCheck").action = "logout.php";
$("regLoginCheck").method = "post";
$("regLoginCheck").submit();
}
바로위에서 말했듯이 "login_check_tender.php" 페이지에서 생성된 xml 형식의 코드를 분석 참조하여if ( window.addEventListener ) { // 최초 웹 로딩시 불려지는 함수
window.addEventListener( "load", startTimeout_loginCheck_update, false )
} else {
window.attachEvent( "onload", startTimeout_loginCheck_update )
}
function startTimeout_loginCheck_update () { // 최초불려짐
chkTimeout_loginCheck_update ( self );
}
function chkTimeout_loginCheck_update ( self ) { // 매초마다 실행
LoginCheckTender();
self.t1 = setTimeout(function(){ chkTimeout_loginCheck_update ( self ); }, 1000); // 1초마다 데이터 참조
}
function LoginCheckTender() { // xml 형식 코드를 생성하도록 호출
new ajax.xhr.Request("login_check_tender.php", "sessid="+$("sessid").value, CheckLoginTender, 'GET');
stateCnt++;
}
function CheckLoginTender( xmlDoc ) { // xml 형식의 코드를 참조
var code = getNodeValue( xmlDoc.getElementsByTagName( 'code' ) );
if (code == 'success') { // 데이터 로딩 성공시 (로그인후)
var loaddata = eval( "(" + getNodeValue( xmlDoc.getElementsByTagName ( 'data' ) ) + ")" );
if ( loaddata.length > 0) {
for(var i = loaddata.length-1; i >= 0; i--) {
makeLoginCheck(loaddata[i], i);
}
}
} else { // 데이터 로딩 실패시 (외부에서 로그인이 되었을때)
var loaddata = eval( "(" + getNodeValue( xmlDoc.getElementsByTagName ( 'data' ) ) + ")" );
if ( loaddata.length > 0) {
for(var i = loaddata.length-1; i >= 0; i--) {
makeLoginFailed(loaddata[i], i);
}
}
}
}
function makeLoginCheck(data, i) { // 데이터 추출 확인
//if ( $("txtsesskey2") != null ) $("txtsesskey2").innerHTML = data.sK;
//if ( $("txtState") != null ) $("txtState").innerHTML = data.sC;
//if ( $("txtCnt") != null ) $("txtCnt").innerHTML = stateCnt;
}
function makeLoginFailed(data, i) { // 외부로그인이 되었을때
if ( $("sessid").value != "" && data.sC == "failed" ) {
//경고창
alert(" 외부에서의 로그인이 이루어졌습니다.\n 로그아웃을 합니다.");
//실행
Logout_Session("outlogin");
}
}
function Logout_Session(mode) { // 로그아웃 처리
$("mode").value = mode;
$("regLoginCheck").target = "_top";
$("regLoginCheck").action = "logout.php";
$("regLoginCheck").method = "post";
$("regLoginCheck").submit();
}
다른곳에서 로그인이 이루어졌는지를 판단 및 처리를하게되는 스크립트이다.
다른곳 또는 다른 웹브라우저로 로그인을하게되면 기존에 로그인된 웹페이지는 자동적으로 로그아웃이 이루어지게된다.
여기까지 섭군이가 대충 짜집기한 중복로그인 방지 소스코드였습니다.
실질적으로 구상은 쉽게되는데 짜맞추려니... 여간 힘든게 아니네요 ㅠㅠ;;
질문은 않받을래요~ 머리가 뽀개질꺼 같거든요 ㅎㅎ;;;
피드 구독하기:
글 (Atom)