Objective-C 개발을위한 Clang 경고 플래그


86

C & Objective-C 프로그래머로서, 나는 컴파일러 경고 플래그를 가진 약간의 편집증입니다.
나는 일반적으로 내가 사용하는 컴파일러에 대한 경고 플래그의 전체 목록을 찾으려고 노력하지 말아야 할 충분한 이유가 없다면 대부분을 켜십시오.

개인적으로 이것이 코딩 기술뿐만 아니라 잠재적 코드 이식성을 향상시키고 일부 문제를 예방할 수 있다고 생각합니다. 모든 세부 사항, 잠재적 구현 및 아키텍처 문제 등을 알고 있어야합니다.

또한 숙련 된 프로그래머라도 매일 학습 도구로 사용하는 것이 좋습니다.

이 질문의 주관적인 부분으로, 나는이 주제에 관해 다른 개발자들 (주로 C, Objective-C 및 C ++)을 듣는 데 관심이 있습니다.
실제로 경고와 같은 것들에 관심이 있습니까? 그리고 예 또는 아니오라면 왜 그렇습니까?

Objective-C에 대해서는 최근 GCC 대신 LLVM 툴체인 (Clang 포함)으로 완전히 전환했습니다 .

프로덕션 코드에서 일반적 으로이 경고 플래그를 설정합니다 (명시 적으로 일부는 -Wall로 덮여있을 수 있음).

  • -벽
  • Wbad 기능 캐스트
  • 캐스트 정렬
  • -Wconversion
  • -진술 후 진술
  • 더 이상 사용되지 않는 구현
  • -엑스트라
  • 플로트 같음
  • -Wformat = 2
  • -Wformat-nonliteral
  • -4 차 문자 상수
  • 암시 적 원자 속성
  • 괄호
  • 결선 선언
  • 결산 현장 초기화 장치
  • 결측 형식 속성
  • -결손 무지
  • -방사형 프로토 타입
  • -외국인
  • -뉴 라인 eof
  • -골드 스타일 정의
  • ᆞ 길이 문자열
  • 괄호
  • -포인터 말리
  • -중복 데크
  • 화형
  • -결점
  • 그림자
  • -64에서 32로 단축
  • -비교
  • 부호 변환
  • 엄격한 프로토 타입
  • 엄격한 선택기 일치
  • 스위치
  • 스위치 기본
  • 스위치 열거 형
  • -선언 된 선택기
  • 초기화되지 않은
  • -알 수없는 pragma
  • 도달 할 수없는 코드
  • 사용하지 않는 기능
  • 사용하지 않는 라벨
  • 사용하지 않는 매개 변수
  • 사용하지 않은 가치
  • 사용 된 변수
  • 쓰기 문자열

다른 개발자들이 이것에 대해 말하는 것을 듣고 싶습니다.

예를 들어 Clang (Objective-C)에 대한 특정 플래그를 놓쳤다 고 생각하십니까?
또는 특정 플래그가 유용하지 않거나 전혀 원하지 않는다고 생각하는 이유는 무엇입니까?

편집하다

질문을 명확히하기 위해 -Wall몇 가지 기본 경고 만 제공합니다.
그들은 실제로 더 많은 경고 플래그 -Wall이므로 다루지 않으므로 질문과 내가 제공하는 목록입니다.


9
도구 사용에 대한 질문이기 때문에 이것이 아마도 스택 오버플로에 머물러 있어야한다고 말하고 싶지만 커뮤니티가 어떻게 변화하는지 볼 것입니다.
Adam Lear

의견 주셔서 감사합니다 :) 어떤 식 으로든, 나는 당신에게 동의하며, 이것이 원래 이것을 StackOverflow에 게시 한 이유입니다 (또한 일반 사용자가 아니기 때문에 부끄러워합니다). 많은 견해,
공감 율 등을 가졌습니다

글쎄, 우리가 당신에게 좋은 대답을 줄 수 있기를 바랍니다. 행운을 빕니다. :)
Adam Lear

