구글플레이 개발자 본인확인

Posted by ironmask84
2024. 9. 16. 01:04 나는 프로그래머다!


구글플레이에 앱을 업로드 하려면, 개발자 등록을 먼저 해야합니다.

글쓴이는 공익을 위한 앱을 하나 업로드하고자,
개인적으로 20달러 정도를 주고 구글플레이 개발자로 등록했으며,
1개의 테스트 앱과 1개의 공익을 위한 앱을 개발하여 업로드하였습니다 ^^

2021년에 업로드 하였는데,
해가 갈수록 구글에서는 개발자 관리를 계속 강화하고,
정책을 따르지 않을 경우 업로드한 앱을 모두 삭제 조치를 취한다고 압박을 합니다.

글쓴이는 정책에 대해서 앱을 삭제당하지 않기위해 최소한의 조치를 따르고 있으며,
상업적인 목적으로 유료앱, 광고 포함 등은 하지 않았고, 
앱 내에 결제시스템이 없기 때문에, 그나마 수월하게 정책을 통과하고 있었습니다.

갈수록 강화되는 정책이 계속되고..
최근에는 본인 인증을 위해 거주하는 주소지가 적혀있는 서류 사본을 요구하는데
계속해서 실패해서 꽤 애를 먹었기에 
통과 후기를 공유하고자 합니다.

첫번째 시도는 거주하는 "아파트 관리비 명세서" 였습니다.
집주소가 적혀있기에 인정해줄 것이라고 생각했지만.. 승인되지 않았습니다..

두번째 시도는 "카드 명세서" 였습니다.
요즘은 카드 명세서를 지류로 받지 않고 이메일로 받아보는데, 
집주소가 적혀있는 카드사가 생각보다 많지 않았습니다.
다행이 현대카드 명세서엔 집주소가 있어서 캡쳐 후 제출하였지만....
이번에도 승인되지 않았습니다..

세번째 시도로 "주민세 청구"를 제출해보았습니다.
다행이 집주소가 전체로 다 기재되어있었고, 
그리고 다행이 3개월이 지나지 않는 조건을 만족했습니다!
이번엔 통과가 되었다는 메시지를 받았고,
당분간은 또 개발자 계정이 유지될 것으로 생각되네요 ㅎㅎ

보안은 강화하고, 불법을 막기 위한 정책으로 강화되는 구글정책도 일리가 있습니다만,
생각보다 이번 업뎃은 융통성이 없어서 애먹었네요 ㅋㅋ

애먹고 있는 분들 참고하시기 바랍니다 ^^

 

 

안드로이드 개발 재개 from 2020 #2 구글플레이 등록

Posted by ironmask84
2021. 1. 23. 18:45 나는 프로그래머다!/Java & Android




2번째 안드로이드 개발 일기다..

가정이 생기고, 아이가 생기고,

이것저것 할일이 늘어나다보니,

뭐 하나 집중하기가 쉽지 않다...


그래도 요즘은 또 코로나 시대로 인해..

집 밖에 나갈일이 적다 보니,

집에서 할일들에 집중을 해야하는데...

아직 끝나지 않은 원하는 부서이동 및 나의 이직 도전?에

올해도 큰 산이 많이 남아있다.


안드로이드 개발의 목적은 앞서 얘기했듯,

IT개발의 감각 살리기 및 가능하다면 광고 수익도...

그리고 지금 업무에 계속 있게 된다면,

앱 하나 좋은거 만들어서 평가 좀 잘 받아보기..

그래야 진급에 가까워지기도 한다.


이번에는 25달러 주고 산 구글플레이 개발자 권한으로

앱을 등록해보기.

그냥 앱 만들어서 뚝딱 올리면 될 줄 알았더니,

생각보다 기입해야하는 항목이 많고,

요즘 코로나로 구글플레이 등록에도 기간이 길어지는

차질이 있는것 같다. 

앱을 업로드한지 거의 2주가 지나서야 활성화가 되었다는 것


   
 25달러 결제를 마친 후 환영메세지! 

  
 뭔가 혜택이 많은 듯 아닌듯 기능이 많나... 

  
 하나하나 익혀봐야할듯.. 그전에 제대로된 앱이나.. ㅎㅎ 



 ironmask 누군가 쓰고 있다... 


 여러분에게 행운을 가져다 주겠다는 로또.. 


 스토어 등록정보 설정에도 사진이 앱 사진이 몇장 필요해서 괜시리 번거로웠음.. 



 앱 테스트를 자동으로 해주겠다는 건지.. 아직은 기능이 없기에  



 컨텐츠 등급도 설정하고~~ 






 출시 시작을 해보자고!~ 


 전반적인 앱 출시 내역을 보여주는 화면들.. 


 전반적인 관리화면을 보여주는 대시보드... 드디어 활성화가 되었따!! 




 

안드로이드 개발 재개 from 2020 #1

Posted by ironmask84
2021. 1. 18. 18:16 나는 프로그래머다!/Java & Android




컴퓨터공학을 전공하면서 Java를 배웠고..

직장인이 되어 휴대폰 SW개발을 하면서.. C로 시작해서..

안드로이드 스마트폰이 유행하면서 다시 Java를 하다가..


이제는 프로그래밍과는 관련없는 업계의 IT직군? 으로 이직을 해있어서..

근 2년 동안은 겨우겨우 노력해서 2019년엔 자바로 프로그램 하나 개발해서

직장 내 자체 공모전에 출품하고..

2020년엔 안드로이드 앱 하나 해보자 해보자 하면서...

감각도 잃고, 의지도 좀 없어서 힘든 가운데 있지만...

11월 부터 계획을 세우고, 내가 좋아하는 도서관에서 책 3권 빌렸다.

항상 이렇게 뭔가 도전할 때는 시작할 때가 많이 설레인다.. ㅎㅎ


그리고 앞으로의 내 커리어와 직장 생활에 있어서

IT는 계속 되어야 하기에..

꾸역꾸역 안드로이드 개발 책을 펼쳐보고 있는 중이다..

이번 앱 개발 목표는 광고까지 심어서 구글플레이에 출품하여, 수익 도전해보기...


3년전만 해도 어느정도는 알았는데.. 아니 5년 전인가 ㅜㅜ

안드로이드 개발에 손땐지 5년쯤은 되었구나;;;

안드로이드 스튜디오가 막 나올 때쯤 이클립스를 계속 사용하다가,

개발 경험이 끊긴 것 같다..


그래서 이제 다시 살포시 해보려고..

안드로이드 스튜디오를 설치하고...

그 때 기억에도 안드로이드 스튜디오가 너무 기능이 많고, 무겁기도 했고..

그런데 익혀두면, 확실히 능률적인 부분도 많긴 할듯...


Do it! 안드로이드 앱 프로그래밍 책이 제법 설명이 잘되어 있는듯 하다.

따라 해보기가 수월함.. ㅎㅎㅎ

그리고, 처음으로 구글플레이에 앱을 등록해보기도 함.

우선, 개발자 등록을 play.google.com/console 에서 25달러 주고 해야함.

평생 앱 업로드가 가능하니까 25달러 쯤이야!





위 과정으로 개발 계정이 만들어지고!

다음 포스팅은,

앱 하나 만들어서 구글플레이에

업로드하는 과정을 보여주겠다!



 

Java 프로그램 jar를 exe로 만들기

Posted by ironmask84
2019. 10. 1. 22:55 나는 프로그래머다!/Java & Android


올해 8월부터 해서 아주 오랜만에 자바 프로그램을 하나 만들었네요..

프로그래밍 감각 유지 및 회사에 실적도 쌓을 겸.. ㅋㅋ


꼭 프로그램 개발 회사가 아니더라도,

프로그램을 개발해서 회사 업무에 효율화를 가져다주는 Tool 개발은

회사 업무에도 유용하고, 본인의 평가도 높일 수 있습니다.


만드는 김에 실행용 Jar로 만들어 보자 하고 있다가

아주 예전에 어렴풋이 남아 있던 기억에서 

exe로도 만들어주는 tool 이 있다는 것을 떠올렸네요..


혹시나 JRE가 설치 되어 있지 않는 윈도우 PC에서도 

실행이 될까하는 마음에 알아보고 만들어 보았지만..

역시나 JRE 설치 없이는 안되네요 ㅋㅋ


우선 사용한 Tool은 "Launch4j" 라는 툴입니다.

http://launch4j.sourceforge.net/index.html  를 참조해주세요.

인터넷에 검색해보면 exe 만드는 툴로 Jsmooth가 많이 소개되어 있지만,

저는 그 툴로는 만들어지지가 않았습니다...

저처럼 Jsmooth가 안되는 분들은 "Launch4j"  추천 드립니다.

https://blog.naver.com/cigus/120128400630  에 설명 잘되어 있으니 추천!




그래도 exe로 만들어줄 뿐 아니라,

JRE가 설치되어 있지 않으면,

JRE 다운로드 페이지로 안내해주는 기능까지 추가 된다는 점이 돋보입니다!!


또 개발에 좋은 팁이 있으면 공유할게요~




 

안드로이드 기본개념 면접대비 정리

Posted by ironmask84
2019. 7. 15. 22:31 나는 프로그래머다!/Java & Android



안드로이드가 나온지도 10년이 지났다.

우리나라에 막 나타나기 시작한 것이 2009년 쯤이니..

아직도 스마트폰은 안드로이드가 우세다.

아이폰 OS를 제외하면 견줄 것이 없다.


