반응형
클래스 메서드는 메서드를 정의할 때, class 예약어를 추가한 메서드를 말합니다.
클 래스 메서드는 특정 객체에 종속되지 않는 메서드 입니다. 이 말은 Self 레퍼런스가 존재하지 않는다는 것이며, 달리 말하면 멤버 필드 값을 참조할 수 없다는 것입니다. 다음 소스 파일을 컴파일 하면 클래스 메서드인 ClassMethod 내에서는 멤버 필드 값 참조 코드가 모두 에러로 처리됨을 알 수 있습니다.

unit Unit2;

interface

type
  TTestClass = class(TObject)
  private
    FOne: Integer;
    FTwo: string;
  public
    class procedure ClassMethod;
    procedure NormalMethod;
  end;

implementation

class procedure TTestClass.ClassMethod;
begin
  FOne := 10;       // Compile Error
  FTwo :='abcdef';  // Compile Error
end;

procedure TTestClass.NormalMethod;
begin
  FOne := 10;
  FTwo :='abcdef';
end;

end.

멤 버 필드를 참조하지 못한다는 점으로만 판단하면, 클래스 메서드는 별로 사용가치가 없어 보이나, 사실 그렇지 않습니다. 일반 메서드는 반드시 객체를 생성하고 초기화한후에야만 호출할 수 있지만, 클래스 메서드는 객체 생성을 하지 않아도 일반 전역 함수처럼 호출 할 수 있습니다. 다음 코드가 이를 설명합니다.

procedure CallTest;
var
  obj : TTestClass;
begin
  // 클래스 메서드는 클래스명을 참조하여 직접 호출 가능함
  TTestClass.ClassMethod;
  // 클래스 메서드는 생성되지 않는, 즉 초기화하지 않은 객체를 통해서도 호출 가능
  obj.ClassMethod;

  // 일반 메서드는 객체 생성후에야만 호출 가능
  obj := TTestClass.Create;
  obj.NormalMethod;

  // 클래스 메서드는 생성된 객체를 통해서도 호출 가능
  obj.ClassMethod;
  
  obj.Free;

end;


클 래스 메서드를 대체 어떤 경우 사용해야 할까요? 객체 지향 이론에 의하면, 전역 함수는 프로그램 유지 보수를 어렵게 만들기 때문에, 전역함수 대신,  메서드를 사용하라고 권합니다. 이 이론을 따라서, 전역함수를 특정 클래스의 일반 메서드로 정의했다면, 그 메서드를 호출하려면, 앞의 예제에서 봤듯이 항상 객체 생성/파괴와 관련된 코드가 수반되어야 합니다.

반면에 클래스 메서드는 객체 생성과 파괴 없이도 호출할 수 있기 때문에 전역적 함수 역할을 충분히 대신할 수 있다는 이야기 입니다.

즉 클래스 메서드는, 관련된 전역함수들끼리 특정 클래스에 모아두고, 메서드를 전역 함수 처럼 사용할 수 있게 하는 것입니다.

클래스 메서드 사용예로서, 로그인을 처리하는 다음과 같은 클래스를 만들었다고 가정합시다

unit Unit3;

interface.

type
  TLogin = class(TObject)
  public
    class procedure Login;
    class procedure Logout;
  end;

implementation

var
  // 요 파일에서만 참조 가능하도록 implementation 영역에서 변수 정의
  LoginCnt : integer = 0;
  LoginId, Password : String;

class procedure TLogin.Login;
begin
  // Login Process Code
  // Get Id
  // Get Password

  inc(LoginCnt);
  if LoginCnt > 4 then
  begin
    ShowMessage('Max log count limit. Program shut down');
  end;
end;

class procedure TLogin.Logout;
begin
  // Log out
end;

이제 로그인 작업을 처리하려면 다음과 같이 하면 될 것 입니다.

procedure SomeJob;
begin
  TLogin.Login;
end;

유감스럽게도 델파이에는 클래스 메서드는 있으나 클래스 필드는 없습니다. 즉 다음과 같이 코딩할 수는 없습니다.

TLogin = class(TObject)
  private
    class ID : string;      // 클래스 필드는 지원하지 않음. 컴파일 에러
    class Password : string; // 클래스 필드는 지원하지 않음. 컴파일 에러
  public  
    class procedure Login;
    class procedure Logout;
  end;

이 때문에 TLogin 클래스와 밀접한 관계가 있는  LoginCnt, LoginId, Password 등을 멤버 필드로 정의하지 못하고, 유닛 전역적 변수인 implementation 영역에서 정의했습니다. 이 변수들을 멤버 필드로 정의해 버리면 클래스 메서드인 Login은 이 값을 참조할 수가 없기 때문입니다.

결론적으로 이야기해서, 클래스 정의가 어떤 변수와 그 변수를 사용하는 함수들간에 문법적 결합을 설정하는 것처럼, 클래스 메서드란 관련성 있는 전역 함수들 간에 문법적 결합을 설정하는 것입니다.
 


반응형
반응형

