기반지식/C/C++2010. 6. 9. 19:36
Posted by windship
기반지식/C/C++2010. 6. 7. 20:41

☆ 교육과정
 - 1주차 : 자료형, 출력, 연산자, 제어문
 - 2주차 : 배열, 포인터, 함수
 - 3주차 : 함수(계속), 구조체, 클래스

☆ 불러올 때에는 workspace(하나의 프로젝트, dsw 파일) 째로 불러온다

☆ 비주얼C++에서 일반적인 source파일을 만들 경우는 cpp(c++) 확장자가 자동으로 붙으므로, 그냥 c 파일을 만들 경우는 이름을 정할 때 끝에 .c까지 확실하게 붙여주면 c 파일로 저장된다.

☆ void main() - 함수
 - 앞의 void는 리턴값의 타입. void는 리턴값이 필요없을 때에 사용(그래서 main() 함수에 사용한다)
 - 함수에는 대괄호 { }가 붙는데, 이 대괄호 안에서 변수를 선언하면 그 안에서만 사용되는 지역변수가 된다.
 - 하나의 프로젝트 안에 같은 이름의 함수는 존재할 수 없다

☆ #include와 같이 #이 붙으면 전처리문이 된다
 - #include 뒤에는 < >가 올 수도 있고 " "가 올 수도 있다

☆ \뒤에 알파벳이 붙는 것은 "제어문자열"이라고 한다. printf(" ") 안에서 사용된다
 - \n : 커서위치 다음줄로 줄 바꿈(next)
 - \t : 탭공백 넣기(tab)
 - \b : 커서위치 한글자 앞으로(back)
 - \a : 경고음 출력(alert)
 - \r : 엔터(return)


☆ 경로명을 취급할 때 \가 붙으면 제어문자열로 판단해 버리기 때문에, 경로명의 "\"를 입력하기 위해서는 "\\"와 같이 2번 써준다

☆ 마찬가지로 문자열에 " "를 그냥 사용하면 printf 명령이 중간에 닫혀버리기 때문에, 따옴표를 그대로 문자열로 사용하기 위해서는 \"과 같이 앞에 \를 붙여준다

☆ MSDN으로 명령어에 대해 알아볼 경우 해당 명령어 위에 마우스 커서를 갖다두고 F1키를 입력한다
 - 그 명령어에 필요한 헤더 파일도 찾아볼 수 있다

☆ 자료형(변수의 종류)

 * 기본형
  - 정수형(Integer)
  - 문자형
  - 실수형
  - 열거형
  - void형 : 타입이 없는 자료형

 * 유도형
  - 배열 : 같은 타입의 자료 집합
  - 구조체 : 다른 타입의 자료 집합
  - 공용체 : 메모리를 공유하는 자료 집합
  - 포인터 : 대상의 메모리 주소(번지)를 가리키는 타입
  - 함수형 : 함수의 메모리 주소(번지)를 가리키는 타입

☆ 변수 여러개를 한꺼번에 선언할 때는 콤마로 이어서 해준다
 - int a, b, c <ㅡ이런 형식

☆ 변수 선언시 앞에 unsigned를 붙이면 부호 비트를 없앤다는 뜻이다
 - 자료형의 허용범위 2배 정도로 늘어난다
 - 음수 표현은 불가능해진다

☆ printf("a=%d(%d Byte)\n",a,sizeof(a));
 - printf의 따옴표 안에 들어가는 변수 값은 따옴표를 닫은 뒤 뒤에 붙게 된다.
 - 즉 빨간색 %d는 빨간색 a, 녹색 %d는 녹색 sizeof(a)의 값이 출력된다.

☆ 변수 선언시에는 a=0과 같이 미리 초기값을 넣어서 초기화를 해주는 것이 좋다. 그렇지 않으면 쓰레기 값이 들어가 버린다

☆ 변수에 정한 자료형의 범위를 벗어난 값이 들어가면 에러가 나거나, 에러가 나지 않아도 프로그램이 자료형에 의해 값을 수정해 버린다. 변수에 값이 들어갈 때에는 자료형의 허용범위와 맞는지 확인해야 한다

☆ (a) printf("%d Byte\n",sizeof(5/3));
    (b) printf("%d Byte\n",sizeof(5.0/3));

 - (a)의 경우 값은 1이 된다(5, 3이라는 상수값이 모두 정수형이므로 실수가 될수없다)
 - (b)의 경우 값은 1.6이 된다(5.0이라는 상수값이 실수이므로 실수 값이 허용된다)

☆  int a=9;
    int b=4;
    double c,d;
    c=a/b; // 정수형끼리의 계산은 무조건 정수형으로 된다.
    d=(double)a/b; //(자료형) cast 연산자라 함. 강제형변환

    printf("c=%.2lf\n",c);
    printf("d=%.2lf\n",d);

 - 3행에서 c에 double을 선언하더라도 이미 1, 2행에서 a와 b는 정수형이기 때문에 c 값에는 정수만 들어간다.
 - 실수 결과값을 얻고 싶으면 a나 b를 실수형으로 바꾸면 되지만, 경우에 따라 그쪽의 자료형을 고정하고 싶을 때가 있다. 이런 경우는 강제 형변환을 사용한다.
 - 5행에서 들어간 것처럼 수식의 앞에 ( )를 치고 자료타입을 선언하면 수식의 결과값을 강제로 원하는 자료타입으로 바꿔준다. 실제 코딩에서 자주 사용하게 되는 방법이다.

☆ void main()
   {
    int a=55; //10진
    int b=055; //8진
    int c=0x55; //16진

    printf("a=%d, b=%o, c=%x\n",a,b,c);
    printf("a=%d, b=%#o, c=%#x\n",a,b,c);
   }

 -  //변환기호
    //정수형 : %d(10진), %o(8진), %x(16진)
    //실수형 : %f(고정소수점), %e(지수형), %g(혼합형)
    //위 자료형들은 float이며, double일 경우는 앞에 L을 붙인다.
    //문자형 : %c(1바이트), %s(문자열)
 - 타입 앞에 b=%#o 와 같이 # 표시를 붙여주면 값을 해당 진법의 표기 형식에 맞게 보여준다

☆  printf("a=%04d\n",a); -> 4d로 하면 값을 4자리로 보여주며, 앞에 0이 붙으면 빈 자리를 0으로 채운다
     printf("a=%4d\n",a); -> 4d로 해서 값을 4자리로 보여주지만 별다른게 없으므로 빈 자리는 빈칸이 출력
     printf("a=%-4dHi!\n",a); ->4d로 값이 4자리가 되지만 -가 붙으면 빈칸을 뒤에 붙인다
      a=0055
      a=  55
      a=55  Hi!

Posted by windship
모바일 WEB 관련2010. 6. 5. 01:47
아이폰 개발시 필요한 내용을 잘 정리해 놓은 자료가 있네요~
원본: http://trend21c.tistory.com/824


1. 아이폰용 css 적용하기

<!--[if !IE]>--> 
<link  
   rel="stylesheet"  
   href="small-screen.css"  
   type="text/css"  
   media="only screen and (max-device-width: 480px)"  
/> 
<!--<![endif]-->



@media only screen and (max-device-width: 480px) { 
/* iPhone only CSS here */
 #test-block { 
   background: red; 
 } 
}