구글의 무서움은 모바일폰에서 그치지 않는다.

LTE, WiFi, Bluetooth 등을 활용한 무선통신이 가능한 기기들

모두의 시장을 점유하기 위해, 즉 IoT 시장을 차지하기 위한

다양한 용도의 OS들을 만들어가고 있다.


어찌되었든 아직까지도 기본은 안드로이드로 시작한다.

안드로이드는 리눅스를 기반으로해서 C, C++, Java 등

다양한 언어를 활용해 구성되어있는 플랫폼이다.

WiFi, LCD, LTE 등 다양한 HW를 구동시키는 드라이버단,

그 위에 이를 컨트롤하는 Hal단,

그 위에 이를 컨트롤하는 Framework단

그 위에서 움직이는 다양한 App과 Service 들...


너무나 방대하기에 이 플랫폼을 활용하는 것도 

그때 그때 찾아보고 공부하지 않으면 힘이 든다.

구글은 이렇게 방대한 플랫폼을 오픈형으로 키웠고

이러한 생태계를 형성함으로써 

IT 시장의 점유율을 높인 무서운 정책을 펼친 회사다.


각설하고...

안드로이드를 활용한 취업시장은
아직 유효할 듯 하다는 것이 포인트!!

이러한 안드로이드를 조금 안다고 면접장에서 방귀를 끼려면

아래에 정리한 것들을 참고하시라.
어디서 본 정보를 취합하고 내 생각도 더한 자료 이다.


보충이 필요한 부분은 댓글로 언제나 환영이다.

Q0. 안드로이드의 실행환경에 대해서 간단하게 설명하시오.

안드로이드는 크게 4가지 실행환경으로 구성되어있습니다. 가장 하단부터 리눅스 커널, 라이브러리, 어플리케이션 프레임워크, 어플리케이션 순서입니다. 리눅스 커널은 OS로 안드로이드 스마트폰의 다양한 하드웨어(화면, 카메라, 블루투스, GPS, 메모리 등)를 관리합니다. 라이브러리는 안드로이드에 있는 다양한 기능(UI 처리, 미디어 프레임워크, 데이터베이스, 그래픽 처리, 웹 킷 등)을 소프트웨어적으로 구현해 놓은 환경 뿐만 아니라 안드로이드 앱을 구동해주는 dalvik 가상머신과 코어 라이브러리까지 포함하는 영역입니다. 어플리케이션 프레임워크는 사용자의 입력(액티비티, 윈도우, 컨텐츠, 뷰, 노티피케이션 등) 또는 특정한 이벤트에 따라 출력을 담당하는 환경을 말합니다. 마지막으로 실제로 동작하는 앱이 설치되는 환경인 어플리케이션이 있습니다.


Q1. 안드로이드는 다른 플랫폼에 비해 어떤 장점이 있는가?

첫째로 안드로이드를 구성하는 모든 소스가 오픈소스로 무료로 개방되어있어 비용적인 부담이 없습니다. 또한 전 세계의 수많은 개발자로부터 피드백을 받아 수정되기 때문에 안정성과 버그 수정이 빠릅니다. 그 밖에도 원한다면 소스를 다운 받아 수정해서 쓰기 편리합니다. 둘째로 자바를 주 언어로 사용하고 있기 때문에 많은 세계적으로 점유율이 높은 자바 개발자들이 쉽게 개발할 수 있습니다. 셋째로 리눅스 커널을 OS로 채택했기 때문에 다양한 하드웨어에 대한 드라이버 소스가 풍부합니다. 마지막으로 구글의 다양한 앱과 연동이 매우 편리하며 다른 플랫폼에 비해 앱간 연동에 너그러운편입니다.


Q2. 안드로이드 프로젝트 구성요소에 대해서 설명하시오.

libs : 프로젝트에서 사용하는 다양한 라이브러리 소스가 저장되는 공간입니다.

androidTest : 앱의 일부 코드를 테스트하기 위한 소스를 저장하는 공간입니다.

java : 자바 코드를 저장하는 공간입니다. 표준 자바와 동일하게 패키지를 이용한 하위 디렉토리 생성 방식을 사용합니다.

res : 리소스(이미지, xml 레이아웃, 메뉴, 값)를 저장하는 공간입니다.

AndroidManifest.xml : 앱에 대한 전체적인 정보를 담고있는 파일입니다. 앱의 구성요소와 실행 권한 정보가 정의되어있습니다.

project > build.gradle : 프로그래머가 직접 작성한 그래들 빌드 스크립트 파일입니다.

gradle > build.gradle : 앱에 대한 컴파일 버전정보, 의존성 프로젝트에 대한 정의가 되어있는 파일입니다.


Q3. 안드로이드에서 다국어 지원을 위해 해야할 작업에 대해서 설명하시오.

다국어 지원을 위해서는 value resource file을 따로 생성해주는 방식으로 사용합니다.

'values > 마우스 오른쪽 버튼 클릭 > value resource file > 리소스 파일 이름을 strings로 입력 > available qualifiers 탭에서 locale 선택 > language 탭에서 언어 선택 > specific region only에서 세부 국가 선택'

파일을 생성하면 디렉토리의 이름은 values-국가코드(예를 들어 values-kr) 형식으로 생성되며 내부에 strings.xml 파일이 생성됩니다. 해당 파일에 string의 name 값은 동일하게 유지한 후 해당 국가의 언어로 번역하여 추가하면됩니다.


Q4. 안드로이드 매니페스트(android manifest) 파일에 대해서 설명하시오.

안드로이드 매니페스트는 앱의 이름, 버전, 구성요소, 권한 등 앱의 실행에 있어서 필요한 각종 정보가 저장되어있는 파일입니다. 반드시 존재해야하는 xml 형식의 파일로 안드로이드 프로젝트의 최상위에 위치하고 있습니다.

가장 최상위는 manifest 태그가 위치하고 있습니다. manifest 태그에는 패키지명, 앱 버전 코드, 앱 버전 이름을 정의합니다.

application 태그에는 앱 아이콘, 앱 이름을 정의합니다.

activity 태그에는 액티비티의 클래스명과 액티비티 이름을 정의합니다. 하위에는 intent-filter 태그를 이용하여 액티비티에 대한 인텐트 작업시 필요한 action과 category를 정의합니다.

service, receiver, provider 태그에는 각각 서비스, 리시버, 프로바이더에 대한 내용을 정의합니다.

permission 태그에는 앱에서 필요한 권한에 내용을 정의합니다.

그 밖에 최소 안드로이드 SDK 버전을 지정하는 uses-sdk와 다른 패키지를 등록할 수 있는 uses-library 태그 등이 존재합니다.


Q5. 디스플레이(display), 윈도우(window), 서피스(surface), 뷰(view), 뷰 그룹(view group), 뷰 컨테이너(view container), 레이아웃(layout)에 대해서 설명하시오.

디스플레이 : 안드로이드 단말기가 가지고 있는 하드웨어 화면을 의미합니다.

윈도우 : 안드로이드에서 실행되는 앱이 그림(뷰)을 그릴 수 있는 영역을 의미합니다. 사용자로부터 입력(터치, 키) 이벤트를 받아 앱에 전달합니다.

서피스 : 윈도우에 그림(뷰)을 그릴 때 그림이 저장되는 메모리 버퍼를 의미합니다.

뷰 : 사용자 인터페이스를 구성하는 최상위 클래스를 말합니다. 윈도우의 서피스를 이용하여 화면에 어떤 모양으로 그림을 그릴지와 발생하는 이벤트를 어떻게 처리할 것인지에 대한 기능을 구현하고 있습니다. 뷰 중에서 일반적인 제어 역할을 하고 있는 것들을 위젯이라고 합니다.

뷰 그룹 : 여러개의 뷰를 포함하고 있는 뷰를 의미합니다.

뷰 컨테이너 : 다른 뷰를 포함할 수 있는 뷰를 의미합니다. 대표적으로 리스트 뷰(list view), 스크롤 뷰(scroll view), 그리드 뷰(grid view) 등이 있습니다.

레이아웃 : 뷰 그룹 중에서 내부에 뷰를 포함하고 있으면서 해당 뷰를 어떻게 윈도우에 배치할지 정의하는 관리자 역할을 하는 클래스 말합니다.


Q6. 인플레이션(inflation)이란 무엇인가?

xml 레이아웃 파일로 정의한 정보를 런타임에 setContentView 메소드가 호출됨에 따라 메모리 상에 객체로 만들어주는 과정을 말합니다. 이 과정에서 xml 레이아웃 파일에서 뷰에 id를 설정하고 해당 id가 R.java 파일에 주소 값으로 환원되며 findViewById 메소드와 id를 이용하여 코드 상으로 뷰 객체를 가져와 제어할 수 있습니다.


Q7. 안드로이드에서 색상을 지정하는 다양한 방식은 어떤 것들이 있는가?

#RGB, #ARGB, #RRGGBB, #AARRGGBB 총 4가지 방식이 있습니다. R은 붉은색, G는 초록색, B는 파란색의 정도를 나타내며 A는 알파 값 즉 투명도를 나타내는 수치입니다. 각각의 요소는 16진수(0부터 F까지)로 표현합니다.


Q8. 안드로이드의 크기를 표현하는 다양한 표현방법에 대해서 설명하시오.

픽셀(px) : 화면의 픽셀을 의미합니다.

밀도 독립적 픽셀(dp, dip) : 160dpi(160인치에 들어가있는 픽셀 수) 화면을 기준으로 한 픽셀을 의미합니다.