C와 gcc -Wwrite-strings의 경우 언어를 매우 유사하지만 정확히 C가 아닌 컴파일러로 만듭니다. 그 이유만으로도 해당 옵션을 사용하지 않습니다. 당신이, 내가 사용 지정한 것보다 기타 -pedantic -Wstrict-overflow=5 -Winline -Wundef -Wcast-qual -Wlogical-op -Wstrict-aliasing=2-Wno-missing-braces -Wno-missing-field-initializers완벽하게 합리적인 초기화에 대한 struct whatever obj = {0};. 또한 -Wconversion유용한 경고보다 더 많은 "스팸" 을 제공 한다는 것을 알았습니다. :)
pmg

답변:


158

문맥 상, 저는 Google에서 일하는 Clang 개발자입니다. Google에서는 Clang의 진단 기능을 모든 C ++ 개발자에게 제공했으며 Clang의 경고도 오류로 취급합니다. Clang 개발자와 Clang 진단의 더 큰 사용자 중 하나로서 나는이 플래그들과 그것들이 어떻게 사용될 수 있는지에 대해 밝힐 것이다. 내가 설명하는 모든 것은 Clang에 일반적으로 적용되며 C, C ++ 또는 Objective-C에만 해당되지 않습니다.

TL; DR 버전 : 사용하십시오 -Wall-Werror개발중인 새로운 코드에 대한 최소한. 우리 (컴파일러 개발자)는 여기에 좋은 이유로 경고를 추가합니다 : 버그를 찾습니다. 버그를 잡는 경고를 발견하면 켜십시오. 보십시오 -Wextra여기 좋은 후보의 무리에 대해. 그중 하나가 너무 시끄럽게 사용하기에 너무 시끄럽다 면 버그를 신고하십시오 . "명백한"버그가 포함 된 코드를 작성했지만 컴파일러가 경고하지 않은 경우 버그를 신고하십시오.

이제 긴 버전입니다. 먼저 경고 플래그 그룹화에 대한 배경 지식이 있습니다. Clang에는 많은 경고 그룹이 있으며 GCC에는 제한이 있습니다. 이 토론과 관련된 일부 :

  • 기본적으로 :이 경고는 명시 적으로 비활성화하지 않으면 항상 켜져 있습니다.
  • -Wall: 다음은 개발자가 경고이며 높은 가치와 낮은 위양성률 모두에 대한 신뢰를.
  • -Wextra: 이것은 귀중하고 건전한 것으로 여겨지는 경고입니다 (즉, 버그가 없음).
  • -Weverything: 말 그대로 Clang의 모든 경고를 활성화하는 미친 그룹입니다 . 코드에서 이것을 사용하지 마십시오. Clang 개발자를 위해 또는 어떤 경고가 있는지 탐색하기위한 입니다.

위에서 언급 한 두 가지 주요 기준은 Clang에서 경고가 발생하는 위치를 안내하고 이것이 실제로 무엇을 의미하는지 명확히하겠습니다. 첫 번째는 특정 경고 발생의 잠재적 인 입니다. 이는 경고가 발생하고 코드 문제를 올바르게 식별 할 때 사용자 (개발자)에게 기대되는 이점 입니다.

두 번째 기준은 위양성 보고서에 대한 아이디어입니다 . 이러한 상황은 코드에서 경고가 발생하지만 실제로 발생할 수있는 문제는 상황이나 프로그램의 다른 제약 조건으로 인해 발생하지 않습니다. 경고 코드는 실제로 올바르게 작동합니다. 경고는 해당 코드 패턴에서 경고를 발생시키지 않았을 때 특히 나쁩니다. 대신, 경고 구현에 결함이있어 경고를 발생시킵니다.

Clang 경고의 경우 은 스타일, 취향 또는 코딩 규칙이 아닌 정확성 측면에 있어야합니다 . 이것은 문장 {}의 본문 주위에서 s를 사용하지 않을 때마다 경고와 같이 자주 요청되는 경고를 제외하고 사용 가능한 경고 세트를 제한합니다 if. Clang은 또한 위양성에 매우 관대 합니다. 대부분의 다른 컴파일러와 달리, 구성의 정확한 철자, 추가 '()', 캐스트 또는 전 처리기 매크로의 존재 또는 부재를 포함하여 잘못된 정보를 제거하기 위해 엄청나게 다양한 정보 소스를 사용합니다!

이제 Clang의 실제 예제 경고를 살펴보고 어떻게 분류되는지 살펴 보겠습니다. 먼저 기본 경고 :

% nl x.cc
     1  class C { const int x; };

