Home

더 나은 프로그래머가 되기 위해 알아야할 모든것은 이미 유치원에서 우리는 배웠다.

All I Need To Know To Be A Better Programmer I Learned In Kindergarten"라는 오래된 글이지만, 훌륭한 프로그래머가 되는 것은 먼 곳에, 어려운 곳에 있지만은 않다는 느낌을 받았습니다. 기본적인 내용들이지만, 그동안 바쁘다는 핑계로 잊었던 것들을 다시 생각해 보는 계기가 되었네요. 그리고 조금씩 먼저 실천해 가는 개발자만이 훌륭한 프로그래머로 되지 않을까요? 생각해 보면서 정리해 봅니다.

프로그래밍은 참으로 복잡한것이다. 그렇지만, 훌륭한 프로그래머가 되기 위해서 필요한 대부분의 것들은 우리가 어릴때 학교에서 배운 것과 크게 다르지 않다. 즉, 훌륭한 프로그래머는 어릴때 유치원에서 배운대로만 하면 된다는 이야기다.

아래의 리스트에 대한 영감은 Robert Fulghum의 All I Really Need to Know I Learned in Kindergarten"라는 에세이에서 많이 왔다.

1. 모든 것을 공유해라.
가능하면 오픈 소스를 사용하고 할 수 있다면 기여까지(contribute) 해보자. 커뮤니티의 집단 지성은 몇몇 대기업의 제한된 비전(생각들)보다는 훨씬 좋다.

2. 공평하게 해라.
다른 기술들이나 프레임워크, 방법론, 그리고 의견들에 기회를 주자. 자신의 선택만(내 방법만) 잘 동작한다고 생각하면 안된다. 다른 대안들도 잘 동작할 수 있고 열린 마음으로 다른 것들을 알아가는 것도 좋다.

3. 사람을 공격하자 마라.
2번에서와 같이 사람들이 .net이나 Java, PHP를 사용하고 있다는 이유만으로 그들을 공격하지 말자. 때로는 그들이 당신이 생각하는것보다 훨씬 사용성이 좋고 더 유용할 수 있다. 당신이 그들을 공격하지 않는다면 당신은 그들로부터 더 많은 것을 배울 수 있다.

4. 내가 어질른것은 내가 정리하자.
잘 동작하는 코드를 배포할 수 있도록 노력하자. QA가 너의 모든 버그를 찾아준다고 생각하면 안된다. 자주 테스트하고 때로는 치밀하게 때로는 광범위하게 테스트 하자.

5. 내것이 아니면 가지지 말자.
자신이 사용하는 것의 라이센스를 따르자. 절대로 훔치는 것은 안된다. 그리고 나중에 몰랐다고 잡아때도 안된다.

6. 사람을 다치게 했다면 꼭 미안하다는 말을 하자.
코드 리뷰는 매우 좋은 것이지만, 거의 행해지지는 않는다. 당신보다 경험이 없는 프로그래머에게 가르쳐주는 것은 팀 전체에는 큰 도움이 된다. 사람들을 공개적으로 비난하는 것을 그만하자. 학습은 사람을 경시하는 것이 아니다. 때때로 사람들은 내말을 들어줄때도 있고 그렇지 않을때도 있다. 나 자신보다 못하다고 생각되는 사람으로부터 많은 것을 배울수도 있다.

7. 먹기 전에 손을 씻자.
코드를 작성하기 전에 대상을 잘 이해하도록 노력하자. 프로토타입을 만들고, Web상에서 예를 체트해 보자. 같은 일하는 동료와 이야기하거나 심지어 같이 노는 것도 좋다. 경험을 하지 않았거나 사용한적이 없는 것을 구축하는 것은 매우 힘들다. 결국 단서를 가지고 일을 시작하면 결과는 잘 마무리 될 것이다.

8. 사용이 끝나면 물을 내리자.
사용할 수 없는 물건을 바꾸거나 다시 작성, 리팩토링, 그냥 포기하는 것을 두려워하면 안된다. 때로는 의심스럽다면 던져버리는 것이 최고의 철학이다. 그리고 결코 자신의 코드와 사랑에 빠지면 안된다.