var
  aaa : Integer;
begin
  aaa :=  StrToIntDef('a',-1);

  edt_1.Text := FormatFloat('#,',aaa);


세자리수 마다 끊어서 , 출력

반응형
반응형

녕하세요.

 

StringGrid 내용을 자동으로 스크롤 시키는 팁이 있어서 소개해 드립니다.

 

 

 

 

StringGrid의 데이터 영역에서 마우스를 클릭한 상태로 상하좌우로 이동하면

데이터 영역이 자동으로 스크롤 됩니다.

 

루틴은 아래와 같이 간단 합니다.

 

procedure TForm1.StringGrid1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  px,py: Integer;
begin
  if not flag then Exit;
  //if not(ssCtrl in Shift) then Exit;

  px := GetScrollPos(StringGrid1.Handle, SB_HORZ);
  py := GetScrollPos(StringGrid1.Handle, SB_VERT);
  px := px - (X - x1);
  py := py - (Y - y1);

  StringGrid1.Perform(WM_HSCROLL, px shl 16 or SB_THUMBPOSITION, 0);
  StringGrid1.Perform(WM_VSCROLL, py shl 16 or SB_THUMBPOSITION, 0);

  x1 := X;
  y1 := Y;
end;

 

여러가지로 응용이 가능 할 것 같은데요...

 

반응형
반응형

팁은 담비님(천리안 FREKBS)님이 99년 4월 1일에 천리안 프로그래머포럼에 올리신 것입니다.
담비님으로부터는 전제하여 올리는 데 대해 허락을 받았습니다.
좋은 정보를 공유하도록 허락해주신 담비님께 감사드립니다.

-----------------------------------------------------------------------
안녕하세요! 담비입니다.

출처 : http://www.inprise.co.jp/tips/cbuilder/cb010/index.html

메모 콤포넌트는 윈도우 클래스의 "EDIT"를 사용하고있지만, 모든 메세지를 커버
하는것은 아니다. 메모 콤포넌트가 제공하고 있지 않는 주요한 메세지들에 관하여
소개한다.

메모 콤포넌트와 메세지
----------------------

Memo Component는 복수행에 걸쳐 문자열을 편집할 수 있는 기본적인 component이다.
이것은, Windows가 제공하는 Window Class인 "EDIT"를 사용하여 실현하고 있다.
Memo Component는, "EDIT" 클래스가 메세지에 의해 제공하고 있는 기능을 많은
method나 property를 사용해 이용할 수 있도록 하고 있다. 그러나, 그다지 사용되지
않는 일부의 메세지에는 대응하는 property와 method가 존재하지 않는다. 아래는,
Memo Component를 사용하여 제공되지 않는 주요한 메세지와 그 사용 예를
나타낸것이다. 다시말하자면 , 콤포넌트에 메세지를 보내기위해 Perform method를
사용할 수 있다. Perform의 첫번째 인수에는 메세지를 두번째 인수에는
WParam(int형), 세번째 인수에는 LParam(int형)을 건네준다. WParam과 LParam은
메세지마다의 역할이 다르다. 이들 인수가 사용되지 않는 경우에는 0을 건네준다.

EM_GETRECT, EM_SETRECT, EM_SETRECTNP
──────────────────
Memo 컴포넌트중에서 편지영역으로 사용할 영역을 취득, 설정한다.
Perform의 LParam에는, 지정하는 범위를 나타내는 RECT형 변수의 주소를 건내준다.
예를 들자면, 다음의 프로그램은, Memo1 컴포넌트의 편집 영역을 Memo1 전체로부터
10 dot 이내로 한다. EM_SETRECTNP는, 메모 컴포넌트의 내용을 다시 그리지는
않는다는 점을 제외하고, EM_SETRECT와 동일하다.

    RECT R := Memo1->ClientRect;
    InflateRect(&R, -10, -10);
    Memo1->Perform(EM_SETRECT, 0, (int)&R);

다음의 프로그램은, Memo1 컴포넌트에 실제로 표시되어지는 행수를 계산한다.
    RECT R;
    Memo1->Perform(EM_GETRECT, 0, (int)&R);
    int N = (R.bottom - R.top) / Canvas->TextHeight("H");


EM_SCROLL
─────
Memo 컴포넌트의 내용을 상하 스크롤시키는 메세지이다. WParam에는 4종류의
스크롤 방법을 지정할수 있다.

SB_LINEDOWN     1줄 아래로 스크롤
SB_LINEUP       1줄 위로 스크롤
SB_PAGEDOWN     1페이지 아래로 스크롤
SB_PAGEUP       1페이지 위로 스크롤

다음의 프로그램은, Memo1의 내용을 1줄 아래로 보이게(전체를 1줄 위로하여)
스크롤 한다.
    Memo1->Perform(EM_SCROLL, SB_LINEDOWN, 0);