축척 독립적 픽셀(sp, sip) : 가변 글꼴을 기준으로 한 픽셀을 의미합니다. 글꼴의 설정에 따라 차이가 있습니다.

텍스트 크기(em) : 글꼴과 상관없이 동일한 텍스트 크기를 표시하기 위한 단위입니다.

그 외 인치(in), 밀리미터(mm)가 있습니다.


Q9. 안드로이드의 4대 컴포넌트(component)에 대해서 간단하게 설명하시오.

안드로이드의 4대 컴포넌트는 액티비티, 서비스, 브로드캐스트 리시버, 콘텐트 프로바이더입니다. 첫 번째로 액티비티는 안드로이드에서 화면을 관리하고 사용자가 발생시키는 다양한 이벤트를 처리하는 컴포넌트입니다. 두 번째로 서비스는 화면에서 보이지 않지만 특정한 기능을 백그라운드에서 수행하는 컴포넌트입니다. 세 번째로 브로드캐스트 리시버는 특정 안드로이드에서 발생하는 특정 브로드캐스트 메세지를 처리하기 위한 컴포넌트입니다. 네 번째로 콘텐트 프로바이더는 앱간 데이터의 공유를 위해 표준화된 인터페이스를 제공하는 컴포넌트입니다.


Q10. 안드로이드 MVC 모델은 어떻게 구성되어있는가?

안드로이드에서 뷰는 화면에 실제로 보이는 구성을 만드는 영역으로 View 클래스를 상속하는 클래스를 이용하여 구성할 수 있습니다. 다음으로 컨트롤러는 뷰와 모델을 서로 연결하며 제어하는 영역으로 액티비티, 서비스, 브로드캐스트 리시버, 프래그먼트로 구성됩니다. 마지막으로 모델은 앱의 다양한 데이터를 저장하는 역할로 SQLite를 이용한 DB, SharedPreference를 이용한 파일 시스템, 콘텐트 프로바이더가 있습니다.


Q11. 액티비티(activity)가 무엇인지와 액티비티 생명주기에 대해서 설명하시오.

안도르이드에서 화면을 관리하며 사용자가 발생시키는 다양한 이벤트를 처리하는 컴포넌트입니다.

부모 액티비티에서 새로운 자식 액티비티를 실행하고자 한다면 먼저 매니페스트 파일에 해당 자식 액티비티를 추가 해줘야합니다. 다음으로 부모 액티비티에서 startActivity 메소드에 인텐트를 파라미터로 넘겨 실행하거나 startActivities 메소드를 이용하여 여러개의 액티비티를 한꺼번에 실행할 수 있습니다.

액티비티의 실행과정은 첫 번째로 부모 액티비티에서 자식 액티비티를 생성 및 호출합니다. 두 번째로 액티비티 매니저 서비스가 해당 앱 프로세스에서 인텐트를 복사해온 후 매니페스트 파일에서 해당 인텐트에 명시되어있는 액티비티를 찾고 어떻게 실행시켜야할지 결정합니다. 세 번째로 찾아낸 액티비티를 실행하고 다시 해당 앱 프로세스에 인텐트를 복사하여 넘겨줍니다. 그 외 자식 액티비티 내의 onCreate 메소드에서 setContentView 메소드에 레이아웃의 아이디를 파라미터로 넘겨 해당 액티비티의 화면을 구성하게됩니다.

액티비티는 크게 3가지 상태가 존재합니다. 먼저 실행(running) 상태는 액티비티 스택의 최상위에 있으며 포커스를 가지고 있어 사용자에게 보이는 상태입니다. 다음으로 일시 중지(paused) 상태는 사용자에게 보이기는 하지만 다른 액티비티가 위에 있어 포커스를 받지 못하는 상태를 말합니다. 예를들어 대화상자가 위에 있어 일부가 가려져 있는 경우를 말합니다. 마지막으로 중지 (stopped) 상태는 다른 액티비티에 의해 완전히 가려져 보이지 않는 상태를 말합니다.

액티비티가 처음 만들어지면 onCreate 메소드가 호출되어 레이아웃을 구성합니다. 이후 onStart 메소드가 화면에 보이기 직전에 호출됩니다. 다음으로 onResume 메소드가 사용자 상호작용(화면이 포커스를 얻었을 때)하기 바로 전에 호출됩니다. 이 3가지 메소드가 호출되어 액티비티는 실행 상태를 갖게됩니다. 이후 포커스를 잃었을 때 onPause 메소드가 호출되고 일시 중지 상태가 됩니다. 일시 중지 상태에서 다시 포커스를 획득하면 onResume 메소드가 호출되거나 다른 액티비티에 의해서 완전히 화면이 가려졌는지 여부를 확인하여 가려져 보이지 않는 경우 onStop 메소드가 호출되어 중지 상태가됩니다. 정지 상태에서 다시 화면이 보이기 직전에 onRestart 메소드가 호출되고 onStart 메소드가 차례로 호출됩니다. 그 외 finish 메소드가 실행되어 해당 액티비티가 종료되기 직전에 onDestroy 메소드가 실행됩니다.

가끔은 일시 중지나 중지 상태에서 시스템이 메모리가 부족하다고 판단될 경우 onCreate 메소드부터 다시 해당 액티비티를 구동합니다. 이 경우 onStop, onResume 메소드 호출이 생략됩니다. 따라서 onSaveInstanceState, onRestoreInstanceState 메소드를 이용하여 액티비티가 갑자기 죽을 것을 대비해서 상태를 저장하고 복원하기 위한 작업을 정의해줄 수 있습니다.


Q12. 액티비티간 데이터 전달에서 임의의 클래스 객체를 바로 전달하지 못하는 이유는 무엇이고 전달하기 위해서는 어떤 처리가 필요한가?

액티비티간 전달할 수 있는 데이터의 type은 보통 기본형으로 정해져있습니다. 그 이유는 인텐트를 이용하여 액티비티의 데이터를 전달하는 과정에서 현재 실행중인 앱 프로세스가 시스템 프로세스로 실행중인 액티비티 매니저 서비스 프로세스에게 인텐트를 전달합니다. 이 경우 프로세스간 통신이기 때문에 인텐트에 있는 값들을 복사하여 넘기는 방식으로 처리되기 때문에 객체 주소를 바로 넘기지 못하는 문제가 발생합니다. 따라서 이 문제를 해결하기 위해 자신이 임의로 만든 클래스 객체를 전달하기 위해서는 Serilizable이나 Parcelable 인터페이스를 상속받아 객체를 직렬화하여 넘기는 방식을 사용해야합니다.


Q13. 부모 액티비티에서 자식 액티비티의 결과 값을 받아오기 위해 어떻게 해야하는가?

먼저 부모 액티비티에서 startActivityForResult 메소드를 이용하여 인텐트와 리퀘스트 코드를 파라미터로 넘깁니다. 이후 자식 액티비티에서 setResult 메소드에 결과 코드와 데이터를 파라미터로 넘깁니다. 다시 부모 액티비티에서 onActivityResult 메소드를 오버라이딩하여 자식 액티비티에서 보낸 결과 코드와 데이터를 받아 처리하는 코드를 작성할 수 있습니다. 이후 실행과정에서 자식 액티비티의 finish 메소드가 호출되면 부모 액티비티가 다시 화면에 나타나면서 onResume 메소드가 실행됩니다. 이때 onActivityResult 메소드가 작동하게 됩니다.


Q14. 안드로이드가 리소스(resource)를 접근하는 방식에 대해서 설명하시오.


Q15. 서비스(service)가 무엇인지와 서비스 생명주기에 대해서 설명하시오.

서비스는 백그라운드에서 실행되는 구성 요소입니다. 서비스는 사용자에게 보이는 화면이 존재하지 않으며, 정해지지 않은 시간 동안 운영됩니다. 각각의 서비스는 매니페스트 파일에 서비스 태그를 이용하여 선언해야합니다. 서비스는 Service 클래스를 상속받아 onStartCommand 또는 onBind 메소드를 재정의하여 구현할 수 있습니다.


서비스는 다른 구성 요소들처럼 메인 쓰레드에서 동작합니다. 따라서 CPU를 많이 사용하거나 대기 상태를 필요로 하는 경우 새로운 쓰레드를 이용하여 생성해야합니다. 또한 서비스의 객체는 단말에서 오직 1개만 생성되어 관리합니다.


먼저 서비스가 startService 메소드로 실행되는 경우 서비스가 생성될 때 onCreate 메소드가 실행됩니다. 이후 서비스가 실행을 시작할 때 onStartCommand 메소드가 호출되며 서비스의 상태가 실행중으로 변경됩니다. 이후 stopService 메소드가 실행되면 서비스가 종료되며 onDestroy 메소드를 호출하며 서비스의 상태가 종료로 변경됩니다.


다음으로 서비스가 bindService 메소드로 실행되는 경우 서비스가 생성될 때 onBind 메소드가 호출됩니다. 다음으로 unbindService 메소드가 호출되어 바인딩이 해제되면 onUnbind 메소드가 호출됩니다. 이후 완전히 종료될 때 onDestroy 메소드가 호출됩니다.


Q16. 브로드캐스트 리시버(broadcast receiver)가 무엇인가?


Q18. 인텐트(intent)와 인텐트 필터(intent filter)에 대해서 설명하시오.

Intent : 어떤 Activity에 데이터를 보낼 때 값들을 지정하기 위해 사용