% clang -fsyntax-only x.cc
x.cc:1:7: warning: class 'C' does not declare any constructor to initialize its non-modifiable members
class C { const int x; };
      ^
x.cc:1:21: note: const member 'x' will never be initialized
class C { const int x; };
                    ^
1 warning generated.

이 경고를 표시하는 데 플래그가 필요하지 않았습니다. 근거는이 코드가 경고 높은주는 정말 올바른 결코 있다는 것이다 값을 , 그리고 경고 연타가 그것을 제로주고,이 버킷에 폭포를 증명할 수있는 코드 만 화재 위양성 비율.

% nl x2.cc
     1  int f(int x_) {
     2    int x = x;
     3    return x;
     4  }

% clang -fsyntax-only -Wall x2.cc
x2.cc:2:11: warning: variable 'x' is uninitialized when used within its own initialization [-Wuninitialized]
  int x = x;
      ~   ^
1 warning generated.

Clang에는 -Wall이 경고에 대한 플래그 가 필요합니다 . 그 이유는 의도 하지 않은 값 을 의도적으로 생성하기 위해 경고하는 코드 패턴을 사용하는 사소한 양의 코드가 있기 때문입니다 . 철학적으로, 나는 이것에 아무런 의미가 없지만 많은 사람들이 동의하지 않으며이 의견의 차이의 현실은 -Wall깃발 아래 경고를 일으키는 것입니다. 여전히 가치가 높고 오 탐지율이 낮지 만 일부 코드베이스에서는 스타터가 아닙니다.

% nl x3.cc
     1  void g(int x);
     2  void f(int arr[], unsigned int size) {
     3    for (int i = 0; i < size; ++i)
     4      g(arr[i]);
     5  }

% clang -fsyntax-only -Wextra x3.cc
x3.cc:3:21: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare]
  for (int i = 0; i < size; ++i)
                  ~ ^ ~~~~
1 warning generated.

이 경고에는 -Wextra플래그 가 필요합니다 . 일치하지 않는 사인온 비교가 매우 일반적인 코드베이스 가 매우 크기 때문입니다 . 이 경고는 몇 가지 버그를 발견하지만 사용자가 작성할 때 코드가 버그 일 확률은 평균적으로 매우 낮습니다. 결과는 매우 높은 오 탐지율 입니다. 그러나 이상한 승격 규칙으로 인해 프로그램 에 버그있는 경우 버그 가 상대적으로 높은 값을 표시 때이 경고를 만드는 것은 매우 미묘 합니다 . 결과적으로 Clang은이를 제공하고이를 플래그 아래에 노출시킵니다.

일반적으로 경고는 -Wextra깃발 밖에서 오래 살지 않습니다 . Clang은 정기적으로 사용하고 테스트하지 않는 경고를 구현하지 않으려 고 노력합니다. 추가 경고 -Weverything는 일반적으로 활성 개발 중이거나 활성 버그가있는 경고입니다. 그것들은 고정되어 적절한 깃발 아래에 놓이거나 제거되어야합니다.

이제 Clang에서 이러한 기능이 어떻게 작동하는지 이해 했으므로 원래 질문으로 돌아가 보겠습니다. 개발시 어떤 경고를 설정해야합니까? 불행히도 그 대답은 달려 있습니다. 상황에 가장 적합한 경고를 결정하려면 다음 질문을 고려하십시오.

  • 모든 코드를 제어 할 수 있습니까, 아니면 외부 코드입니까?
  • 당신의 목표는 무엇입니까? 버그 잡기 또는 더 나은 코드 작성?
  • 당신의 위양성은 무엇입니까? 정기적으로 경고를 끄는 추가 코드를 작성 하시겠습니까?

우선, 코드를 제어하지 않으면 추가 경고를 설정하지 마십시오. 전원을 끌 준비를하십시오. 세계에는 잘못된 코드가 많이 있으며 모든 코드를 수정하지 못할 수도 있습니다. 괜찮습니다. 코드에 노력 집중하는 방법을 찾는 작업 제어합니다.