아이폰은 max-device-width가 480px로 정의되어 있습니다.

위 두개의 코드는 이러한 값을 이용하여 아이폰용 css를 추가하는 방법입니다.

범용적인 스타일시트로 모바일 웹어플리케이션을 개발후

아이폰에서는 더 나은 UI를 만들기 위해 위와 같이 아이폰용 CSS를 추가함으로써

아이폰의 사파리브라우저로 접속하는 사용자들에게 다른 UI를 제공해줄수 있습니다.



2. 아이폰용 서버측 코드 실행하기

<?php
  $browser = strpos($_SERVER['HTTP_USER_AGENT'],"iPhone");
    if ($browser !== false){
    $browser = 'iphone';
  }
?>


<?php if($browser == 'iphone'){ ?>
  <title>Short iPhone only title</title>
<?php }else{ ?>
  <title>Regular title</title>
<?php } ?>


php의 경우 user-agent 값을 이용해서 서버측에서 아이폰을 위한 코드를 별도로 실행이 가능합니다.



3. viewport meta 태그

아이폰은 meta태그의 viewport를 이용해서 더 나은 UX를 제공해줄수 있습니다.

예를 들면 기기의 

최대 가로크기를 정한다거나, 줌레벨을 정한다거나, 사용자 확대축소 방지 여부 등을 설정할 수 있습니다.



<meta name="viewport" content="width=device-width" />
<meta name="viewport" content="width=780" />
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
maximum-scale=1.0 



width=device-width

이 값은 페이지를 기기의 width에 맞도록 출력합니다. 아이폰은 320*480의 세로보기 모드와 480*320의 가로보기 모드를 가지고 있습니다. width=780 과 같이 특정 값을 정의할 수도 있지만, 가로, 세로보기 모드에 최적화 시키기 위해서 width=device-width로 설정하는 경우 기기의 width값에 맞춰서 페이지를 보여줍니다.


initial-scale=1.0

이것은 페이지가 로딩될때 확대비율을 정할수 있습니다. 값이 커질 수록 확대 비율된 모습으로 페이지가 나타납니다.



maximum-scale=1.0

허용가능한 확대비율의 최대치를 설정합니다.



user-scalable=0

사용자의 확대보기를 허용할지 여부를 설정합니다. 값은 0(허용하지 않음), 1(확대보기 허용함) 입니다.






<meta name="viewport" content="width=device-width" /> 를 설정했을때




<meta name="viewport" content="width=device-width" />를 설정 안했을때




위의 두개의 예시화면처럼

viewport를 width=device-width 로 설정한 경우에는 

페이지의 가로길이를 기기에 맞춰서 페이지를 보여주지만

설정이 되어있지 않은 경우 

사파리브라우저는 마치 자신이 데스크탑브라우저인양

페이지를 넓게 인식하여 보여줍니다.



4. 툴바 숨기기

window.addEventListener('load', function(){
  setTimeout(scrollTo, 0, 0, 1);
}, false);




위 스크립트를 사용하면 사파리브라우저의 

주소입력창과 검색창이 있는 툴바를 보이지 않는 상태로 변환합니다.

툴바가 사라지는 것이 아니라

스크립트를 통하여 스크롤을 아래로 내려 

툴바 바로 아래에서부터 웹페이지가 보여질수 있도록 하는것입니다.

이 스크립트를 사용하는 경우 사용자에게 최초로 페이지를 보여줄때 

툴바가 차지했던 부분까지 화면공간을 확보하여 보여줄 수 있습니다.

그리고 보기에도 확연히 넓어보이는 것을 느낄수 있습니다.





간혹 페이지 콘텐츠 길이가 너무 짧아서 스크롤할 내용이 없을때 

이 스크립트는 우리가 원하는 기능을 수행하지 않을 수도 있습니다.

그리고 페이지 콘텐츠 길이가 스크롤을 내리기에 어정쩡한 길이라면 

툴바가 보여지지도 사라지지도 않은 반쯤 가려진 상태로 보이게 되는 경우도 있습니다.

위의 캡쳐 사진이 그 예입니다. 

콘텐츠 길이가 어정쩡해 툴바가 가려질 만큼 스크롤바가 내려가지 않아

툴바가 절반만 가려진 모습입니다.



이런문제를 해결하기 위해서는 높이값을 최대사이즈로 지정하여 

페이지가 스크롤될 수 있게 할 수 있습니다.


<meta name="viewport" content="height=device-height,width=device-width" />



viewport를 이용해 height=device-height 를 설정하면

height가 기기의 height값이 되도록 설정되기 때문에 콘텐츠 길이가 짧더라도

페이지 최초 로딩 후 툴바가 보이지 않게 됩니다.



5. 기울기변화 감지하기

window.onorientationchange = function() {
  alert(window.orientation); 
}



0 : 일반적인 세로 화면(홈 버튼이 아래에 있음)
-90 : 시계 방향으로 회전된 가로 화면(홈 버튼이 좌측에 있음)
90 : 시계 반대 방향으로 회전된 가로 화면(홈 버튼이 우측에 있음)
180 : 180도 뒤집힌 화면(홈 버튼이 위에 있음)


가로보기 모드와 세로보기 모드에서 다른 UI를 제공하려는 경우

이 이벤트를 동해서 특정 스크립트를 실행할 수 있습니다.



보기 모드에 따라 다른 UI를 제공한다거나 하는 특별한 이유가 없다면

viewport에서 <meta name="viewport" content="width=device-width" />를 설정함으로써

width가 보기 모드에 따라 자동 조절되기 때문에 걱정할 것이 없습니다.



6. 라운드박스, 라운드버튼


.box {  
   -webkit-border-radius: 5px;  /* safari */
   -moz-border-radius: 5px;  /* firefox */
   background: #ddd;  
   border: 1px solid #aaa;  
}







사파리 브라우저에서는 사파리브라우저의 css 속성을 이용하여

쉽게 라운드박스, 라운드 버튼을 구현할 수 있습니다.



7. 터치 이벤트

touchstart
touchend
touchmove
touchcancel (시스템이 터치한 것을 취소하는 경우)


위의 것들은 터치관련 이벤트 입니다.


이벤트 발생시 event객체를 전달 받는데 다음과 같은 프로퍼티가 존재합니다.



touches : 복수로 화면에 터치되는 각 손가락들에 대한 터치 이벤트 모음들. 이 객체들은 페이지에 터치되는 좌표들의 값을 가지고 있습니다.
targetTouches : 터치할 때 발생합니다. 그러나 전체 페이지가 아닌 타깃 요소에만 반응합니다.



8. 제스쳐

gesturestart
gestureend
gesturechange

제스처 관련 이벤트 입니다. 

event 객체를 전달받으며 다음과 같은 프로퍼티가 존재합니다.

event.scale : 확대비율 값입니다. 값 1은 확대축소가 되지 않은 기본 상태 입니다. 값이 1보다 작을 때는 줌-아웃이며 줌-인일때는 1보다 값이 큽니다.
event.rotate - 회전 각도입니다.



9. 특수링크

<a href="tel:12345678900">Call me</a>
<a href="sms:12345678900">Send me a text</a>

아이폰은 통화 또는 SMS 보내기를 실행할수 있는 특수 링크가 있습니다.