9. 따뜻한 쿠키와 찬 우유는 건강에 좋다.
물론 프로그래머는 자신의 업무 환경이 좋아야 한다. 좋은 의자, 조용한 환경, 최신 PC에, 더 좋고 더 쉬운 코드를 만들수 있는 도구가 필수적이다. 관리자는 프로그래머에게 떨어지는 것을 지켜주는 우산 역할을 하는 것이다. 프로그래머라면 저급한 노예의 삶을 거부하자. 만약 고용주가 너를 하찮게 취급한다면, 다른 더 좋은 회사를 찾아라.

10. 균형된 삻을 살자 - 매일 조금씩 배우고, 생각하고, 그리고 칠하고, 노래하고, 춤추고, 놀고, 일하자.
나는 자신이 가치 있다고 생각하면 뭐든지 20%의 시간을 투자할 수 있는 Google의 20%룰을 좋아한다. 고용주들은 별도로 낮잠을 자는 룸이나 게임룸이나 긴장을 풀어주는 환경을 준비해야 한다. 프로그래밍은 정신적으로 매우 힘든일이다. 때때로 우리의 뇌를 쉽게해주는 것이 필요하다. 일상적인 주 80시간 노동은 당신이 만든 제품을 품질을 파괴하기 때문에 거부하자.(자신을 녹초로도 만들수 있다)

11. 오후에는 꼭 낮잠을 자자.
하루 24시간 일하는 것은 전혀 생산적이지 않다. 휴식을 취하고, 집으로 가서 제대로 수면을 취하라. 나는 종종 고약한 문제를 집에 가는동안에 해결될 때가 있었다. 퇴근길 운전중에, 혹은 다음날 아침에 해결 방법이 떠올랐다.

12. 밖에 나갔을때는 차를 조심하고 손을 잡고 함께 건너자.
커뮤니티활동은 아주 중요하다. 블로그를 읽고, 새로운 언어와 프레임워크에 대해 배우자. 토론에 참여하고 다른 사람이 하고 있는 것을 보라. 일을 하는 것만으로는, 훌륭한 프로그래머가 될 수 없다. 독불장군이 된다면 당신은 결국 쓸모없게 된다.

13. 궁금한것은 알아보라. 스티로폼컵 속의 씨는 뿌리가 자라고, 식물이 자란다. 아무도 그것이 어떻게, 왜 그런지는 모른다. 하지만, 우리 모두는 그것과 같다.
매일 새롭고 멋진 것들이 프로그래밍과 기술 세계에 일어나고 있다. 알아 보자. 매혹될 것이다. 매일 새로운 어떤 것을 배우자. 그래서 너의 마음은 신선해지고 너의 선택은 넓어지고, 기술력이 업데이트 된다. 만약 프로그램이 지루하거나 재미없다고 생각한다면 새로운 일을 찾는 것이 좋다.

14. 금붕어와 햄스터, 생쥐, 스티로폼 컵속에 씨앗조차 모두 죽는다. 우리들도 죽는다.
코드도 오래되면 나빠지고 죽는다. 때로는 그것을 아주 묻어주거나 혹은 다시 작성해야 한다. 돈을 아낄려고 더러운 코드를 유지보수하는 것은 전쟁이다.

15. Dick와 Jane의 동화책을 기억하고 먼저 배운 말을 생각해 보자 - 가장 중요한 단어는 "보는 것"이다.
만약 시도하지 않으면 아무것도 배울 수가 없다. 내가 프로그래밍에서 배운 모든것은 새로운 것들을 시도하거나 노는데서 왔다. 매일 아침 나는 프로그래밍 세계에서 무엇이 이어나고 있는지를 알기 위해서 여러 사이트들을 읽었다. 나는 이것을 80년대 초부터 계속 진행하고 있다.(당시는 카탈로그와 잡지들만 읽을지만.)

봐라, 5세의 눈을 통해서 보면 프로그래밍은 이렇게 간단하다.
Tags :

Vitess

YouTube의 거대한 동영상 시청 데이터 및 메타 데이터를 관리하고 있는 MySQL의 스케일 기능을 담당하는 Vitess를 오픈 소스로 공개했다.

1. 아키텍처


2. Vitess의 주요 특징
- SCALABILITY
  • MySQL의 커넥션에 걸리는 메모리 오버 헤드 제거.
  • 어플리케이션의 샤드 로직 추가없이 데이터 베이스 확장.
  • 샤딩 기능 내장.
  • 읽기 다운 타임 최소화가 가능하고 라이브 리샤딩 기능 지원.