EM_LINESCROLL
───────
Memo 컴포넌트의 내용을 상하좌우로 스크롤하는 메세지이다.
WParam에는 수평방향의 문자수를, LParam에는 수직방향의 행수를 건제준다.
스크롤되어지는 의미가 없는 경우는 무효이다. 예를들자면, WordWrap property가
true인 때는 수평스크롤은 할수없다.
다음의 프로그램은 Memo1의 내용을 2문자와 2행의 좌상으로 스크롤한다.
    Memo1->Perform(EM_LINESCROLL, 2, 2);


EM_CANUNDO, EM_UNDO, EM_EMPTYUNDOBUFFER
────────────────────

편집 조작을 취소시키기 위한 메세지이다. Memo 컴포넌트는 상에서 Ctrl-Z을 누르면
현재 텍스트메뉴에서 [취소 (U)]를 실행한것과 동일한 처리를, 프로그램으로부터
실행할수 있다. EM_CANUNDO는, 원래대로 되돌릴 편집조작이 있는가를 판단하기
위한것이다. 예를 들자면, EM_CANUNDO의 결과가 false에 있는 경우 [취소 (U)]이라는
조작을 금지시킬수 있다. 또, EM_EMPTYUNDOBUFFER은 원래대로 되돌릴 조작을 위한
버퍼를 클리어한다. EM_EMPTYUNDOBUFFER 메세지가 보내진 후에는, EM_CANUNDO는
false를 되돌린다. 이들 메세지는 어느것도 Wparam, Lparam을 사용하지 않는다.

EM_LINEFROMCHAR
────────
지정한 문자위치에 있는 행을 되돌린다. 문자의 위치와 행번호는, 각각 0이 시작점
이 된다. 마지막으로, 선두의 문자와 선두의 행은 0의 값에서 나타난다. 문자위치는
WParam에 건네주지만, -1을 건네주면 현재 커서위치의 행번호를 돌려준다. 다음의
프로그램은, Memo1의 OnKeyUp 이벤트를 사용하여, 키입력이 있을때마다의 현재의
행번호를 Caption에 표시한다.
    void __fastcall TForm1::Memo1KeyUp(TObject *Sender, WORD &Key,
          TShiftState Shift)
    {
        Caption = IntToStr(Memo1->Perform(EM_LINEFROMCHAR, -1, 0) + 1);
    }


EM_SETTABSTOPS
───────
Tab Stop의 위치를 지정하는 메세지이다. WParam에는, 지정하는 Tab Stop 배열의
요소수를, LParam은 Tab Stop 배열에 대한 주소값을 건네준다. 그러나, WParam의
값에 따라 LParam의 평가방법이 변하게 된다.           
WParam이 0인 경우, LParam에 관련된 Tab Stop의 위치는 8문자 단위가 되어지다.
WParam이 1인 경우, LParam에 지정하는 배열은 1개의 요소만을 가지지만, Tab Stop은
여기에 지정된 위치가 연속적으로 반복되어진다.
WParma이 2 이상인 경우, LParam이 지정한 배열은 WParam개의 요소를 가지고, 이
범위를 초과한 부분은 Default의 Tab Stop위치를 가지게 된다.
Tab Stop은 DWord형의 배열로 지정하고, 위치는 Dialog 단위로서 나타내진다.
Tab Stop 단위는 문자폭의 평균치의 1/4이 되기때문에, 4문자 단위의 Tab Stop을
지정한 경우에는 16을 지정한다.
다음의 프로그램은, Memo1 컴포넌트의 Tab Stop을 2문자 단위로 한다.
    DWORD TabStops[1] = { 4 * 2 };
    Memo1->Perform(EM_SETTABSTOPS, 1, (int)TabStops);


EM_FIRSTVISIBLELINE
──────────
Memo 컴포넌트상에서, 실제로 눈에 보여지고 있는 최초의 행의 행번호를 되돌려준다.
(최초의 행은 0)

EM_GETMARGINS, EM_SETMARGINS
──────────────
Memo 컴포넌트상에서 좌우의 여백을 설정한다. WParam은 성정한 여백의 종류를
나타내고, LParam은 MAKELONG과 병용하는 여백의 크기를 나타낸다.
다음의 프로그램은, 좌측에 20 dot, 우측에 30 dot의 여백을 설정한다.
    Memo1->Perform(EM_SETMARGINS,
                   EC_LEFTMARGIN : EC_RIGHTMARGIN, MAKELONG(20, 30));