'tel:번호'로 이루어진 링크는 전화연결이 되며
'sms:번호'로 이루어진 링크는 sms가 연결됩니다.







이외에도

아이튠즈 스토어 링크는 아이튠즈와 연결됩니다.

구글맵 링크는 지도 애플리케이션과 연결됩니다.

유튜브 링크는 유튜브 애플리케이션과 연결됩니다.

이메일 주소 링크는 메일 애플리케이션에 연결됩니다.




10. 홈아이콘





사파리 브라우저를 이용하여 웹서핑을 하면서 하단에 + 탭을 클릭하면

현재 페이지를 책갈피(북마크, 즐겨찾기) 추가하거나

홈화면에 추가할 수가 있습니다.






여기서 말하는 홈화면에 추가란 

아이폰의 바탕화면에 아이콘이 생성되어 웹페이지로 빠르게 연결할 수 있는 것을 말합니다.


<link rel="apple-touch-icon" href="http://www.example.com/iphone_home_icon.png" />


이 코드를 넣으면 여기에 설정된 이미지 파일이 홈아이콘으로 설정됩니다. 

홈아이콘은 57*57의 png파일로 만드는 것이 좋습니다.

아이폰에서 자동적으로 볼록 튀어나와보이는 듯한 효과와 아이콘의 라운딩처리를 하기때문에

홈아이콘은 정사각형의 모양으로 만드셔도 됩니다.

홈아이콘이 설정되어있지 않을 경우 

해당 웹페이지의 썸네일화면이 홈아이콘으로 설정됩니다.



11. 디버깅


console.log('Something');
console.error('Oops');
console.warning('Beware!');





위의 코드를 실행하였을 경우 아이폰 사파리 브라우저의 콘솔디버그 도구는 다음과 같은 메시지를 표시합니다.

디버깅용으로 사용되는 함수들입니다.

아이폰 사파리브라우저에서 콘솔디버그 도구를 사용하는 방법은

제가 지난번에 쓴 포스팅에 자세히 나와있습니다.





스마트폰 시장이 발달하고 무선인터넷이 보편화되고, 네트워크이용요금이 점점 낮아지고 있습니다.

스마트폰 시장에서는 저마다의 독자적인 플랫폼들이 속속 자신의 영역을 넓히려 하고 있습니다.

특정기기에 최적화된 어플리케이션은 만드는 것은

사용자경험을 극대화한다는 점에서 좋으나

안드로이드용, 아이폰용, 윈도모바일용 등 플랫폼별로 어플리케이션을 개발해야하는 비용이 뒤따릅니다.


반면 어떠한 플랫폼이든 웹브라우저가 있기때문에

웹어플리케이션은 많은 비용을 절감하면서

스마트폰 사용자들의 기대를 충족시켜줄수 있습니다.


아이폰용 웹어플리케이션을 개발하려고 하신다면 위의 사항을 꼭 알아두시면

개발에 많은 도움이 되실겁니다.


  Commented by 별제이 at 2010/03/22 15:35  r x

http://firejune.com/1506
이곳도 참고~ 중복이 좀 있긴 한데...다른 내용도 있네요~ 


  Commented by 별제이 at 2010/03/23 11:57  r x

http://cafe.naver.com/webstandardproject/349
참고 사이트~
검색키워드: onorientationchange 


  Commented by 별제이 at 2010/03/22 20:57  r x

아이폰 웹 사이트 팁! Tip&Tech
세로보기때 320 픽셀에 딱 맞춘상태인데 좌우로 스크롤 되는 현상이 가끔있다.
특정 div에서 paddding 등을 사용할 경우 주로 이런 현상이 발생하는데...
이를 해결 하는 방법은
body { overflow: hidden; } 또는 
body { overflow: auto; }
속성을 사용하면....해결된다!!! 


  Commented by 별제이 at 2010/03/22 20:24  r x

http://bongdal.tistory.com/63

지도 어플 실행하기
조금 특이한 부분으로 애플과 구글의 제휴로 인해 실행되는부분인듯합니다.
그냥 Anchor 태그에 구글맵 주소를 입력하면 자동으로 구글 지도 어플을 실행시킵니다.

<a href="http://maps.google.com/maps?q=seoul&z=5">서울지도보기</a>
<a href="http://maps.google.com/maps?daddr=seoul&saddr=busan">서울-부산 길찾기</a>


Google Maps parameters
Table 1 Supported Google Maps parameters Parameter
Notes

q=
The query parameter. This parameter is treated as if it had been typed into the query box by the user on the maps.google.com page. q=* is not supported

near=
The location part of the query.

ll=
The latitude and longitude points (in decimal format, comma separated, and in that order) for the map center point.

sll=
The latitude and longitude points from which a business search should be performed.

spn=
The approximate latitude and longitude span.

sspn=
A custom latitude and longitude span format used by Google.

t=
The type of map to display.

z=
The zoom level.

saddr=
The source address, which is used when generating driving directions

daddr=
The destination address, which is used when generating driving directions.

latlng=
A custom ID format that Google uses for identifying businesses.

cid=
A custom ID format that Google uses for identifying businesses.

YouTubu 어플 실행하기
역시, Anchor 에서 youtube와 연결된 링크가 있을경우 자동으로 내장된 YouTubu 어플이 실행됩니다.
웹상에서는 위의경로는 웹페이지에서 실행되며, 아래의 경로는 전체화면 플레이어가 실행됩니다.

<a href="http://www.youtube.com/watch?v=a_GaLdTbOG4">YouTube Play1</a>
<a href="http://www.youtube.com/v/a_GaLdTbOG4">YouTube Play2</a>

아이튠즈 및 앱스토어 실행하기
아래의 URL로 앱스토어 및 아이튠즈 어플이 실행가능합니다.
한가지 주의 할점은 앱스토어의 경우 "http://itunes.apple.com/kr/app/id304608425?mt=8" 어플이 일반적인 경로(일반 web에서 사용)이나, 모바일 사파리에선 내부에서 자동으로 아래 패턴으로 변경하여 사용합니다. 하지만 어플위에 올라간 UIWebview 컨트롤상에서는 따로 구현해주지 않으면 앱스토어 넘어가지 않습니다.

<a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=304608425&cc=kr&mt=8&ign-iphone=1 ">지도어플(앱스토어 연결)</a>
<a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?i=156093464&id=156093462&s=143441">Toy Story OST(itunes 연결)</a> 


  Commented by 별제이 at 2010/03/22 22:01  r x

http://firejune.com/1247