- PERFORMANCE
  • 데이터베이스 성능에 문제를 야기하는 쿼리를 자동 재작성함.
  • 프록시 서버에서 캐싱 메커니즘을 활용하여 쿼리 조정이나 중복 쿼리 제거.

- MANAGEABILITY
  • etcd과 Zookeeper와 같은 락 서버를 통해 서버군들을 추적 및 관리 할 수 있음.
  • 마스터 장애조치, 백업 등의 기능을 자동화함으로써 다운 타임을 최소화 해 줌.

[참조 사이트]
Tags : ,

생산성과 창의성, 그리고 문화

급박한 일정에 놓여있고 빨리 개발하는 개발자를 편애하는 환경속에서 있다보니 생산성이 암묵적으로 중요하다는 생각이 우리의 머리에 자리잡고 있다.


그 부작용으로 창의력과 문제해결 능력을 갖고자 생각의 시간을 갖는 사람을 프로젝트에서 방해자로 간주되기 쉽게 되고 사람을 단지 목적을 달성하기 위한 종속자 역할만을 바라보게 된다.


그래서 단순 개발 효율화를, 빠른 피처 개발만이 생산성으로 치부해 버리고 생산성과 창의성의 반비례가 고착화된다.


구성원과 조직의 비전을 이해하고, 부족한 부분을 찾거나 메워주고, 상호 인식의 전환과 공유 노력을 하고, 목표에 기반한 조직력 증대 등 개발 문화 형성에 모든이들의 노력해야 생산성과 창의성은 정비례로 가게 될 것이다.


또한, 문화의 혜택을 자신의 편이로 활용하기보다는 더 나은 문화를 만드는데 일조하도록 지속적으로 노력해야 그 문화가 유지된다.


생산성, 창의성, 문화는 서로 결부되었을때 성숙될 것 같다.

삶의 태도

1. 가정을 하는것보다 질문을 하는것이 낫고 질문보다 그전에 한번 내가 온전히 할 수 있는지에 대해 조사하고 고민해보자. 증명을 하지 않는 가정은 실수를 낳게 하고 무조건 질문 먼저 하게되면 스스로 배울 기회를 앗아가고 기본기가 떨어지게 만든다.

2. 들을 땐, 검색할 땐 배우는 자세로, 그리고 듣고 검색한 후에는 맞는지 혹은, 내 것으로 만드는 후행학습을 하자. 그러면 경험 지식으로 만들어버려 오래갈 수 있다.

3. 코드나 문서 등은 내 얼굴이라고 생각하고 리팩토링이나 리뷰의 습관을 가지고, 문서는 필요한 경우에 한해 하며 항상 유용성과 현행화를 고민하자.

4. 인간에게 인식과 이해는 비동기적으로 일어나기 때문에 될 수 있으면 쉽게 말하는 버릇을 가지고, 중요한 건 캐싱이 안되고 별거아닌 기분 나쁜건 오래 캐싱되기에 완곡하게 표현하는(기분이 나빠도 한템포 참고 넘어가는) 습관을 가지자.

5. 목표 때문에 필요가 생겨나고 그 필요에 의해 의도가 생기니 굳이 친한 관계가 아니면 의도를 숨기는 편이 나은것 같다.

6. 인간은 형편보다 기회에 초점을 맞추다보니 자신의 유용성을 항상 강구하고 갖추기를 노력하고 어필한다.

코드를 쓴다는 것

언어의 선택도 고민해 보고
다양한 방법이 있다는 것도 생각해 보고
코드 리뷰를 통해 남의 생각도 알아보고
테스트를 통해 코드의 정당성도 확보해 보고

그러면서 코딩하다보면 소프트웨어가 된다.

코드를 쓴다는 것은 무한한 가능성을 버리고 단 하나의 방법을 선택하는 것이다.

그만큼 코드를 쓰는데 많은 고민이 필요하다.

그렇다고 코드를 쓰는 것을 주저하지 말며
내가 발전해가는 것만이 코드에 대한 최소한의 양심이다.
Tags :

Peter Thiel과 그가 생각하는 미래