EM_POSFROMCHAR, EM_CHARFROMPOS
───────────────
Memo 컴포넌트상의 좌표와 문자의 위치를 상호 변환시키는 메세지이다.
EM_POSFROMCHAR은, 지정된 문자위치(텍스트의 선두로부터의 바이트 수의 문자의
좌상의 좌표를 되돌려준다. WParam에는, TPoint형의 변수를 사용하는 주소값을
되돌려준다.
EM_CHARFROMPOS에는, 클라이언트 영역의 좌표로부터 그 장소에 있는 문자의 위치
(텍스트의 선두로부터의 위치와 행번을 되돌려준다.
다음의 프로그램은, Memo1의 OnMouseMove 이벤트를 사용하여, 마우스 커서상에
있는 문자의 위치와 행번을 Caption에 표시하는것이다.
    void __fastcall TForm1::Memo1MouseMove(TObject *Sender, TShiftState Shift,
          int X, int Y)  
    {
        DWORD DW = Memo1->Perform(EM_CHARFROMPOS, 0, MAKELONG(X, Y));
        Caption = IntToStr(LOWORD(DW)) + ":" + IntToStr(HIWORD(DW));
    }  


반응형
반응형

중국어로 되어있음.

//查找是否存在
var
  reg: TPerlRegEx;
begin
  reg := TPerlRegEx.Create(nil);

  reg.Subject := 'CodeGear Delphi 2007 for Win32';
  reg.RegEx   := '\d';

  if reg.Match then
    ShowMessage('找到了')
  else
    ShowMessage('没找到');


  FreeAndNil(reg);
end;

//查找是否存在(方法2) var   reg: TPerlRegEx; begin   reg := TPerlRegEx.Create(nil);   reg.Subject := 'CodeGear Delphi 2007 for Win32';   reg.RegEx  := '\d';   reg.Match; //执行查找   if reg.FoundMatch then  //布尔变量 FoundMatch 会告诉我们查找有没有结果     ShowMessage('找到了')   else     ShowMessage('没找到');   FreeAndNil(reg); end;
//显示找到的第一个 var   reg: TPerlRegEx; begin   reg := TPerlRegEx.Create(nil);   reg.Subject := 'CodeGear Delphi 2007 for Win32';   reg.RegEx  := '\d';   if reg.Match then     ShowMessage(reg.MatchedExpression)  //2   else     ShowMessage('没找到');   FreeAndNil(reg); end;
//分别显示找到的每一个和总数 var   reg: TPerlRegEx;   num: Integer; //用 num 来计数 begin   reg := TPerlRegEx.Create(nil);   reg.Subject := 'CodeGear Delphi 2007 for Win32';   reg.RegEx  := '\d';   num := 0;   while reg.MatchAgain do  //MatchAgain 是下一个   begin     ShowMessage(reg.MatchedExpression); //将分别显示: 2 0 0 7 3 2     Inc(num);   end;     ShowMessage(IntToStr(num)); //6   FreeAndNil(reg); end;
//分别显示找到的每一个和总数(另一种写法) var   reg: TPerlRegEx;   num: Integer; //用 num 来计数 begin   reg := TPerlRegEx.Create(nil);   reg.Subject := 'CodeGear Delphi 2007 for Win32';   reg.RegEx  := '\d';   num := 0;   if reg.Match then   begin     repeat       ShowMessage(reg.MatchedExpression); //将分别显示: 2 0 0 7 3 2       Inc(num);     until (not reg.MatchAgain);   end;     ShowMessage(IntToStr(num)); //6   FreeAndNil(reg); end;
//目标字符串的位置与长度 var   reg: TPerlRegEx; begin   reg := TPerlRegEx.Create(nil);   reg.Subject := 'CodeGear Delphi 2007 for Win32';   reg.RegEx  := 'Delphi';   while reg.MatchAgain do  //很明显: 本例只能找到一个结果   begin     ShowMessage(reg.MatchedExpression); //找到的字符串: Delphi     ShowMessage(IntToStr(reg.MatchedExpressionOffset)); //它所在的位置: 10     ShowMessage(IntToStr(reg.MatchedExpressionLength)); //它的长度: 6   end;   FreeAndNil(reg); end;

// MatchedExpression 与 SubExpressions[0]
var
  reg: TPerlRegEx;
begin
  reg := TPerlRegEx.Create(nil);

  reg.Subject := 'CodeGear Delphi 2007';
  reg.RegEx   := 'Delphi'; 

  while reg.MatchAgain do
  begin
    ShowMessage(reg.MatchedExpression); //Delphi; 这是匹配到的内容
    ShowMessage(reg.SubExpressions[0]); //Delphi; 也可以这样显示匹配到的内容
  end;
{
  SubExpressions 是一个数组:
  SubExpressions[1] 储存第 1 个表达式匹配的内容;
  SubExpressions[2] 储存第 2 个表达式匹配的内容;
  SubExpressions[n] 储存第 n 个表达式匹配的内容;

  SubExpressions[0] 储存整个表达式匹配的内容;

  MatchedExpression 表示的不过是 SubExpressions[0].
}

  FreeAndNil(reg);
end;

//提取子表达式匹配到的内容 var   reg: TPerlRegEx; begin   reg := TPerlRegEx.Create(nil);   reg.Subject := 'abc A1111 BB222 CCC33 DDDD4';   reg.RegEx  := '\b([A-D]+)([1-4]+)\b'; //这个表达式有两个子表达式构成   while reg.MatchAgain do   begin     ShowMessage(reg.SubExpressions[0]); //将分别显示: A1111 BB222 CCC33 DDDD4     ShowMessage(reg.SubExpressions[1]); //将分别显示: A BB CCC DDDD     ShowMessage(reg.SubExpressions[2]); //将分别显示: 1111 222 33 4     {另外:       reg.SubExpressionCount      是子表达式的个数;       reg.SubExpressionLengths[n] 是第 n 个表达式返回的字符串的长度;       reg.SubExpressionOffsets[n] 是第 n 个表达式返回的字符串在源字符串中的位置     }   end;   FreeAndNil(reg); end;


//设定搜索范围: Start、Stop
var
  reg: TPerlRegEx;
begin
  reg := TPerlRegEx.Create(nil);

  reg.Subject := 'ababab';
  reg.RegEx   := 'ab';
  reg.Replacement := '◆';

  reg.Start := 1;
  reg.Stop := 2;
  while reg.MatchAgain do
  begin
    reg.Replace;
  end;
  ShowMessage(reg.Subject); //返回: ◆abab


  reg.Subject := 'ababab';
  reg.Start := 3;
  reg.Stop := 4;
  while reg.MatchAgain do
  begin
    reg.Replace;
  end;
  ShowMessage(reg.Subject); //返回: ab◆ab


  reg.Subject := 'ababab';
  reg.Start := 5;
  reg.Stop := 6;
  while reg.MatchAgain do
  begin
    reg.Replace;
  end;
  ShowMessage(reg.Subject); //返回: abab◆

  FreeAndNil(reg);
end;

// Replace
var
  reg: TPerlRegEx;
begin
  reg := TPerlRegEx.Create(nil);

  reg.RegEx   := 'ab';
  reg.Replacement := '◆';

  reg.Subject := 'ababab';
  reg.ReplaceAll;
  ShowMessage(reg.Subject); //返回: ◆◆◆


  reg.Subject := 'ababab';
  //下面四行程序, 相当于 reg.ReplaceAll;
  while reg.MatchAgain do
  begin
    reg.Replace;
  end;

  ShowMessage(reg.Subject); //返回: ◆◆◆

  FreeAndNil(reg);
end;
{
  ReplaceAll 函数返回的是 Boolean;
  Replace 函数返回的是 Replacement 的值, 当然是不能赋值的, 它仅仅是返回值.
}

// Compile、Study
var
  reg: TPerlRegEx;
begin
  reg := TPerlRegEx.Create(nil);

  reg.RegEx   := 'ab';
  reg.Options := [preCaseLess];
  reg.Compile; {编译表达式}
  reg.Study; {Study 方法会检查是否编译, 如果没有编译则执行 Compile}

  reg.Replacement := '◆';
  reg.Subject := 'abAbaB';

  reg.ReplaceAll;
  ShowMessage(reg.Subject); {返回: ◆◆◆}

  FreeAndNil(reg);
end;

{
  编译表达式, 会加快执行速度、降低启动速度;
  如果表达式比较复杂而又多次执行, 应该先编译;
  编译内容包括表达式选项.
}



// EscapeRegExChars 函数可以自动为特殊字符加转义符号 \
var
  reg: TPerlRegEx;
begin
  reg := TPerlRegEx.Create(nil);

  reg.Subject := 'C++Builer';
  reg.RegEx   := reg.EscapeRegExChars('C+') + '{2}'; {相当于 'C\+{2}'}
  reg.Replacement := '◆';
  reg.ReplaceAll;

  ShowMessage(reg.Subject); {返回: ◆Builer}

  FreeAndNil(reg);
end;



//字符串分割: Split
var
  reg: TPerlRegEx;
  List: TStrings;
begin
  List := TStringList.Create;
  reg := TPerlRegEx.Create(nil);

  reg.Subject := 'aaa,bbb,ccc,ddd';
  reg.RegEx   := ','; {这里可是运行相当复杂的分割符啊}

  reg.Split(List,MaxInt); {第一个参数读入的是 Subject; 第二个参数是分成多少份}
  { 输入一个最大整数, 表示能分多少就分多少}

  ShowMessage(List.Text);
  {返回:
    aaa
    bbb
    ccc
    ddd
  }

  FreeAndNil(reg);
  List.Free;
end;




반응형
반응형

안녕하세요. 웹표준화팀 박상혁입니다.

2009년 어느날
"우리도 모바일에 최적화된 모바일 전용 웹 서비스를 제공 하기로 했습니다~!!" 라는 결정이 내려졌다면... 우리 UI개발자들은 어떤 것부터 해야할까요?
서적이나 가이드문서를 옆에두고 참고하면서 진행하려고 하는데 관련 자료를 찾기가 힘들고 책은 더더욱 힘듭니다.
이런 상황에서 가장 먼저 쉽게 할 수 있는 것은 아마도 이미 모바일 서비스 제공중인 곳의 마크업을 살펴보고 코드를 응용해서 작업 하는 방법일 겁니다.
하지만 얼마전 구입한 최신 핸드폰으로 http://pda.naver.com에 접속했으나 모바일 웹 브라우저는 소스보기를 지원하지 않고 PC에서 접속하니 모바일 사이트는 접근 할 수 없습니다.

위와 같은 상황에서 PC 웹 브라우저로 모바일 사이트를 볼 수 있는 방법을 소개하려고 합니다. 물론 소스보기도 가능하구요.

일반적으로 브라우저는 User Agent 혹은 사용자 정보라고 불리우는 브라우저 고유의 정보를 가지고 있습니다. 이것은 사용자가 브라우저에 주소를 입력해 접속 요청을 하면 현재 사용자의 브라우저종류, 버전, OS 등을 서버에 알려주는 역할을 합니다.
이러한 정보를 이용해 특정 브라우저 사용자가 해당 웹사이트 접근을 할 수 없게 하거나 혹은 해당되는 사용자만 사용할 수 있도록 해 놓은 경우가 있습니다. (물론 특정 URL로 PC에서도 별도 설정 변경 없이 확인 가능한 서비스도 있습니다.)
모 바일 웹 브라우저도 PC 웹 브라우저와 마찬가지로 User Agent를 웹 서버에 전송합니다. 이것을 이용하여 사용자가 특정 서비스에 접속했을때 User Agent를 확인 해 PC,Mobile 에 최적화된 각각의 서비스로 연결시킵니다.

실제로 전송되는 User Agent 를 테스트 해본 결과 PHP의 $_SERVER['HTTP_USER_AGENT'] 로 아래와 같은 User Agent Strings 을 확인 할 수 있었습니다.

LG 아르고폰(LG텔레콤) - Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 800*600;POLARIS 6.0;em1.0;lgtelecom;EB10-200090218-707682823;LG-LH2300;0);
iPod Touch - Mozilla/5.0 (iPod; U; CPU like Mac OS X; ko-kr) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3
옴니아 Opera Mobile - SAMSUNG-SCH-M490/(null)HK4 (compatible; MSIE 6.0; Windows CE; PPC) Opera 9.5
옴니아 IE Mobile - SAMSUNG-SCH-M490/(null)HK4 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)