window.onorientationchange = function() {
var orientation = window.orientation;
switch(orientation) { 
case 0: document.body.setAttribute( "class","portrait" );
document.getElementById( "currentOrientation" ).innerHTML = "Now in portrait orientation (Home button on the bottom).";
break;
case 90: document.body.setAttribute( "class","landscapeLeft" );
document.getElementById( "currentOrientation" ).innerHTML = "Now in landscape orientation and turned to the left (Home button to the right).";
break;
case -90: document.body.setAttribute( "class","landscapeRight" );
document.getElementById( "currentOrientation" ).innerHTML = "Now in landscape orientation and turned to the right (Home button to the left).";
break;
}


  Commented by 별제이 at 2010/03/23 10:52  r x

http://www.iphonewebdev.com/examples/hideurl.html

// 아이폰 사파리 툴바 없애기 (IE에서도 에러 없다)
if (navigator.userAgent.indexOf('iPhone') != -1) {
addEventListener("load", function() {
setTimeout(hideURLbar, 0);
}, false);
}
function hideURLbar() {
window.scrollTo(0, 1);


  Commented by 별제이 at 2010/03/30 16:21  r x

mobile safari keyboard type / form 샘플

http://www.smashingmagazine.com/2010/03/11/forms-on-mobile-devices-modern-solutions/
Posted by windship
모바일 WEB 관련2010. 6. 3. 22:48
<script>
//불여우 2/3 버전 감지 by DoctorDan
var FF=/a/[-1]=='a';

//불여우 3 by 원작자
var FF3=(function x(){})[-5]=='x';

//불여우 2 by 원작자 
var FF2=(function x(){})[-6]=='x';

//자신이 전에 올렸던 IE 감지
var IE='\v'=='v';

//사파리 by 원작자
var Saf=/a/.__proto__=='//';

//크롬 by 원작자
var Chr=/source/.test((/a/.toString+''));

//오페라 by 원작자
var Op=/^function \(/.test([].sort);

//위에 모든걸 통틀어 브라우저 인식하는 한줄 스크립트 
var B=(function x(){})[-5]=='x'?'FF3':(function x(){})[-6]=='x'?'FF2':/a/[-1]=='a'?'FF':'\v'=='v'?'IE':/a/.__proto__=='//'?'Saf':/s/.test(/a/.toString)?'Chr':/^function \(/.test([].sort)?'Op':'Unknown'

//보너스:링크 #2에서 발췌한 IE 감지 스크립트 
var IE=!!top.execScript
document.write(B);
</script>
<SPAN id=tx_marker_caret></SPAN>


출처 : http://towis.net/2690114
Posted by windship
모바일 WEB 관련2010. 6. 3. 21:59

<HEAD> </HEAD> 사이에 다음 태그를 넣는다.

<script type="application/x-javascript"> 

    if (navigator.userAgent.indexOf('iPhone') != -1) 
    { 
        addEventListener("load", function() 
        { 
        setTimeout(hideURLbar, 0); 
        }, false); 
    } 

    function hideURLbar() 
    { 
        window.scrollTo(0, 1); 
    } 
</script> 

Posted by windship
모바일 WEB 관련2010. 6. 3. 17:21

아이폰 웹페이지 이것만 알아도 유용하다.

<head></head>사이에 아래의 한줄을 집어넣어보자.

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />  

위의 한줄을 집어넣음으로써 아이폰의 해상도에 적절하게 화면이 표시될 것이다.
간단한 내용이지만 한부분씩 살펴보겠다.

width=device-width; 
이부분은 영문 그대로 웹페이지의 너비를 기기의 너비대로 보여주라는 얘기다.
아이폰은 320 x 480의 해상도를 갖고 있으므로 320px에 맞춰주는 역할을 한다.

initial-scale=1.0;
초기화면 로딩시 몇배로 보이게 할 것인가를 지정해주는 부분이다.
당연한 얘기지만 1.0으로 지정하면 1배로 보이게 된다.

maximum-scale=1.0;  1배 까지 확대가능. 즉, 확대 불가를 의미한다.
아이폰은 멀티터치를 이용해서 화면을 맘대로 키우거나 줄일 수 있다. 
그러나 때로는 웹사이트가 멀티터치로 화면크기 조절이 안되는걸 볼 수 있는데 
이는 바로 이 옵션이 1로 적용되었기 때문이다.

maximum-scale=10.0; 이렇게 지정하면 10배까지 확대가 가능해진다.

user-scalable=0; 이부분은 멀티터치를 확용한 확대를 허용할 것인가의 여부를
결정하는 부분이다. 위에서 maximum-scale의 숫자를 키우면 해당 숫자 배수까지
화면이 커질 수 있다고 설명했지만 user-scalable가 0으로 되어있으면 작동하지 않는다.

반대로 user-scalable가 1이 적용되어 확대조절을 허용하더라도 
maximum-scale이 1.0으로 되어있으면 화면 확대가 안된다.

 

아래에 예제 하나를 제시한다.

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=10.0; user-scalable=1;" /> 

 위의 예제의 설정은 웹페이지를

1) 아이폰 화면에 맞추며,
2) 처음 크기는 1배로,
3) 그러나 10배까지 키울 수 있다.


아이폰을 위한 웹페이지의 가장 기초적인 부분이지만, 응용해서 좋은 웹사이트를 제작하시길 바랍니다.


---


출처 : http://ozahir.com/941

Posted by windship
iPhone 개발절차/준비2010. 5. 28. 14:47


아이폰 개발자 등록방법 을 묻는 질문들이 포털에 많이 올라오고 있습니다.
결제만 한글로 되어있고 신청은 영어로 해야되서 그런지 사람들이 좀 어려워 하는 것 같아서 캡쳐를 해보았습니다.

 영어를 만나면 머리가 어지러워지는 관계로.. 최대한 자세히 캡쳐하면서도 설명은 간락하게 했습니다. ^^; 

많은 도움이 되었으면 좋겠네요. (참고로 web2log라는 회사 명의로 개발자 등록을 했습니다.)



http://developer.apple.com/iphone/index.action
  페이지에 들어갑니다. 이제 시작이죠 후훗


아이디를 가지고 계신분들은 로그인을 하시면 됩니다. 저는 새로 아이디를 만들었습니다.


상단 부분은 아이폰 개발 프로그램, 아래부분은 맥 개발자 프로그램입니다.
우선 상단에 첫번째는 개인개발자입니다. 두번째 체크한 부분은 회사로 등록하는 거구요. 
세번째는 500명 이상의 직원을 가진 회사가  사내에서만 쓸 수 있는 어플리케이션을 등록하는 엔터프라이즈 계정입니다. 
마지막은 대학에서 아이폰개발을 교육용으로 쓰기위해서 받는 무료 프로그램입니다.


일년에 99달러(결과적으로 104,000원)를 내면 된다는군요 , 파란색 등록버튼을 눌러줍니다. 


간략하게 개발 프로세스를 설명해주고 있네요 , 컨티뉴~~!!고고


기존 개발자인지 새로운 개발자인지를 물어보는군요. 
저는 새롭게 개발자 등록을 하는 것 중에서 계정도 새로만든다고 체크했습니다.


개인으로 가입할 것인지 회사이름으로 가입을 할 것인지를 묻는 창입니다. 회사로 가입하였습니다.


아이디와 비밀번호 생년월일, 그리고 이름, 이메일 국가, 지역 등의 개인정보까지 입력해줍니다.


첫질문으로 어떤 플랫폼을 개발할 것인지를 묻습니다. 
아이폰 운영체제, 맥OS X 등을 체크하고 원하는 시장과 유료/무료 어플리케이션을 개발할 것인지, 
개발은 얼마나 경력이 있는지 , 다른 모바일 플랫폼에서도 개발을 할 계획인지 등을 체크해줍니다.


약관을 술술술 대충 읽고나서 체크박스 체크한 뒤 동의 버튼을 누릅니다.


아까 적은 이메일로 숫자가 여섯자린가 일곱자리가 옵니다. 메일로 받은 숫자를 입력하고 컨티뉴~~고고


회사 정보들을 입력해 줍니다.


회사 정보를 입력하시면 되겠습니다. 법적으로 책임질 수 있는 확실한 정보를 입력하라네요.


입력하신 정보를 확인하고 맞으면 컨티뉴 ~~고고


입력이 일차적으로 끝났습니다. 여기까지 하셨으면 그다음 메일을 기다리셔야 합니다. 
요 메일은 바로 옵니다.


접수된 아이디(Enrollment ID)가 메일로 옵니다. 음.. 이건 다음 메일이 왔을때 필요합니다.


네 이게 팩스번호입니다. 팩스에다가 회사 영문 사업자 등록증을 팩스로 넣는데 
팩스로 넣을때 거기에다가 등록된 ID(Enrollment ID)를 함께 적어서 팩스로 보내셔야 합니다. 

그리고 약 2주간 기다립니다.
.......

기다려도 기다려도 오지 않는 답장메일..

그래서 다시 스캔을 해서 메일로 보냈습니다.
jhkim@asia.apple.com - 애플 아시아 담당자인가 봅니다. 팩스로 보냈던 영문 사업자등록증을 스캔해서 메일로 보냈습니다.



잘 받았다고 답변이 왔습니다. 가운데 링크를 통해서 이제 구매를 하면 끝입니다.


메일에 링크를 타고 들어와서 개발 프로그램 라이센스를 읽고 동의한뒤 버튼을 꾸욱 누르면,


애플 온라인 스토어에서 주문하시고 등록 활성화 메일을 24시간안에 보내준다고 하는 문구입니다. 
24시간안에 활성화 메일이 오지 않으면 연락달라는군요.


요기서부터는 익숙한 한글창입니다. 결제하기 버튼을 누릅니다.


다시한번 주소가 정확한지 적어줍니다.

카드이용 결제하시면 됩니다.


자 드디어 끝났습니다 ^^;
 ㅋㅋㅋ 아 막상 해보면 별거 아닌데 , 기다리고 기다리는 시간들이 너무 지루한것 같습니다. 
밉습니다. 애플 ㅠㅠ




Posted by windship
프로그래밍/Cocos2D2010. 1. 20. 22:46
개발Q&A / 2010.01.19 21:55 / drkhero79 / http://cafe.naver.com/mcbugi/27576  

코코스2D엔진에서 스프라이트 애니메이션 할때 스프라이트에 애니메이션 등록해놓고 사용하잖아요
근데 CCRepeatForever actionWithAction을 이용하면 모든 프레임을 전부다 처음부터 끝까지 반복재생해주잖아요..

[sprite runAction:[CCRepeatForever actionWithAction: [CCAnimate actionWithAnimation:animation restoreOriginalFrame:NO] ]];
 
그렇게 하지않고 특정 한 프레임 만 계속 띄워놓는 다든지 첫번째 프레임만 선택해서 계속 보이게 한다던지 혹은 2~5번째 만 선택적으로 재생한다던지 하는 선택 재생 방법은 없는 건가요?
 
또다른 질문은 aniframe으로 프레임을 만들고 aniframe2를 만들어서..
처음엔 aniframe으로 애니를 재생하다가 특정 이벤트가 발생되면 aniframe2로 교체해서 애니메이션을 재생해주는
그런 방법은 없는것 인가요?

제가 테스트 해볼라고 간단히 작성해본것 입니다.



CGSize size = [[CCDirector sharedDirector] winSize];

    //애니메이션에 필요한 이미지 파일로딩    
    CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:@"walk.png"];
    CCTexture2D *texture1 = [[CCTextureCache sharedTextureCache] addImage:@"dive.png"];
    
    // manually add frames to the frame cache
   //걷는 그림 프레임 세팅
    CCSpriteFrame *frame0 = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake( 25*0, 0, 25, 66 ) offset:CGPointZero];
    CCSpriteFrame *frame1 = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake( 25*1, 0, 25, 66 ) offset:CGPointZero];
    CCSpriteFrame *frame2 = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake( 25*2, 0, 25, 66 ) offset:CGPointZero];
    
  //다이빙하는 그림 프레임 세팅
    CCSpriteFrame *frame_0 = [CCSpriteFrame frameWithTexture:texture1 rect:CGRectMake( 0, 0, 25, 40 ) offset:CGPointZero];
    CCSpriteFrame *frame_1 = [CCSpriteFrame frameWithTexture:texture1 rect:CGRectMake( 45, 0, 25, 40 ) offset:CGPointZero];
    CCSpriteFrame *frame_2 = [CCSpriteFrame frameWithTexture:texture1 rect:CGRectMake( 80, 0, 25, 40 ) offset:CGPointZero];
    CCSpriteFrame *frame_3 = [CCSpriteFrame frameWithTexture:texture1 rect:CGRectMake( 118, 0, 25, 40 ) offset:CGPointZero];
    
   //기본으로 걷는 첫번째 프레임이미지으로 스프라이트 세팅한다.
    CCSprite *sprite = [CCSprite spriteWithSpriteFrame:frame0];
    sprite.position = ccp( size.width/2-80, size.height/2);
    [self addChild:sprite];
    
   //걷는 프레임으로 세팅한 이미지를 에니메이션으로 할당한다.
    NSMutableArray *animFrames = [NSMutableArray array];
    [animFrames addObject:frame0];
    [animFrames addObject:frame1];
    [animFrames addObject:frame2];
 
     //다이빙하는 프레임으로 세팅한 이미지를 애니메이션으로 할당한다.   
     NSMutableArray *animFrames1 = [NSMutableArray array];
    [animFrames1 addObject:frame_0];
    [animFrames1 addObject:frame_1];
    [animFrames1 addObject:frame_2];
    [animFrames1 addObject:frame_3];
    
   //애니메이션 변수 할당
    CCAnimation *animation;

    switch([(CCMenuItemFont*)sender tag])    // callBack에 들어온 sender를 위에 아이템과 같은 형으로 변환을 한다.
    {
        case 0:    //걷는 프레임 재생
            animation = [CCAnimation animationWithName:@"run" delay:0.2f frames:animFrames];
            [sprite runAction:[CCRepeatForever actionWithAction: [CCAnimate actionWithAnimation:animation restoreOriginalFrame:NO] ]];
            break;
            
        case 2:   //다이빙하는 프레임 재생
            animation = [CCAnimation animationWithName:@"dive" delay:0.2f frames:animFrames1];
            [sprite runAction:[CCRepeatForever actionWithAction: [CCAnimate actionWithAnimation:animation restoreOriginalFrame:NO] ]];
            break;

    }
 