PayPal의 창업자이자, 투자자(Facebook, Friendstar, Powerset, Linkedin, Quora, Zynga, Yammer, SpaceX)인 Peter Thiel이 쓴 Zero To One을 읽으면서 Peter Thiel이 어떤 사람인지 궁금했다. 이분은 참 독특하면서도 재밌다. Facebook 투자로 억만장자가 되었고, 그 사람의 투자한 회사들을 보면 미래가 어떻게 흘러가리라 예상할 수 있다.

그리고 Peter Thiel을 알기전에 먼저 Paypal Mafia에 대해 먼저 알 필요가 있다. Peter Thiel은 페이팔 마피아의 대부였기도 했고, 이들은 서로 서로 창업을 한 동료들을 투자해주기도 했지만, 그들이 투자하고 창업한 회사들은 하나같이 유명한 회사들이어서 살표보면 놀랍다.

Paypal Mafia

  • Peter Thiel : PayPal 창업자, eBay에 $1.5 billion에 매각. Facebook, Friendstar, Powerset, Linkedin, Quora, Zynga, Yammer, SpaceX 투자자.
  • Max Levchin : Slide를 Google에 매각해 부사장됨.
  • Elon Musk : Space X 창업, Tesla Motors 창업, Tesla IPO.
  • Reid Hoffman: Linkedin 창업, Facebook, Friendster, Six Apart, Zynga, IronPort, Flickr, Digg 등의 스타트업에 투자하는 등 투자자로 행보를 이어감.
  • David Sacks : Yammer 설립 후 2012년 6월에 $1.2B로 Microsoft에 Exit.
  • Jeremy Stoppelman(Yelp/CEO), Russel Simmons(Yelp/CTO) : Yelp 창업.
  • Steve Chen(Youtube/CTO), Chad Hurley(Big Six/Founder), Jawed Karim(Youniversity Ventures/Partner) : Youtube를 Google에 Exit.
  • Keith Rabois : Square에서 COO로 있다가 투자자로 행보를 이어감.
  • Roelof Botha : Sequoia Capital에서 PayPal 마피아 회사에 많은 자금을 제공하고 있고, Facebook과 Youtube에 투자함.

Singularity



미국의 발명가이자 미래 학자 Ray Kurzweil이 쓴 "How to Create a Mind:The Secret of Human Thought Revealed"에서는 컴퓨터가 인간의 뇌가 가진 패턴을 시뮬레이션이 가능하며, 현재 속도로 컴퓨터의 성능이 상승한다면, 기술이 기하급수적으로(산술급수적이 아니라) 발전하기 때문에 2029년 컴퓨터의 능력은 개별 인간을 뛰어넘고, 2045년엔 전 인류 지능의 총합마저 크게 앞질러 버린다고 그는 예측했다. 이 시점을 그는 '특이점(singularity)'이라고 부른다.

Peter Thiel도 기술적 특이점의 중요성을 매우 느끼고 연구를 위해 2006년 2월과 2007년 5월에 인공 지능 특이점 연구소에 50만 달러의 투자를 하고 있다. 또, NY과 스탠포드에서 개최된 Singularity Summit에 참가했었다.

- 그외 Singularity를 향한 움직임
  • 미국에서 차세대 리더를 육성하고 인류가 직면 한 큰 과제를 해결하는 것을 목표로하는 Singularity University가 개설 되었다. 창립자는 Ray Kurzweil 박사(저술가, 과학 기술자, 미래 학자), Peter Diamandis 박사(XPRIZE), Pete Worden(NASA Ames 연구소 소장), Robert L. Richards 박사(International Space University(ISU)의 창립자 중 한명), Robert D. Richards 박사(ISU의 학장) Michael Simpson 박사, 또한 Google이 스폰서로 지원하고 있다.

해상 국가



Google의 엔지니어였던 Patri Friedman이 2008년 해상 인공 국가 실현을 목표로 캘리포니아의 Seasteading Institute를 설립했는데 자유주의를 표방하는 Peter Thiel이 2011년까지 125만 달러를 투자했다고 한다. Seasteading Institute를 부연 설명하자면, 공해상에 석유 플랫폼과 같은 인공섬을 건설하고 독립 국가를 창설하는 것을 목표로하고 있다. 자세한 내용은 여기를 참조하기 바랍니다.

[첨조 사이트]
Tags : ,

Make에 대해 알아야할 7가지

