웹마스터 팁

앱..이랄건없고 모바일웹을 제작했습니다.


http://ddbang.terainvest.co.kr/?m=1


주소를 공개해도되나 모르겠지만 그냥 살펴보시라고 넣어둡니다.


디자인/개발 단독작업이라 엉성한부분이좀 있습니다. 스크립트작업이나 디자인을 조금더 보완해야하긴합니다만..


무튼 되긴했습니다.


해당 모바일웹을 안드로이드 웹뷰 앱으로 제작했습니다.


말그대로 그냥 껍데기만있는 앱이지요.


껍데기만있고, 앱을실행하면 내부에선 웹브라우저가 동작하는 형태입니다.


굳이 앱을 만든 이유는.. 아무래도 푸쉬때문이겠죠 ^^


푸쉬서버는 parse.com에서 제공하는 월 100만건 무료 api를 이용합니다.


푸쉬내용은 XE알림센터를 이용해 알림센터가 전달하는 모든 내용을 푸쉬로 전달합니다.


이 팁은 저처럼 앱을 제작하시는분이 있을까봐 적어둡니다.


일단 빈 모듈을 하나 생성하시는게 작업에 유리합니다. 저는 app_module 이라는 모듈을 생성했습니다.


app_module.class.php 를 이용해 member 테이블에 obid 라는 필드를 추가하고, 단말기의 정보를 저장해줄 함수를 로그인 트리거로 걸어줍니다.


obid는 단말기의 고유번호이고, 트리거로 추가한 함수 두개중 하나는 고유번호를 세션에 저장해주는것 하나는 로그인할때 저장된세션에 있는 고유번호를 회원정보에 반영해 주는 부분 입니다.


app_module.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
require_once(_XE_PATH_.'modules/member/member.class.php');
class app_module extends member {
/**
 * @brief install the module
 **/
function moduleInstall() {
    return new Object();
}
 
/**
 * @brief chgeck module method
 **/
function checkUpdate() {
    $oDB = &DB::getInstance();
    $oModuleModel = &getModel('module');
    if(!$oDB->isColumnExists("member""obid"))    return true;
    if(!$oModuleModel->getTrigger('member.doLogin''app_module''controller''triggerAfterLogin''after')) return true;
    if(!$oModuleModel->getTrigger('moduleHandler.proc''app_module''controller''triggerModuleHandlerProc''after'))   return true;
    return false;
}
 
/**
 * @brief update module
 **/
function moduleUpdate() {
    $oDB = &DB::getInstance();
    if(!$oDB->isColumnExists("member""obid")) $oDB->addColumn("member""obid""varchar","128");
 
    $oModuleModel = &getModel('module');
    $oModuleController = &getController('module');
    if(!$oModuleModel->getTrigger('member.doLogin''app_module''controller''triggerAfterLogin''after'))
    $oModuleController->insertTrigger('member.doLogin''app_module''controller''triggerAfterLogin''after');
    if(!$oModuleModel->getTrigger('moduleHandler.proc''app_module''controller''triggerModuleHandlerProc''after'))
        $oModuleController->insertTrigger('moduleHandler.proc''app_module''controller''triggerModuleHandlerProc''after');
    return new Object(0, 'success_updated');
}
 
function moduleUninstall() {
    return new Object();
}
 
/**
 * @brief re-generate the cache files
 **/
function recompileCache() {
}
 
}


이제 controller 부분의 두개함수를 작성 해주어야겠죠?


app_module.controller.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
 * @brief Get ObjectID, Save Session
 */
function triggerModuleHandlerInit(){
    if(Context::get('obid')){
        $_SESSION["obid"] = Context::get('obid');
    }
}
/**
 * @brief A trigger to add Object ID for Member
 */