다음으로, 경고에서 원하는 것을 파악하십시오. 이것은 사람들마다 다릅니다. Clang은 엄청나게 많은 버그 나 버그 패턴이 매우 높다는 것을 나타내는 과거의 선례가 지난 코드 패턴에 대한 옵션없이 경고를 시도 할 것입니다. 가능하면 -Wall당신은 연타 개발자들이 C ++ 코드에서 관찰 한 가장 일반적인 실수를 잡기를 대상으로 경고 훨씬 더 공격적인 세트를받을거야. 그러나이 두 가지 모두에 대해 위양성 비율은 상당히 낮아야합니다.

마지막으로, 매 턴마다 가양 성 (false-positive) 을 완전히 침묵 시키려고한다면 가십시오 -Wextra. 실제 버그가 많이 발생하지만 어리 석거나 무의미한 오 탐지가있는 경고가 표시되면 버그를 신고하십시오. 우리는 지속적으로 더 버그-찾는 로직을 더 가져다에서 제시하는 방법을 찾기 위해 노력하고 있습니다 -Wextra-Wall우리는 가양를 피할 수있는 곳입니다.

많은 사람들이 이러한 옵션 중 어느 것도 그들에게 딱 맞는 것은 아니라는 것을 알게 될 것입니다. Google -Wall은 경고를 위반 한 기존 코드가 많아 경고를 표시하지 않았습니다. 또한 Google -Wall에서 특히 높은 가치를 지니고 있기 때문에에 의해 활성화되지 않은 경우에도 명시 적으로 일부 경고를 설정했습니다 . 마일리지는 다를 수 있지만 비슷한 방식으로 다를 수 있습니다. 모든 것보다는 몇 가지 주요 경고를 활성화하는 것이 종종 더 나을 수 있습니다 -Wextra.

모든 사람-Wall기존 코드가 아닌 코드를 사용 하도록 권장 합니다. 새 코드의 경우 경고는 거의 항상 가치가 있으며 실제로 코드 개발 경험을 향상시킵니다. 반대로, 나는 모든 사람들이를 넘어서는 플래그를 사용 하지 않도록 권장합니다 -Wextra. 당신이 연타 경고 찾아내는 경우에 -Wextra 포함되지 않지만 증명하는 모든 가치있는 당신을 단순히 버그를 제출하고 우리는 가능성이 아래를 넣을 수 있습니다 -Wextra. 경고의 일부 하위 집합을 명시 적으로 활성화할지 여부 -Wextra는 코드, 코딩 스타일 및이 목록을 유지 관리하는 것이로 밝혀진 모든 항목을 수정하는 것보다 쉬운 지 여부에 크게 좌우됩니다 -Wextra.

OP의 경고 목록 ( -Wall및 모두 포함 -Wextra)에서 다음 경고 만 해당 두 그룹에서 다루지 않습니다 (또는 기본적으로 켜져 있음). 첫 번째 그룹은 강조하는 이유 이상 의존 나쁜 될 수 있습니다 명시 적 경고 플래그에 : 이들 중 어느 것도도 있습니다 구현되지 연타에! GCC 호환성을 위해서만 명령 행에 허용됩니다.

  • -Wbad-function-cast
  • -Wdeclaration-after-statement
  • -Wmissing-format-attribute
  • -Wmissing-noreturn
  • -Wnested-externs
  • -Wnewline-eof
  • -Wold-style-definition
  • -Wredundant-decls
  • -Wsequence-point
  • -Wstrict-prototypes
  • -Wswitch-default

원래 목록에서 불필요한 경고의 다음 버킷은 해당 목록의 다른 경고와 중복되는 경고입니다.

  • -Wformat-nonliteral -서브셋 -Wformat=2
  • -Wshorten-64-to-32 -서브셋 -Wconversion
  • -Wsign-conversion -서브셋 -Wconversion

범주별로 다른 경고도 선택할 수 있습니다. 이들은 버그가 있거나 버그가없는 코드가 아닌 언어 방언 변형을 처리합니다. 를 제외 -Wwrite-strings하고 Clang에서 제공하는 언어 확장에 대한 경고입니다. Clang이 사용에 대해 경고하는지 여부는 확장의 보급에 따라 다릅니다. Clang은 GCC 호환성을 목표로하므로 많은 경우 암시 적 언어 확장을 통해이를 쉽게 사용할 수 있습니다. -Wwrite-strings는 OP에 대해 언급 한 바와 같이 실제로 프로그램 의미를 변경하는 GCC의 호환성 플래그입니다. 나는이 깃발을 깊이 후회하지만, 우리는 지금 가지고있는 유산 때문에 그것을지지해야합니다.

  • -Wfour-char-constants
  • -Wpointer-arith
  • -Wwrite-strings