인텐트필터 : AndroidManifest.xml에서 설정하는 암시적 인텐트 (받는 쪽에서 설정 함)

             즉, 인텐트를 보내는 앱에서는 받는 앱의 이름을 알 필요가 없다.


Q19. 어플리케이션(application)과 컨텍스트(context)에 대해서 설명하시오.

어플리케이션 앱 프로세스가 실행되면 가장 먼저 생성되는 객체로 하나의 어플리케이션 객체는 하나의 앱 프로세스와 대응됩니다. 앱이 백그라운드로 내려가도 앱 프로세스는 계속 살아있기 때문에 어플리케이션 객체도 살아있다고 할 수 있습니다.


컨텍스트는 안드로이드의 컴포넌트들이 동작하기 위해 필요한 정보를 담고 있는 객체를 말합니다. 각각의 컴포넌트들(액티비티, 서비스, 브로드캐스트 리시버 등)은 자신만의 컨텍스트를 가지고 있습니다. 컨텍스트 내에는 어플리케이션의 정보(패키지명 등), 컨텍스트가 실행되는데 필요한 정보(테마 등)를 얻거나 시스템 서비스(윈도우 매니저, 레이아웃 인플레이터 등)를 구동하는데 사용됩니다.


Q20. 노티피케이션(notification)은 무엇인가?

Q21. 안드로이드에서 로그(log)를 출력하는 방법과 종류를 설명하시오.

Q22. 스타일(style), 테마(theme)에 대해서 설명하시오.

Q23. 프레그먼트(fragment)가 와 프레그먼트 생명주기에 설명하시오.

프레그먼트는 액티비티의 일부분에만 배치되는 화면 및 동작을 조작하기 위한 객체입니다. 안드로이드 3.0(허니콤)에서 화면이 비교적 큰 태블릿의 등장으로 작은 단위의 화면의 생명주기 관리할 필요가 있어 추가되었습니다. 프레그먼트 매니저를 통해서 여러개의 프레그먼트를 조작할 수 있습니다. 레이아웃 xml 파일에서 다른 뷰들과 함께 배치될 수 있습니다.

액티비티가 생성되면 프레그먼트 매니저는 초기화(initializing) 상태가 됩니다. 프레그먼트가 매니저에 의해 추가되면 onAttach, onAttachFragment, onCreate 메소드가 차례로 실행됩니다. 다음으로 액티비티의 onCreate 메소드 호출 이후 매니저는 생성(created) 상태로 변경됩니다. 이때 onCreateView, onViewCreated, onActivityCreated 메소드가 차례로 호출됩니다. 다음으로 액티비티의 onStart 메소드가 호출되면 매니저는 시작(started) 상태로 onStart 메소드를 호출합니다. 이후 액티비티의 onResume 메소드가 호출되면 매니저 역시 재시작(resume) 상태로 변하며 onResume 메소드를 호출합니다. 그 외 액티비티가 화면에서 보이지 않을경우 호출되는 onStop 메소드 호출 이후 매니저는 중지(stop) 상태가 되며 액티비티의 onDestroy 메소드 호출 이후 매니저는 onDestroyView 메소드를 호출합니다.


Q24. 뷰 홀더 패턴(view holder pattern)에 대해서 설명하시오.

Q25. 나인패치(9patch)란 무엇인가?

Q26. 태스크(task)란 무엇인가?

예를들어 어떤 앱에서 앨범 앱을 실행하는 기능이 있다면 이 앱은 두개의 앱을 실행하는 형태가 되지만 사용자 입장에서는 하나의 앱에서 화면이 전환된다고 판단합니다. 이와 같은 사용자 입장에서 논리적인 화면 구성의 단위를 태스크라고 말합니다.


Q27. 안드로이드의 메모리 관리 방식에 대해서 설명하시오.

안드로이드는 액티비티, 서비스, 리시버, 프로바이더를 실행하기 위해 앱이 실행되는 과정에서 프로세스를 생성합니다. 실행중인 모든 앱은 컴포넌트가 모두 종료되어도 다음에 이 앱을 다시 실행할 가능성이 높기 때문에 프로세스를 바로 제거하지 않습니다. 바로 종료하지 않는 이유는 앱을 실행하기 위해 프로세스를 생성하는 과정에서 딜레이가 발생하는데 이 딜레이를 줄이기 위함입니다. 따라서 사용자에 의해 다시 앱이 실행되면 남아있던 프로세스가 존재하는 경우 바로 실행됩니다. 이 과정에서 쌓여있던 많은 프로세스로 인해 메모리가 부족해지는 경우 프로세스의 우선순위(사용빈도)에 따라 프로세스를 종료하여 메모리를 확보합니다.




 

Linux - 시그널 Signal (Ctrl+c, Ctrl+z)

Posted by ironmask84
2018. 5. 13. 00:39 나는 프로그래머다!/Linux



리눅스에서 Ctrl + C 키 조합을 통해 프로세스 종료를 많이 해보셨을 겁니다.

저 또한 그냥 개발시에 테스트 진행하다가 빨리 강제종료 시키기 위해 사용을 해왔었습니다.

그러다가 Ctrl + C가 먹히지 않는 프로세스가 발생하고는...

Ctrl + Z 를 어디선가 써본적이 있어! 라는 생각이 스쳐지나가면서 써보니 

뭔가 다시 콘솔창에 프롬프트가 상태가 되어 명령어 입력이 가능해집니다.

뭔가 근데 찜찜하기 시작합니다. 

알고 보니 이건 foreground process를 background로 전환하면서 잠깐 중지 시키는 것이더군요 ㅋㅋ

Ctrl + C와 Ctrl + Z 는 리눅스나 윈도우 같은 OS가 기본적으로 지원해주는 시스템호출을 통한 인터럽트 입니다!!

리눅스에서는 이러한 개념을 Signal 이라고 하는 것 같아요.

https://en.wikipedia.org/wiki/Unix_signal


Ctrl-C (in older Unixes, DEL) sends an INT signal ("interrupt", SIGINT); by default, this causes the process to terminate.

Ctrl-Z sends a TSTP signal ("terminal stop", SIGTSTP); by default, this causes the process to suspend execution.

Ctrl-\ sends a QUIT signal (SIGQUIT); by default, this causes the process to terminate and dump core.

Ctrl-T (not supported on all UNIXes) sends an INFO signal (SIGINFO); by default, and if supported by the command, this causes the operating system to show information about the running command.

These default key combinations with modern operating systems can be changed with the stty command.


좀 더 자세하고 다양한 내용은 아래를 참조하면 좋을 것 같습니다.

시그널의 명령어 리스트 : kill -l

시그널의 의미 (/usr/include/asm/signal.h)


자, 그럼 왜 Ctrl + C가 먹히지 않았을까..

검색을 해보자!!

리눅스 C 프로그래밍에는 signal() 이란 함수가 있습니다!!

프로세스에서 아래와 같이 호출하면, Ctrl + C가 무시되도록 설정됩니다!!

signal(SIGINT, SIG_IGN); // SIGINT 명령을 무시하도록 설정 


아래와 같이 handler를 추가해서 커스터마이즈한 활용도 가능합니다!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int  main(void)
{
     signal(SIGINT, INThandler);
     while (1)
          pause();
     return 0;
}
 
void  INThandler(int sig)
{
     char  c;
 
     signal(sig, SIG_IGN);
     printf("singnal test");
}

cs




 

Linux - 디렉토리 용량 확인

Posted by ironmask84
2018. 5. 13. 00:02 나는 프로그래머다!/Linux




회사에서 프로젝트 개발에 OS를 리눅스 Yocto를 사용하고 있는데,

아직 리눅스 사용이 아직 익숙하지가 않습니다.. 

임베디드 + CUI 환경이어서, 더욱 직관적이지가 않다보니...

윈도우에 익숙해온 것이 무서운 것인지.. 확실히 리눅스가 UI, UX 측면에서는 부족한 느낌입니다.

확실히 개발자에게 적합한 환경이랄까요.. CUI 환경자체가.. 단순하니 그런 것 같습니다.


아무튼 임베디드 환경은 용량이 제한적일 수 밖에 없습니다.

한번 쯤 디스크 용량 체크를 해보고 싶을 때가 오는데요.

적당한 명령어는 아래와 같습니다. ^^


du -h /폴더명 : 디렉토리별, 하위 디렉토리까지 확인

du -hs /폴더명 : 하위 디렉토리까지 확인

du -h --max-depth=2 디렉토리 : 디렉토리별 용량 확인

du -s 폴더명 : 해당 폴더의 용량