작동 방식좀 알아볼겸 해서 이렇게 간단히 작성해봤네요..
당연히 구조 변경할거구요..어떻게 동작하는지 보려고 대충 작성해본거니까 머라고 욕은 마세요^^;;;

암튼 위의 소스를 보면 저의 질문이 파악될지 모르겠네요.

이렇게 하니까 0일경우 걷는 프레임을 재생하고 2일경우는 다이빙을 재생하지만..
메모리에서 헤제를 안하고 계속 이전 애니메이션이 재생됩니다. 걷는것도 계속나오고 다이빙하는것도 계속나옵니다.

걷기를 하다가 중간에 다이빙동작으로 바꾼다는지 하는 방법이 무엇이며..

혹은 걷거나 다이빙 하는 프레임중 1~2프레임만 반복한다든지 1번프레임만 정지상태로 계속 보이게 하고도 싶습니다.

어떻게 하면될까요? 화면상에서 지워지지 않는 문제도 있네요..어떻게 하면되는지요^^

고수님들의 좋은 답변 부탁드려요~
 
에어조단(ckw0507) / 2010.01.19 23:43

애니 메이션 등록을 
CCAnimation *aniWaitRight = [[CCAnimation alloc] initWithName:@"waitRight" delay:0.1];
[aniWaitRight addFrameWithFilename:@"0r.png"];
[aniWaitRight addFrameWithFilename:@"9r.png"];
[self addAnimation:aniWaitRight];
[aniWaitRight release];
이런식으로 하시고 사용하실때는 아래처럼..하시면 될꺼에요.
[self stopAllActions];
[self setDisplayFrame:@"waitRight" index:waitFrame%2];
waitFrame++;
if(waitFrame > 1) waitFrame = 0; 