실제로 잠재적으로 흥미로운 경고를 활성화하는 나머지 옵션은 다음과 같습니다.

  • -Wcast-align
  • -Wconversion
  • -Wfloat-equal
  • -Wformat=2
  • -Wimplicit-atomic-properties
  • -Wmissing-declarations
  • -Wmissing-prototypes
  • -Woverlength-strings
  • -Wshadow
  • -Wstrict-selector-match
  • -Wundeclared-selector
  • -Wunreachable-code

이들에없는 이유 -Wall또는 -Wextra항상 명확하지 않다. 이들 중 많은, 그들은 실제로 GCC 경고 (을 기반으로 -Wconversion, -Wshadow등)와 같은 연타는 GCC의 동작을 모방하려고한다. 우리는이 중 일부를 서서히 세밀하고 유용한 경고로 세분화하고 있습니다. 그런 다음 최상위 경고 그룹 중 하나로 만들 확률이 높습니다. 즉, 하나의 경고를 선택하는 -Wconversion것이 너무 광범위하여 예측 가능한 미래를위한 자체 "최상위"범주로 남아있을 것입니다. GCC는 가지고 있지만 몇 가지 다른 경고는 낮은 값이 높은 위양성 비율이 비슷한 더 살지 않는 땅으로 강등 할 수있다.

이것들이 더 큰 버킷 중 하나에없는 다른 이유는 간단한 버그, 매우 심각한 오 탐지 문제 및 개발 중 경고를 포함합니다. 식별 할 수있는 버그에 대한 버그를 조사하겠습니다. 결국 모두 적절한 대형 버킷 플래그로 마이그레이션하거나 Clang에서 제거해야합니다.

이것이 Clang의 경고 상황을 분명히하고 사용 또는 회사 사용에 대한 경고 세트를 선택하려는 사람들에게 통찰력을 제공하기를 바랍니다.


8
탁월한 답변! 고마워 몇 번 다시 읽어야하지만 몇 가지 의견이 곧 다시 올 것입니다. 다시 감사합니다!
Macmade

1
@ 챈들러 Carruth : 좋은 대답! 그러나 변경된 것이 있다면 업데이트 할 수 있습니까? 마지막 목록에서 모든 경고를 사용하고 있지만 일부는 이미 Wextra로 옮겨 졌습니까?
gartenriese

이것은 훌륭한 게시물입니다. 그러나 새로운 경고를 찾는 것은 깃발을 매우 잘 사용한다는 것입니다. 따라서 이런 종류의 탐색에 유용하다는 것을 인정하면서도 "모든 것"그룹에 대해 부정적인 태도를 보이는 것으로 실망합니다.
Kyle Strand

@Chandler Carruth : "정확하지 않은"코드에 대한 경고의 근거에 동의합니다. 더이없는 단지하다는 -Wno오프 전환하는 것은 warn_no_constructor_for_refconst : 그것은 피타 Boost.ConceptCheck와 비슷하게 사용할 수있게 github.com/boostorg/concept_check/blob/...
mloskot

2

Clang을 사용하지는 않지만 내 의견도 마음에 들지 않기를 바랍니다. 또한 최대 경고 수준 (저는 -Wall이 의미하는 것으로 가정)과 경고를 오류로 처리 (-Werror가 의미하는 것으로 가정)로 진행하며 이해가되지 않는 몇 가지 경고 만 비활성화합니다. 실제로, C # 컴파일러가 매우 유용한 특정 경고를 발행하지 않으며 특수 코드 분석 도구를 실행하여 경고를보아야한다는 사실에 상당히 짜증이납니다. 내 코드에서 작은 실수와 버그를 잡는 데 도움이되기 때문에 경고를 좋아합니다. 내가 좋아하는 코드에 대해 경고가 발행되면 어쨌든 해당 코드를 리팩터링하여 경고를 비활성화하지 않고 경고가 발행되지 않도록합니다. 더 나쁘다. 그것을 드러내고 무시한다. 경고가 훌륭하다고 생각합니다.