du -s ./* : 해당 폴더 소속 모든 폴더 용량.

df -h : 파티션 용량 확인




 

Atom - 추천 웹에디터 툴

Posted by ironmask84
2017. 12. 4. 23:32 나는 프로그래머다!/HTML5



2년 전에 제 블로그에 Atom 이라는 에디터를 소개한 적이 있습니다.

http://ironmask.net/231

이 때 당시, Firefox OS를 이용해서 프로젝트 개발을 시도한 때였기 때문에 갑작스레 JavaScript 와 Html 을 학부 때 이후로 

손대기 시작했었죠;;  이 때 jQuery라는 것도 처음 써보기도 했었구요 ㅎㅎ

웹프로그래밍이 2000년대에 붐이 일어났다가, 한 동안 잠잠해 있었던 것 같았습니다.

하지만, html5가 탄생되면서, html5 + CSS + JavaScript 조합이라는 것으로 급부상하고 있습니다.

특히, 스마트폰의 대중화에 따라 웹 근접성이 매우 좋아짐에 맞물려서 더욱 빛을 발하고 있어요 ^^


아무튼 각설하고, 이 때는 단순히 이런 툴이 있다고 소개만 했었습니다. ㅋㅋ

이제는 IoT 관련 프로젝트를 진행하다가, 디바이스의 설정 및 모니터링을 웹으로 해보고자

다시금 웹프로그래밍에 손을 대었습니다. ( html + JavaScript + PHP 조합 )

새롭게 툴을 찾다가 2년 전에 매우 잠깐 써봤던 Atom이 여전히 추천 툴 중에 하나 더군요 :)
(SublimeText, Bracket 와 함게 웹에디터 툴로는 세 손가락에 듭니다. ㅎㅎ)

또 장점으로는 오픈소스로 만들어진 툴이며, 패키지(플러그인)도 상당히 강력하고 지원 수도 많습니다.


쓸만한 패키지를 소개하면서 이 글을 마치겠습니다. ^^


Emmet - Tab키로 자동완성

Syntax Hint - 문법 오류를 잡아줌 Linter, linter-js, linter-html, linter-css, linter-php 

atom-beautify - 자동 정렬 

minimap, minimap-highlight-selecetd, minimap-cursorline - 조그마한 맵을 통해 전반적인 소스현황 모니터링 가능

pigments - 코드 내에 컬러를 직관적으로 보여줌

Remote-FTP - FTP로 외부디바이스에 있는 소스코드에 바로 접근 가능



 File - Setting - Editor 메뉴에 기본 설정 항목이 많습니다.  
 추천 내용으로는 http://dickymicky.blog.me/220950885317 을 참고해주세요 ^^ 



 여기서 패키지 검색을 하신 후, 인스톨 하시면 됩니다. ^^ 


 여기서는 인스톨 된 패키지 목록 확인이 가능해요~~ ^^ 





 

라즈베리파이 프로젝트 실전#1 - LED 컨트롤

Posted by ironmask84
2017. 11. 21. 21:33 나는 프로그래머다!/Sensor



드디어 기본 준비 포스팅은 끝내버리고, 프로젝트 실전 입니다. ㅋㅋ

우선은 제일 간단한 LED 컨트롤 입니다만, 선뜻 나서질 못했네요 ㅎㅎ

사실 디바이스 드라이버에 대해 공부를 하는 중이라, 막상 실전에 들어가기가 쉽지 않았어요.

디바이스 드라이버를 만들기 위해 커널 컴파일 부터 손대어 볼까 했는데, 

역시나 라즈비안OS에는 GPIO 컨트롤을 위한 디바이스 드라이버가 있었습니다.

LED가 아닌 복잡한 장치는 제조사에서 제공해 줄 것 같긴 하고...

GPIO가 아닌 I2C나 SPI에 대한 드라이버도 이미 설치되어 있지 않을까 생각해봅니다.  : )


우선은 C언어 코드로 진행하였고,

차후에는 python으로 갈아타야 할 듯 합니다.
(라즈베리파이 재단에서 기본 제공하는 python 라이브러리가 많다고 들었네요... )


LED 컨트롤 프로젝트를 위해서는 준비물이 몇 개 필요합니다. 

1. LED (당연하겠죠? ㅎㅎ)

2. 저항이 필요합니다. (5V이면, 500옴 정도면 적당하겠습니다.)
(라즈베리파이 스펙에는 전압 5V를 추천하는데, 소모전류를 봤을 땐 3V정도에도 문제 없을 듯 합니다.)

3. GPIO 핀 점퍼케이블 이나 확장 케이블세트
라즈베리파이에는 핀이 40개 있죠. 핀 하나 하나 연결할 수 있는 점퍼케이블도 좋고,
저는 40핀 짜리를 한번에 꽂아서 뺄 수있는 확장 케이블세트를 구입했습니다.
확장 세트에 각 pin 정보도 프린팅 되어있어 더욱 편리합니다.

4. 브레드보드
전자공학도라면, 이것 하나쯤은 가지고 계실 것 같습니다.
저와 같은 컴퓨터공학도라면, 하나 장만하시면 됩니다. ^^


LED와 저항은 지인을 통해 얻었지만,
케이블과 브레드보드 구입기는 아래 링크를 참고해주세요. : )
http://ironmask.net/387


아래에 그림들이 잘 안보이시면, 클릭해주세요! 큰 화면으로 보입니다. ^^


저항 띠색 읽는 방법

브레드보드에 부품을 세팅할 때는 전압, 저항, 전류를 고려해야 합니다.

사실 별 것 아닙니다만, 저항을 잘못 세팅하면, 많은 전류가 흘러 연결한 장치가 망가질 수 있습니다.

어릴 적 과학시간에 배웠던 V = I * R 을 생각해 봅시다 ㅋㅋㅋ

그리고, 저항을 얻어서 사용하다 보니 몇 옴짜리 인지 몰랐는데,

저항에 표시된 띠색깔로 값을 알 수가 있는 거였습니다.  :)

아래를 잘 참고하셔서 500옴 정도 되는 것을 고르세요 ㅎㅎ


 이 표에 따라 아래와 같이 읽으시면 됩니다. 


저항은 색띠의 개수가 4개인것도있고 5개인것도 있고 또 3개인것도 있습니다.

4색띠 읽는 방법은 위와 같습니다.

제 1색과 2색은 수로 십의 자리와 일의자리로 본 뒤에 승수를 곱하면 됩니다 그리고 오차범위를 구하시면 됩니다.

 

주황색(수) 주황색(수) 빨간색(승수) 금색(오차범위) 순서라면

3       3     *    100 =  3300Ω 이 되는 것입니다.

그리고 금색의 오차범위는 ±5%이므로

3300Ω,오차±5% 이렇게 읽을수가 있는것입니다

또 1000Ω =1kΩ이므로 3300Ω은 3.3kΩ으로 나타낼수가 있습니다.

​*여기서 오차범위란 저항이 항상 똑같은 값 만큼만 저항을 주는게 아니라서

약간의 오차가 있을수 있는데 그것의 범위를 나타내는 것입니다.

3300옴의 오차범위 5%는 165옴이므로

 3135옴 ~ 3465옴까지의 저항값이 오차가 있을수 있다는 것을 의미합니다.


이 또한 4색 저항 읽는 법과 비슷한데요 '제 3색(수)'가 추가되었을 뿐 4색 저항과 방법은 같습니다.

제 1색과 2색과 3색을 각자 백의 자리 십의 자리 일의 자리로 본 뒤에 승수를 곱해주시면 됩니다.

노란색(수) 보라색(수) 검정색(수) 검정색(승수) 갈색(오차범위) 순서라면

4       7        0     *    1 =  470Ω 이 되는 것입니다.

그리고 갈색의 오차범위는 ±1%이므로

470Ω,오차±1% 이렇게 읽을수가 있는것입니다

또 1000Ω =1kΩ이므로 470Ω은 0.47kΩ으로 나타낼수가 있습니다.

​*여기서 오차범위란 저항이 항상 똑같은 값 만큼만 저항을 주는게 아니라서

약간의 오차가 있을수 있는데 그것의 범위를 나타내는 것입니다.

470옴의 오차범위 1%는 4.7옴이므로

 465.3옴 ~ 474.7옴까지의 저항값이 오차가 있을수 있다는 것을 의미합니다.

출처 : 
http://blog.naver.com/ygs1090/220085805951


LED 컨트롤 C언어 소스코드

원래 디바이스 드라이버 부터 손대보려고 했기에, 

C언어로 접근을 먼저 해보려 합니다.

기존 제공하는 GPIO컨트롤 디바이스 드라이버를 사용하는 리눅스 응용프로그램을 만들면 되는데요.

리눅스 응용프로그램이란, C언어로 구현한 소스코드를 리눅스환경 버젼의 gcc 컴파일러로 컴파일해서 나온 결과물 입니다.

그리고, 라즈베리파이는 ARM 제조사의 코어를 사용하므로, 이에 맞는 버젼의 gcc 컴파일러가 필요한데,
이미 라즈비안OS에는 설치되어 있는 것 같군요. ^^

각설하고, 코드는 아래와 같습니다. ^^

#include <stdio.h>

#include <fcntl.h>

#include <string.h>

 

int led(int gpio)

{

    int fd;

    char buf[BUFSIZ];

 

    fd = open("/sys/class/gpio/export",O_WRONLY);  /* Export */

    sprintf(buf, "%d", gpio);

    write(fd, buf, strlen(buf));

    close(fd);

 

    sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio);  /* Direction */

    fd = open(buf, O_WRONLY);

    write(fd, "out", 4); /* input: write(fd, "in", 3) */

    close(fd);

 

    sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);  /* Output value */

    fd = open(buf, O_WRONLY);

    write(fd, "1", 2);

    close(fd);

 

    getchar();  /* Wait for key input */

 

    fd = open("/sys/class/gpio/unexport", O_WRONLY);  /* Unexport */

    sprintf(buf, "%d", gpio);

    write(fd, buf, strlen(buf));

    close(fd);

 

    return 0;

}

 

 

int main(int argc, char** argv)

{

    int gno;

    if(argc < 2)

    {

        printf("Usage : %s GPIO_NO\n", argv[0]);

        return -1;

    }

 

    gno = atoi(argv[1]);

    led(gno);

 

    return 0;

}