Make 파일에 대해 그나마 괜찮은 블로그 포스트가 하나 있어 소개합니다. 제목은 "Make 대해 알아야 할 7 가지"인데, 이것만 보면 makefile을 만들거나 만든거에 대한 이해를 도와줄 수 있을 거 같습니다.

구체적인 내용은 아래와 같습니다.

Make는 다양한 유형의 파일들을 자동 빌드하는데 간단하면서도 강력한 도구이다. 그러나 makefile을 작성할 때 문제가 발생하는 프로그래머들도 있고, Make의 기본 지식이 없어 기존에 있는 것을 다시 만드느라 시간을 낭비하는 프로그래머들도 있다.

Make는 어떻게 동작하나?

기본적으로 Make는 첫번째 target에서 시작한다. 이 target을 디폴트 목표(goal)라고 한다.

Make는 현재 디렉토리의 makefile을 읽고 가장 먼저 룰(규칙) 처리를 시작한다. 그러나 Make가 완전히 이 룰(규칙)을 처리하기 전에 룰(규칙)이 종속 파일에 대한 룰을 먼저 처리해야 한다. 각 파일들은 자신의 룰에 따라 처리된다.

사실 이것은 각 target의 재귀 알고리즘으로 되어 있다.
  1. target을 빌드하는 룰(규칙)을 찾아낼 것이다. 만약 target을 빌드할 룰(규칙)이 없다면, Make는 실패한다.
  2. target의 전제 조건이 있는 경우 그 전제 조건과 함께 알고리즘이 실행된다.
  3. target이 존재하지 않거나 전제 조건의 갱신 시간이 target의 갱신 시간보다 이후인 경우 target과 관련된 레시피를 실행한다. 레시피가 실패한다면, (보통) Make도 실패한다.

할당 유형

Make는 makefile을 쓰는 것을 단순화하기 위해 변수가 지원된다. =, ?=, :=, ::=, +=, != 연산자 중 하나를 가지고 할당된다. 각 연산자의 차이점은 다음과 같다.
  • =는 지연된 값을 변수에 할당한다. 즉, 변수가 사용될 때마다 변수의 값이 요구된다는 의미이다. 쉘 명령의 결과를 대입할 때 - 변수가 읽혀질 때마다 쉘 명령이 실행된다는 것을 잊지 마시라.
  • :=::=는 기본적으로 같은 의미다. 이러한 대입은 변수값을 한 번만 처리하고 그 값을 저장한다. 단순하고 강력하다. 이런 유형의 할당은 디폴트로 선택되어야 한다.
  • ?= 는 변수가 정의되지 않은 경우에만 := 역할을 한다. 그렇지 않은 경우는 아무것도 하지 않는다.
  • +=는 더하기 대입 연산자이다. 변수가 미리 := 또는 ::=에 설정되어 있는 경우, 우변은 즉시 값으로 간주된다. 그렇지 않으면 지연된 값으로 간주된다.
  • !=는 쉘 대입 연산자다. 우변은 즉시 평가되고 쉘에 전달된다. 결과는 좌변의 변수에 저장된다.

패턴 룰

동일한 룰(규칙)을 가진 파일을 많이 가지고 있는 경우 모든 target을 일치시키기 위해 패턴 규칙을 쉡게 정의할 수 있다. 패턴 규칙은 target에 '%'가 있는 것을 제외하고는 보통의 룰(규칙)과 비슷하다. 패턴 룰의 타겟은 파일 이름과 일치하는 패턴이라고 판단되며 '%'는 공백이 아닌 부분 문자열에 일치시킬 수 있다.

내 블로그 디렉토리에는 다음과 같은 Makefile을 만들 수 있다.
all: \
    build/random-advice.html \
    build/proactor.html \
    build/awesome_skype_fix.html \
    build/ide.html \
    build/vm.html \
    build/make.html \

build/%.html: %.md
    Markdown.pl $^ > $@
$@가 target을 의미하는 반면, $^ 의존 관계를 의미하는 자동 변수다. 그래서 이 룰은 단순히 마크다운 파일 변환기에 전달하는 룰이다. 패턴 룰의 작성과 자동 변수에 대한 자세한 내용은 설명서를 참조 하라.

디폴트 묵시적 룰