1
답변 해주셔서 감사합니다. 불행히도 -Wall기본 경고 만 제공합니다. 기존 경고 플래그가 많이 포함되어 있지 -Wall않으므로 내 질문에있는 목록입니다.
Macmade

0

나는 보통 새 프로젝트에 대한 Xcode의 기본 설정을 사용합니다. 도움과 성가신의 균형이 잘 맞습니다. 특정 경고 목록 및 기타 컴파일러 옵션은 주로 개인 취향 또는 프로젝트 요구 사항을 기반으로하므로 목록을 살펴보고 특정 경고를 주장하거나 반대하는 데 많은 가치가 있다고 생각하지 않습니다. 그것이 당신을 위해 작동한다면, 좋습니다. 컴파일러가 감지 할 수 있어야한다는 오류가 있고 나중에 도움이 필요한 경우 경고를 표시하고 켜는 컴파일러 옵션을 찾으십시오.

많은 프로그래머가 옹호하는 것 중 하나는 "경고로 경고 처리"(-오류) 옵션을 켜서 경고가있는 경우 빌드가 성공적으로 완료되지 못하게하는 것입니다.


답변 해주셔서 감사합니다! 에 동의합니다 -Werror. 내가 연타를 사용하고 같은 사실, 나는 (진단의 #pragma 연타) 프라그 마를 사용하여 모든 경고를 설정하고, 그들은 치명적인 오류로 설정되어 있으므로이 같은입니다 -Werror:)
Macmade

0

사람들이 경고에 관심을 갖는 가장 좋은 증거는 경고가 존재하고 널리 사용된다는 사실입니다. 컴파일 시간 동안 더 많은 오류가 발생하면 클수록 좋습니다. 이것이 널리 알려진 믿음이 아니라면, 컴파일러 나 인터프리터가 당신에게 더 많은 여지를 제공하기 때문에 모두가 약한 동적 타입 언어를 사용하고있을 것입니다. 반대로, 스크립팅 언어에서도 strict플래그 사용 이 인기가 있습니다. 정적 형식의 언어에서는 사람들이 -Wall -Werror자주 사용 하는 것뿐만 아니라 경고가 너무 중요하여 더 많은 것을 원 하기 때문에 Coverity 와 같은 정적 분석 도구에 대해서만 비용을 지불합니다 .

그렇다고해서 낙담자가 없다는 뜻은 아닙니다. 많은 개발자들이 장기적으로 경고하기보다는 경고가 단기적으로 경고하는 것으로보고 근본적인 문제를 해결하려고하지 않습니다. 따라서 어제 발견 한이 발췌 문장과 같은 멋진 코드를 볼 수 있습니다.

node = node; // Shut up compiler warning

답변 주셔서 감사합니다. 문제는 종종 사람들이없이 작업 -Werror하고 컴파일러가 발행 한 경고를 무시한다는 것을 알았습니다 . 또는 그들이하는 경우에, 그들은 단지에 붙어 -Wall있습니다. 내 질문에 제공하는 대부분의 플래그는에 포함되지 않으며 -Wall개인적으로도 플래그 가 필수적이라고 생각합니다. 내가 편집증인가요? ; )
Macmade

0

일반적으로 나는 -Wall쪽으로 더 기울어지고 -Werror도 포함한다고 확신합니다. 모듈은 경고를 기 대해서는 안됩니다 . 결국 다른 경고를 받고 놓칠 수 있습니다. 그리고 그것은 실제로 문제가 될 것입니다.

또한 새 프로젝트 또는 이전 프로젝트에 "-Wall -Werror"를 추가하는지 여부에 따라 다릅니다. 새로운 것이면 계속 진행하고 완벽을 요구하십시오. 그렇지 않으면 며칠 또는 몇 주 동안 편집 및 테스트를 할 것입니다. 방금 오래된 작은 프로젝트 에서이 작업을 수행했으며 경고를 제거하는 데 2-3 일을 보냈습니다. 코드가 더 깨끗하다고 ​​생각합니다.

다시 말해 시도해보십시오.

랜디


1
-Wall와 님 만 걱정하는 -Werror경우 질문을 다시 읽어야합니다. 많은 경고 플래그는 적용되지 않습니다 -Wall. 어쨌든 대답 주셔서 감사합니다.
Macmade
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.