schedule 을 등록하여 위에방법대로 count 를 이용하여 사용하는 방법이 있을것 같네요.

---
GTekna Corp(gtekna) / 2010.01.20 08:42

Animation 변수를 하나만 사용하지 마시고, 걷는 것과 다이빙에 쓰일 것으로 두 개를 만드세요.   Animation은 미리 만들어 놓고 재 사용하는 것이 좋습니다. 안 그러면, performance에 조금 지장이 있지요.

Posted by windship
[강좌 : 객체지향 - 6] 상속성
2009.10.01 12:31
김성용(topmentor)
http://cafe.naver.com/gisdev/611  
6. 상속성
 
 
오랜만에 다시 이어갑니다. 지금도 중요한 일을 하고 있어야 하는 데 귀차니즘 때문에 그것은 미루고 이것에 손을 대고 있네요. ^^<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix = o />
 
이번 시간은 상속입니다. 상속은 객체지향의 꽃이라고 할 수 있습니다. 상속이 없다면 기존의 절차지향과 다를 게 없습니다. 절차지향에도 기능이나 속성을 추상화할 방법은 존재했기 때문입니다. 기능은 함수를 통해 속성은 구조체와 같은 사용자 정의형을 통해 구현을 할 수 있었죠. 상속이 있기에 객체지향과 절차지향은 중대한 문법적 차별성을 갖게 된 겁니다. 따라서 객체지향에서는 이 상속을 이해하고 활용해야 객체지향의 묘미를 살리는 셈이 됩니다.
 
 
   가. 상속의 개념
     : 상속의 기본 개념은 상위개념의 특징을 하위개념이 물려 받는 것이라 했습니다. ‘남학생’이라는 개념은 ‘학생’이라는 상위개념의 속성을 물려 받고 있습니다. 이런 특징을 프로그래밍적으로 어떻게 지원하는 가 하면 하나의 클래스가 가지고 있는 특징(데이터와 함수)들을 그대로 다른 클래스가 물려 받도록 문법화 하였습니다. 즉, 상속이라는 관계표시만 해 두면 별다른 조치없이 클래스의 기능과 속성을 그대로 가져오게 된다는 것입니다. 이는 기존 클래스에서 새로운 기능이나 특성을 부가하는 것만으로도 새로운 클래스를 정의할 수 있게 하기 위해서 입니다.
 
좀 더 프로그래밍적 측면으로 접근해 보면 ‘상속한다’의 의미는 클래스의 멤버를 다시 정의하지 않더라도 다른 클래스의 멤버변수나 함수들을 자신의 것처럼 쓸 수 있는 것을 말하는 것입니다.
 
오호!! 오늘도 저쪽에서 질문을 날리는 군요.
“편리한 것 같기는 한데, 요즘 에디터는 Copy & Paste가 쉬워서 기존에 만들어둔 코드를 그대로 복사해서 붙이면 되는데 굳이 상속을 쓸 필요가 있나요?”
 
대단한 지적입니다. 맞습니다. 복사해서 붙이기 하면 간단히 해결될 수 있습니다. 그럼 이런 상황을 생각해 봅시다. 화면에 원을 출력하는 기능을 확장해서 동심원을 출력하는 모듈을 만든다고 생각해 봅시다. 만약 복사를 해서 원을 출력하는 로직을 가져다 동심원 출력 모듈을 완성했다면 원을 출력하는 기능을 만든 사람이 그것을 업데이트 했을 때 동심원에 적용한 원 출력 로직은 업데이트가 안 된 상태로 남아있게 됩니다. 기능을 상속받았다면 업데이트 된 로직이 그대로 적용되었을 것입니다. 유지보수의 측면에서 상속이 복사&붙이기 보다 훨씬 일관성이 있고 안전하다고 할 수 있습니다.
 
“그런 경우 복사해서 붙이지 않고 함수를 호출하는 식으로 되면 안 되나요?”
 
이런 경우 원래 모듈의 안정성을 기할 수 있을 겁니다. 그런데 자료구조나 속성은 어떻게 물려줄 까요? 상속은 데이터이든 로직이든 안전하게 하위 클래스로 물려주고 자신의 색깔도 잃지 않게 하는 장점이 있습니다.
 
이런 측면도 있습니다. A라는 사람이 Car라는 클래스를 구현하였습니다. B라는 사람이 SuperCar라는 클래스를 만들려고 합니다. 그런데 Car의 기능과 속성을 이용하면 쉽게 구현할 수 있을 것 같습니다. Car 클래스는 A의 통제하에 있는 것이라 섣불리 B가 Car를 직접 수정할 수는 없습니다. Car는 그대로 두고 자신은 SuperCar만 손댈 수 있도록 하되 Car의 속성과 기능을 가져와야 합니다. 상속은 이런 상황에서 쓸 수 있는 좋은 방법입니다. Car의 속성과 기능을 물려 받되 마음에 들지 않는 것은 오버로딩이나 오바라이딩을 통해서 재구현할 수 있기 때문입니다. 빌려쓰는 모듈을 건들지 않고 원하는 모듈의 기능을 완성한다. 좋지 않습니까?
 
 
 
   나. 상속시 객체 구조
     : 상속을 받은 하위 클래스로 만든 객체의 구조를 이해하는 것은 상속관련 문법을 이해하는 데 매우 중요한 의미를 갖습니다. 일단 하위 클래스 객체에 대한 대원칙을 말씀드리겠습니다.
 
 원칙적으로 상속을 하면 모든 멤버를 하위로 가져온다. 단, 사용할 수 있느냐 없느냐로 상속이 된다 안 된다를 판단한다.
 
이것을 그림으로 설명드리겠습니다.
 
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = v />
 
 
Car를 상속 받은 SuperCar 클래스를 가지고 인스턴스를 생성하면 위 그림과 같이 SuperCar 객체 내에 Car 객체를 포함하는 형태가 됩니다. 상속을 한다면 마치 기능과 속성단위로 하나씩 가져오는 것 같지만 실제로는 그렇지 않다는 것입니다. 상위객체를 통체로 안고 있는 것입니다. 이를 통해서 확인할 수 있는 사실 하나… 상속을 받을 때에는 필요한 멤버만 선택적으로 가져올 수는 없다는 것입니다. 도움이 되든 안 되든 모두 가져와야 하는 구조입니다.
 