디바이스파일에 값을 출력해서 라즈베리파이의 GPIO를 제어할 수도 있습니다. 이 글에 나온 명령어와 코드는 "사물인터넷을 위한 리눅스 프로그래밍 with 라즈베리파이" 책의 108쪽부터 나온다고 합니다.


출처 : http://blog.naver.com/specialist0/221106973238


gcc 컴파일 후 나온 결과물 파일을 실행시킬 때, 

인자로 GPIO 핀 넘버를 붙여주시면 됩니다. ^^

ex) pi@raspberrypi :~ $ LED_Test 12  (12번 핀 일때)

LED 컨트롤 연결구조 및 시연


 확장케이블 세트와 브레드보드 입니다. 
 브레드보드 크기가 조금 아쉽네요.. 


 확장케이블과 브레드보드 그리고 저항과 LED 까지 연결한 모습!! 


 제대로 진행되었다면, 요로케 LED에 불이 들어옵니다. ^^ 


 LED 발 2개가 GPIO 핀과 GND에 담궈야 함을 잊지 마세요!! 


 

 라즈베리파이 프로젝트

라즈베리파이 프로젝트 실전#1 - LED 컨트롤
라즈베리파이 프로젝트 준비#4 - WIFI 설정
라즈베리파이 프로젝트 준비#3 - OS 설치 및 Putty SSH 접속
라즈베리파이 프로젝트 준비#2-1 - 구성품 리뷰

라즈베리파이 프로젝트 준비#2 - 구입 리뷰

라즈베리 파이 프로젝트 준비#1 - 스펙 리뷰
  




 

라즈베리파이 프로젝트 준비#4 - WIFI 설정

Posted by ironmask84
2017. 11. 8. 12:36 나는 프로그래머다!/Sensor


일단 프로젝트 기본 준비 과정은 이번 포스팅까지만 진행하고, 

추후에 필요한 부분에 따라 추가하도록 하겠습니다. (VNC Server 등)

프로젝트 진행이 너무 더딘 것 같아서 안되겠네요 ㅋㅋ

WIFI 설정까지 되면, 보드에 묶이는 선 하나가 줄어서 파워선만 연결하면 되니

조금은 보드 위치 조정에 자유로움이 있습니다.  :)

물론 WIFI를 제공할 무선공유기 혹은 스마트폰의 핫스팟 기능과 같이 AP가 있어야 해요!

아래에 그림들이 잘 안보이시면, 클릭해주세요! 큰 화면으로 보입니다. ^^


무선공유기를 이용한 라즈베리파이 WIFI 설정

유무선공유기를 사용하시면, 브라우져에서 192.168.0.1로 접속시 관리자 화면이 나옵니다.


 관리도구를 클릭해 줍시다!! 


그리고 나서 무선 설정/보안 메뉴로 이동해서,

SSID와 비밀번호를 확인해 둡시다!!


 인증방법은 꼭 WPAPSK로 안해도 됩니다만, 포스팅에서는 저걸 기준으로 합니다. 
 SSID와 비밀번호는 원하는 걸로 해주시면 됩니다. ^^ 


자, 이제 라즈베리파이를 유선을 통해 Putty로 접속합니다.

앞서 포스팅에서 유선 접속은 되었을 것이라고 보고 진행합니다. ㅎㅎ

아래와 같이 "wpa passphrase SSIDname password" 를 입력하고, 엔터키를 눌러보세요.


출력된 내용은 복사해 두고, 

"sudo nano /etc/wpa_supplicant/wpa_supplicant.conf" 명령어를 입력해서 nano편집기로 이동 후,

복사한 내용을 붙여넣습니다.


 편집 후에는 Ctrl + X 를 누른 후, Y를 눌러 저장하고 나가면 됩니다. 

자 이제 이것으로 WIFI 설정이 끝났습니다.

꽤 간단하죠?? ㅎㅎ

이제 "sudo reboot" 명령을 통해 리부팅 시킵시다.

설정이 잘되었으면, 유무선공유기 관리자 화면에서 아래와 같이 유선1개, 무선 1개 2개가 잡힙니다.



WIFI를 통해 Putty로 라즈베리파이에 SSH 접속하기

설정은 끝났으니, 이제 Putty로 라즈베리파이에 WIFI 접속을 해봅시다!


 위에서 유무선공유기 관리화면에서 확인된 IP를 입력해줍시다. 



 유선이든 무선이든 첫 접속에는 이런 key관련 창이 뜨는데, 예! 를 눌러주면 되죠 ㅋ 


자, 이제 랜선을 뽑고!! 

유선에서 벗어나서, WIFI 접속만 해봅시다!

위에 빨강박스를 보시면, WIFI인 wlan0만 잘 접속이 되어 있음을 확인할 수 있습니다. ^^

잘 진행 되시나요??

혹여나 질문 있으시면 댓글로 주시고,

다음 포스팅을 기대해 주세요 ^^


 

 라즈베리파이 프로젝트

라즈베리파이 프로젝트 실전#1 - LED 컨트롤
라즈베리파이 프로젝트 준비#4 - WIFI 설정
라즈베리파이 프로젝트 준비#3 - OS 설치 및 Putty SSH 접속
라즈베리파이 프로젝트 준비#2-1 - 구성품 리뷰

라즈베리파이 프로젝트 준비#2 - 구입 리뷰

라즈베리 파이 프로젝트 준비#1 - 스펙 리뷰
  




 

라즈베리파이 프로젝트 준비#2-1 - 구성품 리뷰

Posted by ironmask84
2017. 10. 24. 20:38 나는 프로그래머다!/Sensor



라즈베리파이로 (Raspberry PI) 프로젝트를 진행하고 있습니다만,

많이 더딥니다. ㅎㅎ

현재까지 Putty로 SSH 접속까지 진행했는데요. ( http://ironmask.net/389 )

조만간 WIFI 접속과 LED 컨트롤까지 진행을 할 예정입니다. ㅎㅎ

구입을 한 후에 제품 구성에 대해 한 번 리뷰하려고 합니다.

심플하지만, 구성이 깔끔하면서도 세심한 부분도 있어요 ^^

구입부는 아래 주소를 참조해 주세요 ^^

http://ironmask.net/387 )


기본 구성품

저는 가징 기본 세트인, 

라즈베리파이 3세대 + 정식케이스 + 방열판 세트 으로 구입했습니다.

아래 사진 나갑니다~ : )


 케이스는 위처럼 5가지 부품으로 나눠져 있어요! (색상은 레드, 블랙있는데 저는 레드로!!) 


 40개의 gpio핀과, BCM28xx CPU, SMSC 칩(이더넷 모듈) 등이 보이죠?? 


 뭐가 달라보이나요??  2개의 칩 위에 방열판을 붙였습니다. ㅋㅋ 


 바닥부분인데, 미끄럼방지용 스티커가 인상적입니다. ^^ 


 13인치 노트북 그램과 라즈베리파이 비교 
 물론 크기차이 만큼 성능차이, 가격차이도 큽니다. ㅋㅋ


 

 라즈베리파이 프로젝트

라즈베리파이 프로젝트 실전#1 - LED 컨트롤
라즈베리파이 프로젝트 준비#4 - WIFI 설정
라즈베리파이 프로젝트 준비#3 - OS 설치 및 Putty SSH 접속
라즈베리파이 프로젝트 준비#2-1 - 구성품 리뷰

라즈베리파이 프로젝트 준비#2 - 구입 리뷰

라즈베리 파이 프로젝트 준비#1 - 스펙 리뷰
  




 

네트워크#1 - TCP, UDP, MTU

Posted by ironmask84
2017. 10. 18. 16:31 나는 프로그래머다!/Sensor



라즈베리파이와 같은 네트워크 기능이 있는 디바이스를 가지고 개발을 하다보면,

네트워크 성능 측정 및 기능체크를 위해 'iperf' 라는 툴로 패킷을 주고받는 측정을 합니다.

이 iperf라는 툴을 사용 시에, 여러가지 옵션을 설정할 수 있는데,

그 중에 TCP, UDP와 같이 프로토콜 선택은 물론,

패킷 사이즈 및 갯수 등과 MSS(MTU 에서 특정 header를 뺀 것)을 설정할 수 있습니다.

예전에 네트워크 관련 스터디를 통해 들어본 바 있는 용어이지만,

다시금 뇌에서 되살려 보는 차원에서 기록 및 공유 합니다. 


TCP와 UDP

TCP 패킷 구조도


Sport =
송신자 포트

Dport= 수신자 포트

Sequence Number= TCP전송되는 데이터의 일련 넘버

Acknowledgment number= 응답 데이터 일련 넘버 + 전송된 데이터 합

Header Lengths = TCP Header 길이

Reserved = 예약된 번호 현재 사용되지 않음 항상 0

Control Bit = 패킷을 어떻게 다룰지 흐름등 관리하기 위한 사항

1.     URG = 최우선 순위 긴급한 패킷

2.     ACK = ACK필드 유효시 1

3.     PSH = 우선순위는 좀 떨어지더라도 최대한 빠른 전송 요청

4.     ROT = 현재 세션을 재 시작하려 할 때 사용 Session을 끊을때도 사용함

5.     SYN = Sequence Number를 송신측과 동기화하려 할 때 Session시작 시

6.     FIN = Session을 끊고자 할 때

Windows = 수신측에서 처리할 수 있는 Buffer

Checksum = TCP 오류 검증을 위한 데이터

Urgent Pointer= 급처리 데이터 마지막 바이트

Option = 필요시 생성 그다지