Firefox (add-on)

위의 정보를 가지고 아래와 같이 설정하시면 확인 하실 수 있습니다.

  • User Agent Switcher - Firefox의 User Agent를 모바일 단말의 User Agent 로 설정하면 모바일 단말의 브라우저로 정보를 요청했을때와 같은 응답을 받을 수 있습니다.

    1. 설치 후 도구 > User Agent Switcher > options > options 선택
    2. 왼쪽의 User Agents > Add 클릭 > 단말기의 User Agent 입력(ex. iPod Touch)

      User Agent 입력화면
    3. 추가된 단말기 User Agent 선택

      User Agent 선택화면
    4. 모바일 웹 서비스 접속

      모바일 웹 서비스 접속화면
  • 비슷한 기능의 Firefox Add on 으로는 Modify Header 등이 있습니다.
  • XHTML Mobile Profile - Firefox 가 본래 지원하지 않는 application/vnd.wap.xhtml+xml mime-type을 지원합니다. 모바일 웹 스펙인 XHTML Mobile Profile을 위한 MIME-TYPE인 application/vnd.wap.xhtml+xml의 설정되어 있을 경우 이를 표시 해주는 Add on 입니다. 설치 후 별도 설정은 필요 없습니다.
  • wmlbrowser - Firefox 에서 WML page 를 보여주는 부가기능입니다. 설치 후 별도 설정은 필요 없습니다.