이쯤에서 이런 질문을 하실 겁니다.
“접근지정자를 쓰면 필요한 것만 상속한다고 하던데요? 즉, private로 지정되는 것은 상속이 안 된다고 하던데…”
 
많은 객체지향 책에서 그렇게 설명하고 있습니다. 일부는 맞는 이야기입니다. 그런데 이 부분은 정확히 이해하셔야 합니다. 접근지정자는 접근을 제한하는 용도이지 상속을 제한하는 제한자가 아닙니다. 상속을 하면 모든 멤버를 가져오는 데 접근지정자에 의해 하위 클래스 쪽에서 접근하는 것을 차단하는 것입니다. 이런 식으로 해서 private멤버를 쓸 수 없게 되니 ‘상속이 안 된다’라고 표현을 합니다만 사실 정확한 표현은 아닙니다. 메모리상에서는 private 멤버도 엄연히 allocation되고 있습니다. 단지 쓰지 못할 뿐이죠.
 
부가적으로 설명하자면 private 멤버는 하위 클래스에서 접근이 차단됩니다. protected나 public으로 지정되어야 하위 클래스서 접근이 가능합니다.
 
그리고 C++에서는 private 상속, protected 상속, public 상속을 구분하도록 문법이 제공되지만 거의 99% public 상속을 하고 있기 때문에 거의 의미가 없다고 보시면 됩니다. 따라서 Java나 C# 같이 나중에 탄생한 객체지향 언어의 경우 상속방식을 접근제한자로 구분하는 문법이 없습니다.
 
자~ 정리해 보겠습니다.
상속의 목적은 새로운 클래스를 정의하는 데 기존의 클래스를 확장하여 정의하고 싶을 때 사용된다. 그리고 하위 클래스의 객체는 상위 클래스의 객체를 포함하는 형태를 취하며 접근지정자에 사용이 제한될 뿐이다.
 
다음 시간에는 다형성을 해야 되는 데 상속에 대해 한가지 더 이야기를 할 게 있어 그것을 다루려고합니다. 사실 객체지향이 제시하는 상속은 2가지가 있습니다. 오늘 알아본 것은 구현상속이라는 것입니다. 새로운 클래스 구현을 목적으로 하는 상속을 말합니다. 상속을 하면 상위 클래스의 기능과 속성을 물려받는다는 특징을 이용하는 것이죠.
 
그런데 한가지가 더 있습니다. Type 상속이라는 것이 있습니다. 이것은 클래스가 갖는 형태만 상속을 하는 것입니다. “‘형’만 상속을 한다.”는 것에 대해 감이 잘 안 오실 겁니다. 주는 것 없이 그저 유형만 가져온다는 게 어떤 의미를 지니고 왜 필요한지도 모르실 겁니다. 하지만 이것을 이해해야 다형성의 고비를 넘어가실 수 있습니다. 다음 시간에는 이 type 상속에 대해 알아 볼 겁니다.
 
C++에서는 엄밀히 구분하지 않지만 Java나 C#등에서는 이 두 가지 상속을 구분하는 문법을 제공하고 있습니다.
Posted by windship
[강좌 : 객체지향 - 5] 캡슐화
2009.09.04 14:30
김성용(topmentor)
http://cafe.naver.com/gisdev/543  
5. 캡슐화<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix = o />
 
   이번 시간은 캡슐화에 대해 알아보겠습니다. 개인적인 생각으로는 객체지향 4대 특징중에 어쩌면 가장 주목받지 못하는 특징이 아닌가 합니다. 그 이유는 캡슐화를 개념적인 측면으로만 접근하고 실제 코드로 별로 적용하지 않기 때문에 생기는 문제라고 봅니다. 캡슐화가 객체지향의 4대 특징으로 올라설 수 있었던 것은 그 만큼 개념적인 중요성이 크기 때문인데 많은 개발자들이 이것의 중요성에 대해 인식하지 못하고 있습니다. 그도 그럴 것이 많은 객체지향 프로그래밍 책에서 캡슐화를 자세히 다루지 않기 때문입니다. 그저 접근지정자 설명에 그치는 경우가 대부분이죠. 하지만 캡슐화의 특징은 접근지정자 이상의 의미를 가지고 있고 실제 코딩에서는 다양한 형태로 구현이 됩니다.
 
자! 그럼 캡슐화로 들어가 보겠습니다.
 
 
가. 캡슐화 개요
잠시 복습하는 차원에서… 객체지향 4대 특징의 개념 시간에 캡슐화를 어떻게 설명했었죠?
네~ 그렇습니다. '데이터 구조'와 '데이터를 다루는 방법'를 결합시켜 묶는 것을 말합니다. 질환을 치료하는 데 필요한 몇몇 약들이 적정한 비율로 섞여 하나의 캡슐에 들어있는 알약을 예로 들어 설명했습니다. 그러면서 특정 객체가 독립적으로 역할을 제대로 수행하기 위해 필요한 데이터와 기능을 하나로 묶어 관리하는 것을 캡슐화라고 한다고 정리했었습니다.
거기에 데이터는 은닉하고 그 데이터를 접근하는 기능(함수)를 밖으로 노출하는 것도 캡슐화라고 했습니다. 데이터를 기능으로 보호하여 데이터의 입출력이 기능을 통해 통제되도록 설계하는 것을 말하는 것이었죠.
 
지금까지의 내용을 정리해 보면 캡슐화는 두가지 측면이 있습니다.
  1) class안에 관련된 변수와 메소드를 묶어 넣는 것.
  2) 정보은닉
     : 객체는 자신이 수행하는 모든 행동의 과정이나 속성을 외부로 보이지 않게 합니다.
       즉, 외부에서는 사용하는 메소드의 로직이나 멤버변수들에 대해서는 알 필요가 없다
       는 것입니다.
 
 
나. 캡슐화의 구현
캡슐화를 구현하기 위해 각 객체지향언어들은 접근지정자라는 것을 제공합니다. 클래스의 멤버에 접근할 수 있는 권한을 통제하여 적절히 보안정책을 취할 수 있게 하는 것입니다. 대표적인 접근지정자는 다음의 3가지 입니다.
 
   . private   : 클래스 내부 (멤버함수)에서만 접근가능
      . protected : 클래스 내부 + 하위 클래스의 멤버함수에서 접근 가능
      . public    : 클래스 내부 + 하위 클래스의 멤버함수 + 외부 함수에서 접근 가능
 
class 클래스 이름
{
public :
        데이터형 멤버변수1;
        데이터형 멤버변수2;
리턴형 함수1 ( 매개변수 );
private:
데이터형 멤버변수3;
        데이터형 멤버변수4;
리턴형 함수2 ( 매개변수 );
};
 
 
위 예에서 멤버변수1, 멤버변수2, 함수1은 pulic 접근지정이 됩니다. 그럼 대충 눈치로 보면 멤버변수3, 멤버변수4, 함수2는 private 지정이 되겠구나라는 짐작이 가시죠? 클래스 내부에 인스턴스가 관련 기능을 온전히 하기 위해 필요한 데이터와 함수를 한묶음으로 가지고 있다면 이것은 캡슐화가 잘 된 것입니다. 캡슐화가 잘 된 클래스는 외부에 의존하는 정도가 줄어들겠죠.
 