Padding = 32Bit의 배수를 만듬



UDP 패킷 구조도


LLC에서는 ethertype IP가 대입이 되어야 IP Packet이 되는 것이고 IP Header에서는 Type TCP UDP가 대입이 되어야지 TCP Packet UDP Packet이 만들어 집니다. ^^ 헤헤..


보시면 왜 MAC IP TCP순인줄은 금방 아시겠지요. ^^

         L2   L3 L4 입니다.

Layer Switch의 경우 L2Switch L3Switch L4Switch이렇게 나누자나요.


이 기준은 바로 Packet을 어디까지 분석해서 보내는지를 나타내는 거죠 ^^

IP만 보면 L3, Port까지 보고 스위칭하면 L4,


아무래도 앞에 있어야 분석하기 쉽겠죠. ^^ L2~L4까지 만약 L4가 먼저 있음 L2스위치는 포워딩하려면 L2데이터가 어딨는지 찾는데 딜레이타임이 걸릴 테니까.


또한 IP레벨의 스위칭도 여러가지 입니다.


보통은 목적지만 보고 라우팅하는데, 시스코의 CEF나 기타 프로토콜은 소스를 같이 보고 라우팅하죠. 이게 무슨 차이냐고 말씀하시는데 -_-;; 생각해보세요.

힌트는 LoadBanlancing입니다. 부하 분산에 차이죠. 라인이 하나라면 목적지만 보고 보내는 거랑 별 차이 없겠죠. 그러나 라인이 둘이라면 좀 다른 문제겠죠. ^^;;

출처: http://redsejo.tistory.com/4 [기도로 시작하는 하루]


MTU, MSS 란?

//MTU 란? http://qaos.com/article.php?sid=149

PING –f –l <MTU Size(Packet size + 28)> <interface default gateway address>
( 여기서 28은 'IP Header (20 bytes) + ICMP-Header (8 bytes)' )

Ex) ping <IP Address> -f -l <576~1500>로 값을 넣어 1472 로 값이 나왔다면 1472 + 28 = 1500 , 즉 MaxMTU 값은 '1500' 이 됩니다.


//MSS란(Maximum Segment Size)? 데이터 프레임 중 순수한 TCP 데이터 부분의 최대 값으로 분할하지 않고 한번에 보내는 것을 뜻합니다.

"윈도우 사이즈(크기) : TCP 환경에서 송신 호스트와 수신 호스트는 데이터를 수신한 다음, 다음 데이터를 보내 줄 것을 요청(Ack)하고, 요청을 받은 호스트는 다음 데이터를 보냅니다. 이런 과정에서 송신호스트는 Ack을 수신하기 전에 일정량의 데이터를 보낼 수 있는데 이를 윈도우 사이즈라고 합니다.

MSS(Maximum Segment Size) : 현재의 연결에서 TCP가 보낼 수 있는 최대의 데이터 크기를 말합니다. MTU라고 알려진 최대 전송 크기에서 헤더 부분을 뺀 부분이 MSS가 됩니다. Ethernet의 경우 MTU가 1500byte로 결정되어 있으며, 따라서 Ethenet에서 MSS는 1460byte가 됩니다.



" - 인용 ( 초보 서버 관리자를 위한 네트워크 및 보안 기초 포켓북 )

  
MSS = MaxMTU - 40 ( 40 = 'IP Header(20 bytes) + TCP Header (20 bytes + ? bytes)' )
Ex) 1500 - 40 = 1460 ( ? = 12byte , timestamp 옵션 적용시 추가됨 )

'Tcp1323Opts(Timestamp - RFC 1323)' 옵션에 'timestamp'이 활성화될 경우,
'Client ACK: TCP header'는 12byte를 추가한다. 즉, MSS 값은 1448 이 된다.

출처 : http://url.tistory.com/3

 

PHP와 Javascript 동작 개념

Posted by ironmask84
2017. 10. 17. 15:55 나는 프로그래머다!/PHP



웹프로그래밍을 하다보면, php와 JavaScript를 함께 사용을 프로그래밍을 합니다.

최근에야 php를 처음 접하다보니, JavaScript와 동시에 코딩을 하다보니, 

웹페이지에서 동적인 수행결과들에 대해 혼동이 오더군요 


간단하게 정리를 해보면,

php와 JavaScript둘다 동적인 웹페이지가 생성되면서, 제어되는 부분에서는 같지만,

php는 내부 데이터를 처리하기에 적합하고, JavaScript는 html로 보여지는 View 부분을 동적으로 제어하는 것입니다.


사실 php내에서도 Javascript 동작을 할 수는 있습니다.

ex) <?php
         echo "<script> window.open('main.php', '_self', ' '); </script>";
      ?>

반대로, javascript에서는 php를 이용한 제어는 불가하며, php에서 사용한 변수 값을 가져오는 정도는 가능합니다.

ex) <script>
         document.getElementById('current_time').innerText = '<?=$time?>';
     </script>


이유는, php는 서버에서 수행되고, JavaScript는 대부분 클라이언트(웹브라우져)에서 수행되기 때문입니다.

즉, php는 페이지 콜이 일어나는 순간 소스를 분석해서 내부 데이터 처리를 합니다. 

그리고 JavaScript는 만들어진 페이지 내에서 동적으로 페이지를 제어하는 방법을 제공해준다.

그러므로 JavaScript를 사용해서 동적으로 php를 다시 호출하거나 제어할 수 없습니다.





 

PHP 샘플코드 - 파일입출력과 문자열 파싱

Posted by ironmask84
2017. 10. 17. 10:21 나는 프로그래머다!/PHP



C언어 버젼에 이어 PHP 버젼으로도 파일입출력과 문자열 파싱 들어갑니다!
http://ironmask.net/392 )

전반적으로 C언어와 비슷한데,

함수가 좀 더 사용성이 좋고, 다양한 느낌이 있습니다.

이용한 함수보다 더 다양하게 제공되는 함수들이 있으니,