Safari

Safari 브라우저의 경우 브라우저에 해당 기능을 기본으로 제공하고 있습니다. DevelopMode 를 활성화 시켜 User Agent 를 iPhone 이나 iPod Touch 로 변경해서 동일한 결과를 얻을 수 있습니다. 설정 방법은 아래와 같습니다.

  1. 편집 > 기본설정 > 고급 > 개발자용 모드 보기에 체크
    Safari 설정화면

  2. 개발자용 메뉴 > 사용자 에이전트 > iPhone
    Safari 설정화면

iPhoney (Mac OS용) - iPhone을 기본화면으로 하고 있으며 iPhone 화면 크기에 맞게 작업물을 확인 할 수 있습니다. TestiPhone 이나 iPhone Tester 과 비슷하며 추가적으로 확대기능, 그리고 User Agents 를 변경 할 수 있습니다.

Internet Explorer

Internet Explorer 브라우저는 시스템 레지스트리값을 변경하여 확인 할 수 있습니다.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent] 의 데이터값을 위의 모바일 단말의 브라우저 User Agent 로 설정

하지만 매번 설정 변경과 원상복구를 해야하는 불편함과 레지스트리값 변경으로 인한 시스템 오류가 있을 수 있으니 권장하지 않습니다.

테스트 가능한 모바일 서비스

아래 서비스는 User Agent String을 체크해 PC와 Mobile 사이트로 각각 이동시켜 줍니다.

아래 서비스는 User Agent String을 체크해 Mobile 단말일때만 서비스 접근을 허용한 서비스 입니다. (주로 PDA용 사이트)

아래 서비스는 User Agent String 값과 관계없이 확인 가능한 모바일 서비스입니다. 주소에서도 알 수 있듯이 특정 브라우저에 최적화된 서비스가 대부분입니다.