두번째 캡슐화 정의를 구현하는 방법은 다음과 같습니다. 모든 멤버변수는 private로 접근지정을 해서 외부의 직접접근을 문법적으로 차단 시키고 멤버 변수 데이터를 수정하거나 데이터 값을 알아내기 위한 별도의 멤버 함수를 제공하는 것입니다. 이렇게 멤버변수를 수정하거나 값을 열람하는 접근함수를 Getter(accessor)/Setter(mutator)라고 합니다.
 
아래 예를 잠깐 살펴 보겠습니다.
 
class Car
{
private :
        int speed;
 
public:
void setSpeed(int n) {  speed = n; }
int getSpeed() {  return speed; }
 
};
 
int main()
{
   Car mycar;
   mycar.setSpeed(100);
   cout << mycar.getSpeed() ;
}
 
 
예제를 보면 speed라는 멤버변수는 private로 묶어 두었기 때문에 main함수에서는 직접 접근할 수 없습니다. 대신 이 멤버에 접근하기 위한 메소드를 제공하고 있는 것을 알 수 있습니다. speed에 데이터를 입력하기 위해 setSpeed()를 제공하고 speed 값을 얻어내기 위해 getSpeed()를 제공하고 있습니다. 그래서 main함수에서도 이들 함수를 호출하여 간접적으로 speed 멤버를 쓰고 있습니다. 함수를 통한 데이터의 접근, 이것이 바로 캡슐화인 것입니다.
 
 
아! 저기서 누가 손들고 계시는군요.
‘speed를 public로 해 두면 굳이 메소드를 만들지 않고 편하게 접근해서 쓸 텐데 이런 번거로운 것을 해야 하나요?’
 
네~!! 맞습니다. 그렇게 쓰면 편하죠. 그런데 이런 측면을 생각해 볼까요? 멤버변수중에 외부에서 값은 열람은 하되 수정은 하지 못하게 하고 싶다면 어떻게 해야 할까요? 멤버변수를 public로 그냥 노출하면 외부에서 수정하는 것을 원천적으로 차단할 수 없겠죠? Getter와 Setter를 선택적으로 두면 그 멤버변수는 읽기전용 혹은 쓰기전용식으로 데이터에 대한 접근권한을 더 세분화 할 수 있습니다.
 
또한 위 예제의 로직을 잘 보세요? speed멤버변수는 음수값이 들어오면 안 됩니다. 마이너스 속도란게 있을 수 없잖습니까? 만약 speed가 노출되어 있다면
speed = -100;
식으로 음수가 입력되는 것을 막을 수 없습니다. 하지만 메소드를 통해 간접적으로 접근하게 하면 이런 입력값의 유효성을 체크할 장치를 둘 수 있습니다. setSpeed()에서 두면 되겠죠.
 
void setSpeed(int n) {
if(n>=0)
  speed = n;
else
  speed = 0;
}
 
위와 같이 해 두면 아무리 main함수에서 ‘mycar.setSpeed(-2000);’ 한다 한들 speed에는 음수값이 입력되지 않습니다. 자~ 그럼 정리해 봅시다. 멤버변수를 멤버함수로 캡슐화하는 이유는
 
     1) 데이터에 대한 읽기 쓰기 권한 구분
     2) 입력데이터의 유효성 검증 부분을 로직에 포함 시킬 수 있음.
 
입니다. 정리가 되셨죠?  실제 COM과 같은 컴포넌트 프로그래밍에서는 외부에서 접근할 필요가 있는 멤버변수에 대해 Getter와 Setter를 반드시 두도록 되어있습니다.
 
 
 
다. 클래스 설계상의 캡슐화
세번째 캡슐화에 대해 설명 드리겠습니다. 이것을 객체지향 프로그래밍 책에는 소개되어 있지 않지만 실제 프로그래밍에서는 많이 활용되고 있는 기법입니다. 이것은 설계적인 측면이 있어서 이해하는 데 좀 어려울 수도 있습니다. 따라서 지금 이해가 안 되더라도 양심의 가책(?) 느끼지 마시고 넘어가셔도 됩니다. 다형성을 이해한 다음에 보시면 됩니다.
 
세번째 캡슐화는 선언만 노출하고 구현은 숨기는 것입니다. 잘 이해가 안 되시죠? 이와 비슷한 기법을 쓴 것이 바로 라이브러리입니다. C나 C++라이브러리를 이용할 때 보면 코딩시에 추가(include)하는 것은 라이브러리의 헤더입니다. 헤더에 드러난 함수나 클래스 선언을 보고 자신이 작성한 코드에서 라이브러리 함수를 호출합니다. 마치 자신이 작성한 함수처럼 말이죠. 그럼 그 라이브러리 함수의 실제 구현부분은 어디에 있는 것일까요? Lib 파일에 네이티브 코드형태로 있다가 link시에 이들 코드가 삽입되는 것입니다. 이것도 캡슐화입니다. 세부적인 구현은 숨기고 외부에는 사용할 수 있는 최소의 정보만 노출하는 것이면 모두 캡슐화입니다.
 
객체지향 설계에 있어서 캡슐화는 클래스의 선언만 담는 순수추상클래스를 전면에 내세워 외부에서는 이것을 사용하게 하고 순수추상클래스를 상속받는 클래스를 만들어 여기에 실질적인 구현을 하는 것입니다. 구조로 보면 아래와 같습니다.
 
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = v />
 
 
 
위 그림에서 ImageSource라는 추상클래스는 구현부가 없습니다. 그냥 멤버함수의 선언만 들어있습니다. 이것이 인터페이스 역할을 하는 것입니다. 그 멤버함수의 구현은 하위 클래스인 LocalImageSource나 RemoteImageSource에 있습니다.따라서 외부에서는 ImageSource라는 추상클래스를 활용하고 실제 기능의 수행은 하위클래스인 LocalImageSource나 RemoteImageSource에서 이루어집니다. 이렇게 되면 클래스를 사용하는 측에서는 세부구현을 신경쓸 필요없이 ImageSource가 노출하는 인터페이스만 보면 되는 겁니다.
 
이렇게 함으로 해서 클래스 사용하는 쪽이 클래스의 실제 구현부를 건드려 클래스 개발에 대한 일관성을 잃게 되는 위험을 피할 수 있습니다. 클래스 구현의 버전관리에도 강점이 있죠. 아무튼 이 기법은 클래스 설계상 구현할 수 있는 캡슐화입니다. 자바를 좀 하신 분은 JDBC가 이런 구조를 가지고 있다는 것을 아실 겁니다. 세번째 기법은 나중에 다형성이 끝난 후 디자인 패턴을 이야기 할 때 자세한 코드를 예로 들어 설명하겠습니다.
 
정리하죠. 캡슐화는 실질적인 것은 숨기고 접근할 방법만 노출하는 것을 의미한다. 요즘에는 관련된 것을 묶는 다는 의미는 많이 퇴색되었습니다.
Posted by windship