GNU Make에는 기본 룰(규칙)이 있다. 많은 경우 명시적 룰을 사용할 필요는 없다. 디폴트 묵시적 룰 목록은 C, C++, 어셈블러 프로그램의 컴파일 룰과 그들을 링킹(연결)하는 것을 포함하되 제한은 없다. 전체 목록은 Make 설명서에서 볼 수 있다.

Makefile에 아무것도 하지 않는 것도 가능하다. 예를 들어, 단순히 hello.c라는 파일에 프로그램 소스 코드를 저장하고 단순히 make hello를 실행할 수도 있다. Make는 hello.c에서 hello.o를 자동으로 컴파일하고 hello에 링킹(연결)한다.

레시피는 $(CC) $(CPPFLAGS) $(CFLAGS) -c 형식으로 정의한다. 변수를 변경하여 룰을 바꿀 수 있다. 소스 파일을 clang으로 컴파일하기 위해서는 단순히 CC := clang 라인을 추가해주면 된다. 나는 작은 테스트 프로그램을 저장할 디렉토리에 아주 작은 Makefile을 가지고 있다.
CFLAGS := -Wall -Wextra -pedantic -std=c11
CXXFLAGS := -Wall -Wextra -pedantic -std=c++11

와일드 카드와 함수

현재 디렉토리의 모든 C와 C++ 소스 파일을 컴파일하려면 종속성을 위해 다음의 코드를 사용하자.

$(patsubst %.cpp,%.o,$(wildcard *.cpp)) $(patsubst %.c,%.o,$(wildcard *.c))
wildcard는 패턴과 일치하는 모든 파일을 검색하고, patsubst는 적절한 파일 확장자를 .o로 대체한다.

Make는 텍스트를 변환하기 위한 많은 기능이 있으며, $(function arguments) 형식으로 호출한다.

함수의 전체 목록은 설명서를 참조하시라.

쉼표 뒤의 공백은 인수의 일부로 간주되는 점에 주의하자. 공간이 있으면 몇몇 함수에서 예기치 않은 결과가 발생할 수 있기 때문에 나는 쉼표 뒤에 공간을 전혀 두지 않는 것을 추천한다.

call 함수와 사용자 정의 함수, 그리고 eval 함수에서 매개 변수화된 템플릿과 같은 것을 쓸 수도 있다.

검색 경로

Make는 특별한 변수 VPATH가 모든 필요 조건을 위한 PATH처럼 사용된다. 또한 VPATH 변수는 디렉토리 이름을 콜론이나 공백으로 구분한다. 디렉토리의 순서는 Make가 검색하는 순서이다. 이 룰은 모든 파일이 현재 디렉토리에 존재하는 것처럼, 필요 조건 목록에서 파일 이름을 지정할 수 있도록 한다.

또한 세밀한 vpath 지시어도 있다. 이것은 패턴과 일치하는 파일에 대해 검색 경로를 지정할 수 있다. 따라서 include 디렉토리에 모든 헤더를 저장한다면, 다음 행처럼 사용할 수 있다.
vpath %.h include

그러나, Make는 룰의 필요 조건 부분만 바꾸지, 룰 자체를 바꾸지 않기 때문에 룰에서 명시적인 파일 이름에 의존하지 않는다. 대신 $^ 같은 자동 변수를 사용해야 한다.

필요요건에 대한 디렉토리 검색에 대한 자세한 내용은 Make 설명서를 참조하세요.

makefile의 디버깅

makefile을 디버깅하기 위한 몇 가지 방법이 있다.

Printing
첫번째는 단순히 옛날 방식의 출력 방법이다. 다음 Make 함수중 하나를 사용하여 그 표현식의 값을 출력할 수 있다.
$(info ...) $(warning ...) $(error ...)

이 라인을 통과하면 Make는 그 표현식의 값을 뿌려준다.
출력에 의한 추적 방법은 이미 알고 있을 것이다.

Remake
Makefile을 디버깅하기 위해 쓰여진 특별한 프로그램도 있다. Remake는 지정된 target에서 멈춰 일어난 것들을 확인하고 Make의 내부 상태를 바꿀 수 있다. 좀 더 자세한 내용은 Remake와 함께 makefile 디버깅에 대한 기사"를 읽어 보기 바랍니다.

makefile의 디버깅에 대한 또다른 방법을 위해서라면 makefile 디버깅에 관한 좋은 기사"도 읽어보자.
Tags : , ,