간략하게 잘 정리된 블로그를 공유드립니다. ( http://slreference.tistory.com/8 )


주제 요약 설명

PHP 언어로 파일을 읽어와서

특정 키워드 를 포함하는 함수를 통해 값을 얻어오고,

특정 delimiter로 파싱해서 결과물을 얻는 코드 입니다.

주요 사용 함수는 fopen, fgets, parse_strisset, strchr, explode입니다.

프로그래밍 언어의 기본 문법과 함수에 대한 사용법을 어느 정도 숙지하신 것을 

기본 전제로 진행합니다. ^^


샘플 코드

아래 코드는 file을 읽어와서 내장함수 parse_str을 이용한 것입니다.

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
<?php
 
// form을 wifiSet.php로 보내서, 파일 저장
 
include "settings.php";
 
// wifi setting
$fp = fopen("wifisetting.txt""r+");
if (!$fp) {
    die("<br/>Failed to open file.");
    echo "<script> alert('Failed to open file.'); </script>";
}
 
// wifienable=0&networkName=1 형식의 문자열을 wifienable 변수 생성 후 0을 넣어주고, networkName변수 생성 후 1을 넣어주는 함수
parse_str(fgets($fp));
 
// 예외처리는 각 설정에 대한 변수가 있느냐?  isset() 함수 그리고 그 변수에 값이 있느냐?  empty() 함수 <- true/false 반환
// 예외에 걸리면, 보드에서 새로 값 가져오기? or 설정파일 다시 생성??
 
if(isset($wifienable)){    // 예외처리를 위한 $wifienable 변수 존재 여부
    $WIFI_Setting['wifienable'= $wifienable;
}
if(isset($networkName)){
    $WIFI_Setting['networkName'= $networkName;
}
if(isset($channelselect)){
    $WIFI_Setting['channelselect'= $channelselect;
}
 
fclose($fp);
 
?>
cs


아래는 웹에서 접근했을 때 외부프로그램인 윈도우에서 제공하는 ipconfig 명령어를 수행한 결과를

strchr과 explode를 이용해서 문자열을 파싱해서 값을 얻어오는 부분입니다.

1
2
3
4
5
6
7
8
9
10
11
<?php
 
    $data1 = iconv("EUC-KR""UTF-8", shell_exec("ipconfig"));    // ironmask unicode 문제 해결 2017-09-18
    $data1_token1 = strchr($data1"이더넷");  // 전체 문자열에서 '이더넷' 문자열이 나오는 부분부터 끝까지 값 복사
    $data1_token2 = strchr($data1_token1"IPv4 주소 . . . . . . . . . : ");
    $data1_token3 = explode(" "$data1_token2);    // delimiter로 문자열 자르기
    $data1_Ipv4 = explode("."$data1_token3[12]);    // 원하는 문자열 값 얻기
 
    echo $data1_Ipv4[0] . "." . $data1_Ipv4[1] . "." . $data1_Ipv4[2] . "." . $data1_Ipv4[3];  // IPv4 출력
    
?>
cs


아래는 위 소스에서 사용된 파일을 write하는 내용 입니다.

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
<?php
 
$wifienable = $_POST['wifienable']; // Radio Button
 
$networkName = $_POST['networkName'];                // check box
$networkName_count = count($_POST['networkName']);  // check box 에서 체크된 녀석 count
 
$channelselect = $_POST['channelselect']; // Select Button
 
 
$fp = fopen("wifisetting.txt""w+");
if (!$fp) {
    die("<br/>Failed to open file.");
    echo "<script> alert('Failed to open file.'); </script>";
}
fwrite($fp"wifienable=");
fwrite($fp$wifienable."&");
 
fwrite($fp"networkName=");
fwrite($fp$networkName_count."&"); // 우선은, 체크박스가 1개인 경우는 체크되면 1 아니면 0 
 
fwrite($fp"channelselect=");
fwrite($fp$channelselect);
fclose($fp);
 
echo "<script> window.open('wifi.php', '_self', ' '); </script>";
 
?>
cs




'나는 프로그래머다! > PHP' 카테고리의 다른 글

PHP와 Javascript 동작 개념  (0) 2017.10.17
 

라즈베리파이 프로젝트 준비#3 - OS 설치 및 Putty SSH 접속

Posted by ironmask84
2017. 10. 4. 17:12 나는 프로그래머다!/Sensor


이제 라즈베리파이 구입해서 배송까지 받았으니,

http://ironmask.net/387 )

라즈베리파이를 작동시키고, 

프로젝트 진행을 위한 환경 세팅을 해보겠습니다.

라즈베리파이를 구동시키는 OS로 Raspbian 이라는 리눅스 기반 OS가 이미 제공되고 있습니다.

이 OS는 Debian이라는 PC용 리눅스 OS를 기반으로 만들어졌다고 합니다.

사실 라즈베리파이 3세대는 손바닥만한 펜티엄 PC라고 해도 될 정도의 성능을 갖췄습니다.

http://ironmask.net/349 )

CPU가 쿼드코어의 1.2Ghz 이며, RAM이 1GB에 블루투스, WIFI, 이더넷, USB 2.0 , HDMI 를 갖췄습니다.

최신 스마트폰의 성능에는 못미치지만, 쿼드코어 PC가 유행하기 시작한지가 8년전 쯤이었으니,

35달러에 이정도 성능이면 어마어마한 전자 하드웨어 보급의 결과입니다. ㅎㅎ

아무튼 Raspbian 이라는 OS를 다운받고,

설치는 라즈베리파이에 따로 저장장치가 없으므로,
micro SD 카드(16GB 적당)를 따로 구해서 설치를 하여야 합니다.

자, 그럼 본격적으로 설치를 해볼까요!! 


OS 설치 방법

우선, 1. Raspbian OS 이미지를 다운 받습니다.

https://www.raspberrypi.org/downloads/raspbian/


그리고 2. 다운받은 이미지 파일을 micro SD카드에 설치해주는 win32diskimager 라는 프로그램을 다운받습니다.

https://sourceforge.net/projects/win32diskimager/



3. Win32 Disk Imager를 설치하고, micro SD카드를 리더기를 통해 PC에 연결합니다.

4. Win32 Disk Imager를 실행해서, 이미지파일을 Write 해줍니다. (대략 7~8분 소요)


 대략 이런 모습으로 Write 되어갑니다 ㅎㅎ
 요즘 노트북엔 SD카드 슬롯이 대부분 내장되어 있죠! ㅎ 


위까지 과정을 거치면, 윈도우에서는 그냥 boot라는 저장장치로 잡히고, 용량도 60메가 정도만 보입니다.

하지만, 이는 OS간 파일시스템이 달라서 윈도우에서 안보이는 것 뿐이고,

라즈베리파이에서는 정상적으로 용량이 잡히니 걱정안하셔도 됩니다. ^^

그럼, 이제 제대로 OS가 설치 되었는지 확인을 해봐야 할텐데요 ㅋㅋ


노트북을 이용해서 Putty로 라즈베리파이에 SSH 접속하기

라즈베리파이는 이더넷 통신이 가능한 랜포트가 있으므로, 

PC와 이더넷 통신이 가능합니다.

데스크탑의 경우 보통 랜카드는 1개인데, 무선랜카드가 없으므로,

인터넷을 이용하려면 라즈베리파이는 공유기로 이더넷을 연결하는 것이 좋습니다.

이 때는 공유기가 알아서 라즈베리파이에 ip주소를 할당해주고, 

데스크탑에서 공유기 관리자로 접근해서 라즈베리파이의 ip를 확인할 수 있으므로 별 문제가 안됩니다만, 

노트북을 이용해서 외부로 나가서 라즈베리파이에 접근하려면 공유기를 사용하지 않기 때문에

라즈베리파이의 ip를 확인할 수 없으므로 라즈베리파이의 IP를 알아야 가능한데요.

그래서 라즈베리파이의 IP를 고정 IP로 변경을 해야 합니다.


1. 라즈베라파이 고정 IP 설정

OS 설치 과정을 거치면, micro SD카드가 boot라는 저장장치로 잡힙니다.

탐색기에서 들어가보면, cmdline.txt 라는 파일을 볼 수가 있는데,

이를 워드패드나 다른 편집기 tool로 열어줍니다. (메모장은 비추천)

마지막으로 가서 한 칸 띄고 ip = 192.168.137.100 으로 쓰고 저장합니다.

마지막 세자리는 꼭 100이 아니어도 되지만, 기본 사용 ip와 충돌날 수도 있으니, 

100으로 하시면, 안전합니다.


2. 노트북 고정 IP 설정

자, 이제 라즈베리파이의 ip주소를 고정으로 해뒀으니,

노트북의 ip도 고정으로 해줘야 접속이 됩니다. 

(이유는 이더넷 프로토콜에 관련한 것으로, 자세한 건 생략합니다.  )

노트북 ip 고정 방법은 윈도우7 기준으로

제어판 -> 네트워크 및 인터넷 -> 네트워크 및 공유센터 -> 어댑터설정 변경 -> 해당 로컬 영역 선택 -> 속성 -> IPv4 로 

들어가서 다음 IP 주소 사용으로 바꾼뒤, 192.168.137.101 로 설정해 줍시다!


3. SSH Server 활성화

그리고 2016년 11월 부터는 한 가지 추가로 설정을 해줘야 할 것이 있습니다.

Putty로 접속 시, 자꾸 connection refused 가 나서 검색을 열심히 해서 알아보니..

라즈비안(Raspbian)에서 2016년 11월 release판 부터 SSH Server가 Default로 비활성화 되어 있다고 하네요 ㅡ_ㅡ

역시 최신 버젼에는 항상 뭔가 기존 정보로는 문제가 발생하기 쉽상입니다.. ㅜㅜ

뭐 물론 보안상 비활성화가 Default인 것이 맞긴 합니다만, 첨에 좀 답답했습니다.. ㅋㅋ

하지만, 간단하게 SSH Server를 활성화 시키는 방법이 있습니다!!

HDMI나 Serial to USB 케이블을 통해 따로 접속하지 않아도 활성화 시킬 수 있습니다!!

OS 설치 과정을 거쳐서, micro SD카드가 boot라는 저장장치로 잡히는 공간에 ssh 라는 이름의 파일만 만들어 주면 됩니다.

파일 안에 내용은 아무 상관 없습니다. 그냥 편집프로그램 열어서 ssh 라는 이름으로 확장자를 꼭 없도록 해서 만들면 됩니다.


4. Putty로 SSH 접속~ ㅎㅎ

자, 이제 micro SD카드를 라즈베리파이에 장착시키고, 전원을 줍시다.

그리고 랜선으로 PC와 라즈베리파이를 연결하고, putty 프로그램을 실행시켜봅시다.

putty  프로그램은 무료 다운 가능합니다.

http://software.naver.com/software/summary.nhn?softwareId=MFS_116451  )

아래 그림과 같이 접속이 잘 되는 것을 볼 수 있습니다. ^^

Raspbian OS 기본  ID는 pi 이고,  password raspberry 입니다.


 캡쳐엔 192.168.0.100 인데 192.168.137.100 으로 하면 됩니다. 


 처음 라즈베리파이에 putty로 접속 시, 뜨는 화면인데 그냥 예 해주면 됩니다. ^^ 



드디어, 대망의 Putty로 SSH 접속 입니다!! :) 


PC와 공유기를 이용해서 Putty로 라즈베리파이에 SSH 접속하기

데스크탑이든 노트북이든 공유기가 있으면 이더넷 통신이 가능합니다. ^^

주의할 점은 공유기 뒤에 보통 1개의 WAN포트와 여러개의 LAN 포트가 있는데,

그 중에 WAN은 건물에 들어오는 인터넷선을 연결하는 용도이니 놔두시고,

LAN 포트에 꽂아주시면 됩니다.

라즈베리파이에 전원선을 꽂고, 이더넷선으로 공유기와 연결을 합니다. ㅎㅎ

제가 연결한 사진은 아래와 같습니다. iptime 유무선 공유기에요 : )


그리고 나서 웹브라우져에서 192.168.0.1 로 접속하시면 아래와 같이 iptime 공유기 관리화면이 출력됩니다.



 관리도구 메뉴를 선택해 줍시다. ^^ 


 관리도구 메뉴를 선택해 줍시다. ^^ 

자, ip가 확인이 되었으니, Putty 접속은 위에 나와있는 노트북과의 접속과 같은 방법으로

ip만 변경시킨 후에 접속하시면 됩니다. ^^


 

 라즈베리파이 프로젝트

라즈베리파이 프로젝트 실전#1 - LED 컨트롤
라즈베리파이 프로젝트 준비#4 - WIFI 설정
라즈베리파이 프로젝트 준비#3 - OS 설치 및 Putty SSH 접속
라즈베리파이 프로젝트 준비#2-1 - 구성품 리뷰

라즈베리파이 프로젝트 준비#2 - 구입 리뷰

라즈베리 파이 프로젝트 준비#1 - 스펙 리뷰