function triggerAfterLogin(&$obj)
{
    $member_srl $obj->member_srl;
    if(!$member_srlreturn new Object();
 
    if(!$_SESSION["obid"]) return new Object();
 
    $query "update xe_member set `obid` = '".$_SESSION["obid"]."' where `member_srl` = ".$member_srl;
    $sql = mysql_query($query);
 
    if($sql){
        unset($_SESSION["obid"]);
        return new Object();
    }else{
        return new Object(-1,"단말기 정보를 가져오는데에 실패했습니다.");
    }
}


이제 푸쉬를 실제로 전송할 Model 클래스에 다음함수를 추가해줍니다.

app_module.model.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function getPushMessage($v,$obid){
switch($v->type)
{
    case 'D':
        $type "글";
    break;
    case 'C':
        $type "댓글";
    break;
    // 메시지. 쪽지
    case 'E':
        $type "쪽지";
    break;
}
 
switch($v->target_type)
{
    case 'C':
        $str = sprintf('%s님이 회원님의 %s에 "%s" 댓글을 남겼습니다.'$target_nick_name$type$v->target_summary);
    break;
    case 'M':
        $str = sprintf('%s님이 "%s" %s에서 회원님을 언급하였습니다.'$target_nick_name,  $v->target_summary, $type);
    break;
    // 메시지. 쪽지
    case 'E':
        $str = sprintf($lang->app_ncenter_message_string, $v->target_summary);
    break;
}
 
 
    //푸쉬전송
    $url 'https://api.parse.com/1/push';
    $appId = <!-- 수정하세요 parse.com appId -->;
    $restKey = <!-- 수정하세요 parse.com RESTKEY -->;
 
    $target_device $obid;  // using object Id of target Installation.
 
    $push_payload = json_encode(array(
            "where" => array(
                    "objectId" => $target_device,
            ),
            "data" => array(
                    "alert" => $str,
                    "url" => getUrl('','act','procNcenterRedirect''notify'$v->notify, 'url'$v->target_url)
            )
    ));
 
    $rest = curl_init();
    curl_setopt($rest,CURLOPT_URL,$url);
    curl_setopt($rest, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($rest, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($rest,CURLOPT_PORT,443);
    curl_setopt($rest,CURLOPT_POST,1);
    curl_setopt($rest,CURLOPT_POSTFIELDS,$push_payload);
    curl_setopt($rest,CURLOPT_HTTPHEADER,
            array("X-Parse-Application-Id: " $appId,
                    "X-Parse-REST-API-Key: " $restKey,
                    "Content-Type: application/json"));
    curl_exec($rest);
 
}


위함수는 CURL을 이용하여 parse.com에 푸쉬메세지를 전달합니다.

중요한부분 몇가지를 짚고넘어가자면,


curl_setopt($rest, CURLOPT_RETURNTRANSFER, 1);

이부분을 통해 결과값을 페이지에 뿌리지않고 변수에 저장해줍니다. 페이지에 뿌리게되면 트리거부분에서 에러가납니다.

(display handler와의 충돌~)


curl_setopt($rest, CURLOPT_SSL_VERIFYPEER, 0);

이부분은 CURL작업할때 많이들 빠뜨리시는 부분인데, https:// 로 데이터를 전송할땐 반드시 포함되어야합니다. 


그리고, 메세지를 생성하는 과정에서 기존 알림센터와 살짝 다른부분이 있습니다.

우선 언어팩을 사용하실분은 global $lang; 을통해 사용하시면되고, 알림센터의 언어팩을 그대로사용할경우 푸쉬메세지에 태그가 그대로 노출되므로 ( <strong> ... ) 새 언어팩을 만드셔서 사용하시면 되겠습니다.


이제, 알림센터의 controller 파일을 조금 수정해줍니다.

ncenter.controller.php
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
else if($logged_info)
{
    // 익명 노티가 아닐 때 로그인 세션의 회원정보 넣기
    $args->target_member_srl = $logged_info->member_srl;
    $args->target_nick_name = $logged_info->nick_name;
    $args->target_user_id = $logged_info->user_id;
    $args->target_email_address = $logged_info->email_address;
 
    //푸쉬알림 추가
    $oMemberModel = &getModel('member');
    $push_sender_info $oMemberModel->getMemberInfoByMemberSrl($args->member_srl);
    if($push_sender_info->obid){
        $oAppModuleModel = &getModel('app_module');
        $oAppModuleModel->getPushMessage($args,$push_sender_info->obid);
    }
}

모듈을 업로드하고, 업데이트를하면 준비가 완료된겁니다. 


이제 앱에서 첫페이지를 로드할때 get방식으로 obid 변수를 전달합니다.


단말기의 고유 object id를 담아 전달하면됩니다.


저의경우 다음과같은 형태로 전달했습니다.


http://ddbang.terainvest.co.kr/?m=1&obid=OBJECTID


그럼, 최초 페이지가 로딩될때 object ID를 세션에 저장하고 로그인이 될때 회원정보에 반영을 하게되지요.


그리고 회원정보에 obid가 반영되어 있는경우 알림센터에서 app_module 에 있는 model클래스의 함수를통해 푸쉬데이터를 생성하고, 전송합니다.


앱에서 들어온 푸쉬데이터의 data->url 을 통해 해당웹페이지를 로드해주면 되겠습니다. ^^


아래는 인증샷..


m2_2k3p58kbtml9nyqyk2iaaaevhcjc23qvjnukl6h_8050906056516760138.jpg



사실.. 이걸어떻게해야하나 하며 웹뷰앱 만드신분과 머리를 맞대고 고민을 많이했습니다만


이렇게 공개해보니 별거아니네요...


흠이 좀 있다면,,, model 클래스의 푸쉬전송함수를 푸쉬데이터 생성만하고 controller에서 처리하려했는데


...귀찮... ^^* 이해하시죠?


MVC패턴에 살짝 어긋나긴했지만 무튼 .. 도움되시길바랍니더 ~(__)~

제목 글쓴이 날짜
jQuery 플러그인 모음 Ansi™ 2017.01.25
DOS 공격에 대한 방어 프로그램입니다. 마루디자인 2017.01.23
관리자 로그인시 원하는걸 보여주자 [5] 빽짱구 2008.04.15
SSL의 정석 (아파치 & nginx) [13] 기진곰 2015.06.16
방명록 형태 사용시 제목이 길게 저장되게 하려면 sejin7940 2016.12.23
로그인풀림방지 - 주소 고정하기 [27] ezi 2011.05.28
숫자 아이디 허용 방법 file 410contents 2016.12.13
(설문조사) 회원만 설문 조사 하도록 [8] Simulz 2007.09.04
클라우드플레어 사용시 서버 IP 노출방지 체크리스트 gnbstory 2016.12.09
간단한 xe 관련 자바스크립트 질문 [1] 마든남 2016.12.01
스크롤 맨아래로 내리면 자동으로 글 목록 더보이기 구현(게시판어어느 스킨이든 사용가능) [19] 장포크 2013.08.10
메뉴에 새 글 표시 모듈 사용 시 new 아이콘이 보이지 않는 버그 수정 [8] 퍼니엑스이 2014.08.12
가상서버 고르실때 참고하시면 좋겠네요. 로니 2016.11.24
CloudFlare 사용시 방문자 IP와 SSL 접속여부가 정확하게 파악되지 않는 문제 해결법 [4] 기진곰 2015.07.12
네이버 웹마스터도구 최적화검증과 GZIP 영흥도우럭1 2016.11.18
구글애드센스 한페이지에 3개 초과하시면 안됩니다. [3] 최윤한 2016.11.11
모바일환경에서, 스케치북스킨의 경우 포인트레벨아이콘이나 닉네임이미지 가 안 나타나는 경우 수정법 sejin7940 2016.11.13
관리자페이지의 게시판 목록에서 '모듈분류'로만 검색이 안 되는 버그 수정 sejin7940 2016.11.09
Bash Shell 버그 패치 필요 [2] 고구마군 2014.09.29
클라우드 플레어 질문있습니다. [2] 생컨38889 2016.08.31