마치며

위와 같이 Firefox add-on 및 Safari,IE 설정 변경으로 모바일 관련 서비스를 간단히 둘러보고 소스보기,응용 작업을 할 수 있습니다. (서버 설정에 따라 다른 사용자 정보를 가지고 접근을 제한할 때는 접근하지 못하는 경우도 있습니다. )
하지만 실제 마크업 작업 후 디버깅 시에는 브라우저 뿐만 아니라 다양한 단말의 화면크기에 따라 테스트를 해야 하므로 테스트 기기로 디버깅 하는 것이 정확합니다.

참고자료
  1. http://paininthetech.com/2007/10/03/fake-iPhone-user-agent/

 

반응형
반응형
1. 사이즈설정
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=medium-dpi" />
 
모바일 브라우저에 맞게 사이즈가 정해지도록 하는 소스.
densitydpi가 medium-dpi이면 아이폰이나 갤럭시나 같은 사이즈로 보이는 걸 보니다른 스마트폰에서도 동일하게 보일 것 같다.
high-dpi로 하면 갤럭시는 가로가 480사이즈로 보인다.


2. 주소줄 설정
<script type="text/javascript">
window.addEventListener('load', function() {
setTimeout(scrollTo, 0, 0, 1);
}, false);
</script>
 
주소줄이 없어지게 하는 소스라고 한다.


3. 모바일 홈페이지로 이동하기
모바일 홈페이지용 주소가 따로 없을 때,
일반 홈페이지와 같은 주소로 접속하면 자동으로 모바일용 페이지로 이동시켜주는 소스
접속환경을 체크해서 이동시키는 소스라 이 소스에 없는 모바일기종은 그냥 일반 페이지가 나올 듯...

3-1. PHP용
<?
$arr_browser = array ("iPhone","iPod","IEMobile","Mobile","lgtelecom","PPC");
for($indexi = 0 ; $indexi < count($arr_browser) ; $indexi++) {
if(strpos($_SERVER['HTTP_USER_AGENT'],$arr_browser[$indexi]) == true){
header("Location: 이동할 경로");
exit;
}
}
?>

3-2.ASP용
<%
mobrwz = "iPhone|iPod|IEMobile|Mobile|lgtelecom|PPC"
spmobrwz = split(mobrwz,"|")
agent = Request.ServerVariables("HTTP_USER_AGENT")
For i = 0 To UBound(spmobrwz)
If InStr(agent,spmobrwz(i)) > 0 Then
Response.Redirect("이동할 경로")
Exit For
End If
Next
%>

3-3. 자바스크립트
<script type="text/javascript">
var ua = window.navigator.userAgent.toLowerCase();
if(/iphone/.test(ua) || /android/.test(ua) || /opera/.test(ua) || /bada/.test(ua)) {
document.location.replace('이동할 경로');
}
</script>

반응형
반응형

기본적 검색의 섬세함 


어 떤 검색엔진이나 섬세한 검색을 지원한다. 다만 우리가 관심이 없거나 귀찮기 때문이다. 검색엔진에 따라서 방법이나 문법은 다르기 때문에 자신이 자주 사용하는 검색엔진에 따라서 찾아보고 여기에서는 구글의 검색에서 좀 더 섬세하게 검색할 수 있는 방법을 소개한다. 


구글 검색은 특별히 키워드만 잘 선택하면 자신이 찾고 싶은 정보들을 잘 보여주는 편이다. 다음의 내용을 알아두면 좀 더 섬세한 검색에 도움이 될 것이다.

참고: Operators and more search help by Google


image all the people → "imagine all the people"

jaguar speed →   jaguar speed -car  : 검색어 제외 

~food facts : 정확한 표현이 생각나지 않을 때 nutrition facts 등과 같은 유사한 내용을 검색에 포함 

Olympics site:nytimes.com  : 해당 사이트 내에서만 검색할 때 site: 

Olympics site:.gov : .gov 도메인을 가지는 사이트 내에서 검색할 때 

"a * saved is a * earned" : 전역 검색 (wildcard) 라고 불리우는 중간 키워드가 생각나지 않을 때, a saved is a earned 와 같이 생각나는 키워드만 입력해도 찾을 수 있지만 wildcard 를 사용하면 문장 구조에 맞는 검색을 찾아준다. 

olympics location 2014 OR 2018 : OR 검색을 한다. 

camera $50..$100 : from .. to 사이의 해당하는 모든 영역을 검색한다. 

"les miserables" filetype:pdf : 파일형식이 pdf 인 것을 찾는다. 


직 관적으로 알기 쉽기 때문에 검색 창에서 바로 문법을 이용해서 입력하면 좀 더 섬세한 검색이 가능하다. 특히 " " 으로 묶어주거나 제외 (- ) 검색어 그리고 site: 와 filetype: 은 아주 유용하기 때문에 해당 검색어는 습관적으로 익혀두고 있으면 좋을 것이다. 해당 문법은 구글 일반 검색 뿐만 아니라 다른 검색 형태의 검색엔진에서도 비슷하게 적용된다. 보다 섬세한 검색을 원한다면 

http://www.google.com/advanced_search  에서 검색하거나 생각나는 키워드를 검색한 다음 이후 검색 결과 위에 나와 있는 검색 옵션을 바꾸는 항목으로 좀더 검색 결과를 좁혀갈 수 있다. 


논 문 검색에 사용되는 구글 학술검색 (google scholar) 의 경우에도 일반적 검색 문법을 지원하지만 특정 저널 등을 정해주고 싶을 때는 검색창에 있는 ▼ 마크를 눌러 검색을 좀더 정확하게 할 수 있다. 일반적 검색 문법은 검색엔진 뿐만 아니라 쥐메일, 구글 드라이브와 같이 구글이 제공하는 웹 서비스 안에서도 동일하게 사용할 수 있다. 특히 쥐메일에서 특정인에게서 받은 메일이나 특정 내용이 포함된 메일에 라벨을 자동으로 붙일 수 있도록 필터를 만들때도 동일하게 사용될 수 있다. (참고: 쥐메일 검색에서 OR 와 함께 | 기호를 통해서도 포현할 수 있다.) 


구글 학술검색 (Google Scholar) 의 세부 검색 화면


주기적으로 검색하는 수고도 하기 싫다... 


자 신이 찾고자 하는 검색 내용이 주기적으로 입력해줘야 하는 번거로움이 있을 수 있다. 예를 들어 자신이 연구하거나 관심있어 하는 영역에서 어떤 내용들의 글이 올라오나, 어떤 정보가 새롭게 변경되었는지 생각날때마다 검색을 할 수 있지만 그러한 불편도 해결해줄 수 있는 서비스가 있다. 구글 알림(google alerts)이 바로 그런 서비스이다. 앞서 설명한 섬세한 검색을 소개한 이유는 일반적인 키워드 검색에서 발생할 수 있는 원하지 않는 정보들을 걸러내고 자신에게 필요한 정보를 가려내기 위한 방법이고 그렇게 가다듬어진 키워드와 문법을 매번 생각날때마다 주기적으로 검색할 필요없이 해당 키워드로 검색된 내용이 있으면 메일로 알려주는 서비스이다. 



자 신이 원하는 키워드, 검색 영역, 빈도, 검색 결과, 메일 수신인 등을 넣고 입력하면 설정에 따랏 자신에게 맞는 메일로 보내준다. 특별히 자신이 검색을 주기적으로 하지 않아도 관심 분야나 확인해야 하는 내용들을 받을 수 있다. 예를 들어 자신의 연구분야에 대한 주기적인 내용도 받아볼 수 있고 검색엔진에서 나타나는 자신의 개인정보 등 노출되지 않았으면 하는 내용, 자신의 블로그 글 내용을 복사하거나 무단으로 복사하는 내용 등을 검색하는데도 응용할 수 있을 것이다. 


자연스럽게 검색하자... 


검 색은 키워드를 기반으로 해서 검색을 하지만 자신의 문제를 해결하기 위한 동사를 적절하게 넣는 것이 좋다. 예를 들어 자신이 찾고 싶어하는 내용이 windows 7 에서 control panel 을 비활성화하는 방법을 찾고 싶을 때 명사에 해당하는 


windows 7 control panel  만 입력하게 되면 해당 키워드가 들어간 관련 없는 내용들도 포함되게 된다.


이때 좀 더 정확한 검색을 위해 묶음 표시를 먼저 사용하면... 


"windows 7" "control panel" 으로 검색할 수 있다. 그러나 해당 검색으로는 무엇을 하고 싶다는 내용을 표시하지 않기 때문에 비활성화하고 싶다는 disable 을 넣어서 검색한다. 


disable "windows 7" "control panel" 으로 범위를 좁혀 나갈 수 있다. 그런데 여기에서 자연어에 가까운 검색으로 변경해보자. 


disable "control panel" "windows 7" 으로 동사에 해당하는 목적어를 바로 뒤에 두는 것이 검색에 있어서도 더 현명한 판단이다. 왜냐하면 자신이 찾고자 하는 정보를 담고 있는 페이지도 자연어를 사용해서 정보를 포함하기 때문이다. 그 이외에 레지스트리를 건드리지 않는 것을 원한다면 -registry 해서 키워드를 넣을 수 있지만 이또한 -"edit registry" 와 같이 자신이 원하지 않는 동사, 목적어를 명시해서 제외시키는 방법도 더 좋을 것이다. 


결 국 검색어도 자연스럽게 대화하듯이 검색을 하게 되면 검색을 좀더 섬세하게 할 수 있다는 것이다. 그외 검색기간을 통해서 오래된 정보를 제외해야 하는 경우도 생각하고 파일 형식이나 다양한 검색 문법을 통해서 자신이 원하는 정보를 줄여 나가는 것도 가능할 것이다.

반응형
반응형