IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  자바  >

사람을 위한 자동화: 지속적인 통합 안티 패턴, Part 2

무엇을 하지 말아야 하는지를 통해 개발자의 삶을 CI로 더 쉽게 만들자

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

영어원문

영어원문


제안 및 의견
피드백

난이도 : 초급

Paul Duvall, CTO, Stelligent Incorporated

옮긴이: 백기선 dwkorea@kr.ibm.com

2008 년 5 월 13 일

지속적인 통합(Continuous Integration, CI)이 프로젝트의 위험을 낮추는 데 매우 효율적일 수 있지만, 여러분이 매일 하는 코딩 활동에 심대한 관심을 필요로 합니다. 이번 CI 안티 패턴에 대한 두 번째 기사를 통해 자동화 전문가이자 Continuous Integration: Improving Software Quality and Reducing Risk 의 공동 저자 Paul Duvall은 CI 안티 패턴과 그보다 더 중요한, 그것들을 피하는 방법에 대해 설명합니다.

두 부분으로 나눈 본 기사의 첫 번째 기사에서는, 다음 여섯 가지 CI 안티 패턴에 대해 설명했다.

  • 아주 가끔 체크인하기. 통합을 지연시킨다.
  • 깨진 빌드. 팀 전체가 다른 작업을 하지 못하게 만든다.
  • 피드백 하지 않기. 일이 발생했을 때 대응하지 못한다.
  • 스팸 피드백 받기. 사람들이 메시지를 무시하게 된다.
  • 느려터진 기계에서 작업하기. 피드백을 지연시킨다.
  • 비대한 빌드 사용하기. 역시 피드백을 지연시킨다.
이 연재에 대하여
우리는 개발자로서 사용자들의 일을 자동화하기 위해 노력한다. 하지만 대다수의 개발자가 자신의 개발 공정을 자동화하는 것은 간과해 버린다. 그런 일이 더이상 발생하지 않도록, " 사람을 위한 자동화 " 연재를 통해 소프트웨어 개발 공정을 자동하는 실용적인 방법과 언제 어떻게 자동화를 성공적으로 적용할 수 있는지에 대해 살펴볼 것이다.

이런 안티 패턴들은 CI로 경험할 수 있는 장점들을 못보도록 방해하거나 지연시킨다. 두 번째 부분에서는 좀 더 기만적인 행동들에 대해 살펴보겠다.

  • 하루가 끝나기를 기다렸다가 커밋하기. 커밋에 병목 현상(bottleneck Commit)을 일으킨다. 보통 빌드는 깨지고 개발자는 좌절한다.

  • 자동화 프로세스가 최소로 구성되어 있는 빌드. 절대로 실패하지 않는 빌드가 되지만 지속적인 무지(Continuous Ignorance)와 통합 지연 문제를 야기한다.

  • 코드가 바뀔 때마다 자주 빌드하기보다는 일정에 따른 빌드(Scheduled Builds)를 선호해 빌드 문제점 수정을 지체시킨다.

  • 내 머신에서 돌아간다고 코드에 문제가 없다고 믿으면, 다른 환경에서 생기는 문제를 뒤늦게 발견할 수밖에 없다.

  • 오래된 빌드 구성물들을 제거하지 않으면, 오염된 환경(Polluted Environment)이 되며 이는 다시 양성 오류와 음성 오류를 야기한다.

다시 한 번 강조하자면 CI의 여러 장점을 살리려면 이러한 안티 패턴을 이해하고 그것들을 피해야 한다.

숨막히는 병목 커밋 멈추기

이름: 병목 커밋

안티 패턴: 개발자들이 코드 변경 사항을 일과를 끝내기 직전에 한번에 커밋한다. 이것으로 인해 통합 빌드가 깨지면 모든 팀원이 늦게까지 집에 못 갈지도 모른다.

해결책: 일과 중에 자주 커밋하라.

통합 빌드는 무엇인가?
통합 빌드는 개발자의 컴퓨터가 아닌, 별도의 컴퓨터의 버전 관리 저장소로부터 소스 코드를 받아 실행하는 빌드 종류를 말한다.

병목 커밋은 드물게 커밋하기(Influent Check-in)라는 안티 패턴의 변종이다. 이것은 하루에 적어도 한 번은 커밋을 한다고 가정하고 있다. 하지만 문제는 모든 사람이 같은 시간에 커밋한다는 것이다. Slave Imeshev는 CM Crossroads 기사를 통해 어떻게 대부분의 빌드 실패가 오후 5시에서 오후 8시 사이에 발생하는지 (그리고 점심 시간에는 적게 발생하는지) 설명했다. "Five-O'Clock Check-In"에서 Imeshev는 이런 현상을 개발자들이 자신의 코드 변경 사항을 일과가 끝나기 직전에 커밋하는 경향 때문이라고 밝혔다.(참고자료 참조)

다섯시 즈음

다섯시 체크인(Five-O'Clock Check-in)은 만약 여러분의 팀이 커밋된 모든 변경 사항과 빌드가 실행되지 않는 상태에서는 집에 가지 않는다는 규칙을 지키고 있다면, 동료로부터 버림받는 지름길이다. 자, 빌드가 실패했을 때를 상상해보자. 나는 집에다 전화를 해서 오늘은 왜 또 늦게 들어가야먄 하는지 설명하는 모습을 상상했다.

그림 1은 소프트웨어 개발 팀의 일반적인 체크인 시간대를 보여준다. 저장소에 커밋하는 일들이 점심 전후와 일과가 끝나기 직전에 몰려있는 것을 주의깊게 살펴보자.


그림 1. 병목 커밋
병목 커밋을 보여주는 타임라인

물론 이 골칫거리에 대한 해결책은 변경 사항들을 자주! 커밋하는 것이다. 이런 접근 방법으로, 더 작은 단위로 더 자주 통합 빌드를 실행하게 될 것이고 빌드 에러가 발생하더라도 작은 문제이기 때문에 훨씬 고치기 쉬울 것이다.

다섯 시라는 말이 함축하는 의미는 좋은 것이어야 한다. 그러므로 코드를 자주 체크인해 다섯 시를 행복한 시간으로 유지하라.




위로


무지는 행복이 아니다.

이름: 지속적인 무지

안티 패턴: 빌드가 성공하면, 모든 사람이 최종 소프트웨어가 제대로 동작할 것이라고 예상한다. 실제로 빌드는 컴파일과 몇 개 안 되는 단위 테스트들로만 구성되어 있는데도 말이다.

해결책: 전체 통합 빌드를 버전 관리 저장소에 변경이 생길 때마다 실행한다.

때때로 팀은 하나씩 추가되는 성공적인 빌드로 인해 잘못된 상황에 대해 점차 무뎌지게 된다. 사실 빌드 실패가 거의 일어나지 않는다는 건 여러분의 팀이 지속적 무지라는 안티 패턴을 적용하고 있음을 알려주는 거의 확실한 조짐이다. 만약 통합 빌드가 절대로 실패하지 않는다면, 여러분은 자신의 코드를 충분히 검사하고 검증하지 않는 것일지도 모른다! 여러분의 빌드가 하는 일이 적어질수록, 여러분의 소프트웨어가 실제 제대로 동작할지 예측할 수 있는 정보도 점차 줄어들 것이다.

테스트 무지
지속적인 무지 안티 패턴의 한 종류로 깨진 테스트를 소스 코드를 수정하여 해결하지 않고 주석 처리하여 빌드를 성공시킴으로 인해 발생한다. 비록 이런 방법으로 성공적인 통합 테스트를 할 수는 있지만 나중에 더 큰 문제를 일으켜 일이 지연되는 원인이 된다.

충분한 빌드는 깨달음을 준다.

그림 2 왼쪽에 있는 스택은 소스 코드 컴파일, 클래스를 바이너리로 패키징하기, 소프트웨어를 운영 환경에 배포하기 외에는 별다른 것을 하지 않는 빌드를 보여준다. 물론 통합 빌드를 전혀 하지 않는 것보다는 좋다. 하지만 오른쪽에 있는 스택을 보자. 두 스택을 비교해보면, 오른쪽에 기술했듯이 테스트와 데이터베이스 변경 같은 추가적인 절차를 통해 문제들을 발견할 수 있다는 알 수 있다.


그림 2. 충분한 빌드는 우리의 친구다.
충분한 빌드는 문제들의 통찰력을 제공한다

여러분의 빌드를 연결하라.

데이터베이스 통합, 개발자 테스트(단위, 컴포넌트, 기능, 기타 등등), 자동 코드 검사(코딩 표준 적합성, cyclomatic 복잡도, 코드 중복 확인과 같은 것들), 그리고 설치와 같은 절차를 추가함으로써, 여러분의 소프트웨어가 실제로 동작 가능한지 개발 과정 초기에 알 수 있다. 하지만 통합 빌드에 무언가를 많이 추가할수록 피드백이 느려진다는 것을 명심해야 한다. 따라서 기초적인 빌드를 마친 뒤에 시간이 오래 걸리는 빌드를 수행하도록 연결관을 만들고 싶어질 것이다. 그렇게 함으로써 더 빠른 피드백을 얻을 수 있고 소프트웨어 검증 작업을 더 유연하게 수행할 수 있다.




위로


정기적인 빌드 일정을 수정하라.

이름: 정기적인 빌드

안티 패턴: 빌드는 매일, 매주 또는 다른 스케쥴에 의해 실행하지, 모든 변경 사항에 대해 실행하지 않는다.

해결책: 빌드를 소스 코드 저장소에 반영된 모든 변경 사항에 대해 실행한다.

지속적인 통합은 소프트웨어 자원을 자주 통합하는 것에 대한 것이다. 그리고 이때 '자주'는 모든 코드 변경 사항을 뜻한다. 이것이 내가 현재까지 알고 있는 가장 빠르게 조기에 이슈를 찾아내는 방법이다. 이슈를 조기에 발견하는 것은 좋은 일이다. 일단, 여러분의 돈을 절약할 수 있다. 다음으로, 더 자주 좋은 코드를 양산할 수 있는 능력을 길러준다.

정기적인 빌드가 가지고 있는 문제는 여러분이 저장소에 변경 사항을 반영했는지 안 했는지에 상관없이 빌드가 동작한다는 것이다. 이것은 아무 가치가 없는 빌드를 수행할 수도 있다는 것을 의미한다. 마지막 빌드 이후에 아무런 변경이 없었을 수도 있기 때문이다. 또한 너무 많은 변경이 있은 뒤에 빌드가 동작하고 문제가 발생하면 해당 문제를 해결하기가 어려워진다.

CI를 효율적으로 수행하려면 적극적인 자세가 필요하다. 빌드가 실패하면, 그 즉시 문제를 해결해야만 한다. 정기적인 빌드의 특성상 이러한 적극적인 대처를 힘들게 하고 "할 수 있을 때 하지 뭐"라는 경향으로 이끌어 간다. 이것은 CI의 정반대 방향이다.

정기적인 빌드를 더 효율적으로 바꾸는 방법은 CI 서버를 설정하는 것만큼이나 간단하다. 예를 들어, Listing 1은 버전 관리 저장소를 2분마다 확인하는 CruiseControl 스크립트를 보여준다. 변경 사항을 발견하면, CruiseControl은 빌드를 실행한다.


Listing 1. 모든 변경 사항에 대해 빌드하기
  ...
  <schedule interval="120">
    <ant anthome="${cc.ant.dir}" buildfile="build-${project.name}.xml"/>
  </schedule>
  ...

내가 틀렸다고 하지 않길 바란다. 정기적으로 수행하는 빌드도 특정 상황에서 유용할 수가 있다. 예를 들어, 로드 테스트와 성능 테스트는 빌드 작업 시간이 길어 매일 밤에 수행할 수 있다. 하지만 일반적으로는, 모든 변경 사항에 대해 빌드하지 않고 드문 드문 빌드하는 것은 문제를 조기에 발견할 수 있는 기회를 져버리는 것이다.




위로


엇, 내 컴퓨터에서는 돌아가는데!

이름: 내 컴퓨터에서는 동작함

안티 패턴: 개별적인 빌드를 개인 컴퓨터에서 돌리고, 다른 환경에서는 동작하지 않는 변경 사항들을 나중에서야 발견하게 된다.

해결책: 팅에서 통합 빌드 컴퓨터를 사용하여 버전 관리 저장소에 반영된 모든 변경 사항에 대해 하나의 동일한 빌드를 수행한다.

상상해보자. 여러분은 코드를 변경하고 여러분의 빌드를 (IDE나 Ant를 사용하여) 실행했다. 그리고 그 결과 모든 것이 잘 동작했고 버전 관리 저장소에 변경 사항들을 반영했다. 며칠이 지나 누군가 그 코드를 다른 환경에 배포해보고 여러분에게 해당 코드가 제대로 동작하지 않는다고 알려주었다. 여러분은 소프트웨어 애플리케이션을 여러분의 컴퓨터에서 실행하고, 어떻게 되나 볼 것이다. 모든 것이 여러분의 주장대로 잘 동작할 것이다. "엇, 내 컴퓨터에서는 잘 돌아가는데!"라면서 말이다.

이런 일이 발생한 적이 있었나? 아직 그런 일이 없었다면, 준비해두는 것이 좋다. 언젠간 발생할 일이다. 이런 이상한 상황이 발생하는 원인은 여러 가지가 있지만, 보통 그 원인은 여러분이 새로 추가된 파일을 버전 관리 저장소에 올리는 것을 깜빡했거나 여러분의 컴퓨터에는 특정 설정이 되어 있지만, 다른 환경에는 설정되어 있지 않기 때문이다.

여러분의 데스크톱 밖에 있는 세상

이름: IDE에서만 빌드

안티 패턴: 자신만의 빌드를 IDE(로컬에서 동작하는)를 사용하여 다른 환경에서 발생하는 문제를 발견하고자 한다.

해결책: 빌드 스크립트를 만들고 그것을 버전 관리 저장소에 커밋한다. 이 하나의 같은 빌드 스크립트를 모든 변경 사항에 대해 실행한다.

IDE를 사용하여 코드를 작성하고 빌드 스크립트를 만드는 것에 대해서는 아무런 문제도 없다. IDE들은 여러분이 일을 더 효율적으로 할 수 있도록 도와준다. 하지만 만약 빌드 과정이 지나치게 IDE와 묶여서 여러분이 개발 환경에 IDE가 설치되어 있어야지만 통합 빌드를 실행할 수 있다는 것은 문제라고 할 수 있다. 운영 팀이 통합(staging) 또는 생산(production) 환경에 IDE를 설치하지는 않기 때문이다. 만약 꼭 그렇게 해야 한다면, 통합 빌드를 실행하기 위한 IDE 설정 매뉴얼(이로 인해 여러 환경에서의 불일치와 빌드 에러를 야기할 수 있다)이 필요하다. 거기에 더해, IDE에 종속적인 빌드는 설정 문제 발견을 통합 환경과 생산 환경에서 그 의존성을 때어내는 개발 과정까지 늦춰질 것이다.

IDE에서만 빌드되는 문제를 해결하려면, 빌드 스크립트를 만들기만 하면 된다(IDE를 사용하여 쉽게 만들 수 있다). 이 동일한 빌드 스크립트가 나중에는 환경에 구애받지 않는 통합 빌드의 주요 메커니즘이 될 수 있다.

근시와 개발자

이름: 근시 환경

안티 패턴: 빌드가 단일 환경에서 동작하기 때문에, 다른 모든 환경에서도 동작할 것이라고 가정한다.

해결책: 빌드 타켓에 빌드 행위를 정의한다. 환경에 종속적인 데이터를 .properties 파일로 빼낸다.

근시 환경 안티 패턴은 단일 환경에서 자신의 코드가 동작하면 자신의 일이 끝났다고 생각하는 개발자의 잘못된 가정에 대한 반영이다. 따라서 이런 사고방식과 싸우려면, CI 시스템은 아무것도 가정하지 않으면 된다. 가정하기를 줄이는 방법은 플랫폼 종속적인 설정을 제거하고 그 설정들을 프로퍼티 파일을 사용하여 교체 가능하도록 만드는 것이다.

만약 빌드가 윈도우(Windows®)와 리눅스(Linux®) 두 환경 모두에서 동작해야 할 때, C 드라이브를 참조하는 설정이 있다면 리눅스에서는 빌드가 실패할 것이다. 만약 빌드가 컴퓨터 종속적인 환경 변수들(예를 들어, GLOBUS_LOCATION)을 사용한다면, 이런 환경 변수가 설정되어 있지 않은 환경에서는 빌드가 실패한다. 이런 경우, 여러분이 해야 할 일은 이런 변수들이 빌드를 실행하는 동안 교체될 수 있도록 참조값을 변수로 대체하는 것이다.

Listing 2에 있는 앤트(Ant) XML 조각은 환경 변수를 담고 있는 .properties 파일을 추가하는 방법을 보여준다.


Listing 2. 빌드 스크립트에서 환경 프로퍼티 참조하기
<property file="${basedir}/TEST.properties" />

Listing 3의 프로퍼티들은 배치 환경에 따른 특정 데이터를 보여준다. 데이터베이스 연결 값, 웹 컨테이너 위치, 호스트 이름, 인증 정보 같은 정보들을 밖으로 뺌으로써 빌드에서 가정을 줄이고 있음을 주목하라.


Listing 3. 프로퍼티 파일에 데이터 정의하기
database.host.name=integratebutton.com
database.username=myusername
database.password=mypassword
database.port=3306
jboss.home=/usr/local/jboss/server/default
jboss.temp.dir=/tmp
jboss.server.hostname=integratebutton.com
jboss.server.port=8080
jboss.server.jndi.port=1099

모든 빌드 행위는 타겟에 포한된다(앤트의 target처럼). 동일한 빌드 스크립트에서 두 번 이상 참조되는 데이터는 프로퍼티에 정의하는 것이 좋다. 서로 다른 플랫폼에 따라 달라지는 값들은 반드시 .properties 파일로 빼내야 한다. 만약 여러분이 이 간단한 조언을 따른다면, 최소한의 두통으로 최고의 유연성을 얻게 될 것이다.




위로


환경 정리하기

이름: 오염된 환경

안티 패턴: 계속해서 빌드하는 것은 시간을 절약해 준다. 하지만 (이전 빌드에서 생긴) 오래된 결과물로 인해 양성 오류(또는 음성 오류) 빌드를 야기할 수 있다.

해결책: 빌드를 실행하기 전에 이전 빌드 결과물들을 제거한다. 기준 서버와 설정 정보는 남겨둔다.

실행 전에 스스로 청소하기

실패하는 빌드를 실행하는 것보다 더 힘들게 하는 몇 가지가 있느데, 그 중 하나가 이전 빌드 결과물이 여전히 존재하기 때문에 발생하는 문제다. 그런 결과물들은 최근에 배포된 WAR 파일, 부적합한 JAR 파일 버전, 데이터베이스 수정들에 해당한다. 그 반대편에는 더 심각한 문제가 있는데, 바로 이전 빌드 결과가 계속해서 성공적인 빌드로 이끌면서 생기는 안전 불감증이다.

빌드를 실행하기 전에 여러분의 환경을 기본 상태로 돌려놓는 것이 얼마나 중요한지 아무리 강조해도 지나치지 않다. 사실, 개인적으로 소프트웨어를 빌드할 때 초토화 작전(scorched earth policy)이라고 부르는 것을 실행하길 좋아한다. Listing 4는 이전 로그 디렉터리, 파일 그리고 리포팅 파일을 앤트의 delete 태스크를 사용하여 제거하는 예제를 보여준다. 이것으로 인해 양성 오류와 음성 오류 발생 가능성을 현저하게 줄일 수 있다.


Listing 4. 앤트로 디렉터리 제거하기
<target name="clean">
  <delete dir="${logs.dir}" />    
  <delete dir="${dist.dir}" />    
  <delete dir="${reports.dir}" />    
  <delete file="cobertura.ser" />     
</target> 

위의 코드는 너무 간단하다. 환경 초토화는 오랜된 클래스 파일과 이전에 배포한 EAR/WAR 파일을 제거하고 데이터베이스를 기준 상태로 돌려놓고, 클래스 패스를 초기화하고 환경 변수 사용을 기피하는 활동을 포함한다.

개발 환경 기준선 마련하기

"초토화"는 여러분으로 하여금 통합 빌드를 수행하는 운영 환경의 상태 설정과 같은 고급 기술을 고려하도록 이끌 수도 있다. 이러한 환경에 기준선을 마련하려면, 각각의 컴포넌트와 설정 목록을 제거하고 자동화를 사용하여 재구성해야 한다. 오래된 파일을 간단하게 삭제하는 것에 비하면 환경의 복잡도에 따라 처리하기 어려운 일일 수도 있다. 하지만 점진적으로 적용할 수 있다. 컴포넌트는 데이터베이스, 웹 서버 또는 파일 서버 또는 몇몇 사적인 소프트웨어들이 될 수 있다. 설정 목록은 환경 변수 또는 데이터베이스 설정 변경, 메모리 할당과 같은 것이 될 수 있다. 일관성이 핵심이다. 여러분이 빌드를 실행하는 환경은 설정이 비슷해야 한다. 개발 환경 기준선을 마련함으로써, 특정 문제의 원인을 발견하는 데 더 최적화할 수 있다. 그림 3은 모든 개발 환경에서 비슷한 방법으로 초토화한 뒤 재적용할 필요가 있는 몇몇 컴포넌트를 보여준다.


그림 3. 개발 환경 초토화하기
개발 환경 초토화하기

내 경험상, 개발 환경 초토화를 함으로써 얻을 수 있는 가장 명백한 이점은 정말 빠르게 문제를 발견할 수 있는 방법을 제공한다는 것이다. 비슷한 환경을 위한 기준선을 마련하는 것은 여러분으로 하여금 사과와 사과를 비교할 수 있는 능력을 가져다 준다. 달리 말하자면, 여러 환경 사이에서 발생할 수 있는 문제들을 굉장히 빨리 고칠 수 있게 된다.




위로


지속적인 통합으로 성공하기

지속적인 통합이 여러분의 개발 프로젝트에 매우 훌륭한 지침이 되었기를 바란다. 그리고 몇 가지 안티 패턴만 피한다면 그 장점을 더 많이 즐길 수 있을 것이다. 개발 팀 내에서 그런 식으로 하려는 이유가 있을 수 있다. 하지만 그것들로 인해 안티 패턴 사용 증세가 나타날 수 있다. 예를 들어, 때때로 정기적인 필드가 필요한 이유가 있을 수도 있다. 또 하나, 소스 코드를 자주 커밋하는 것은 병목 현상을 발생시킬 수 있다. 하지만 자주 커밋하는 것을 나쁜 습관이라고 하지는 않는다. 기억할 것은, 안티 패턴이 나쁜 습관은 아니라는 것이다. 하지만 그것들은 특정 상황에서 나쁜 접근 방법이 될 수도 있다.



참고자료

교육

제품 및 기술 얻기
  • 앤트: 자바(Java™) 빌드를 앤트로 실행하라.


토론
  • Improve Your Code Quality discussion forum: developerWorks 기고자 Andrew Glover가 코드 품질 개선과 관련된 방대한 컨설턴트로서 경험을 이 포럼을 통해 보여준다.

  • Accelerate development space: Andrew Glover는 개발자 테스트, 지속적인 통합, 코드 메트릭 그리고 리팩터링과 관련하여 가장 먼저 들려야 할 포털을 운영하고 있다.


필자소개

Paul Duvall

Paul Duvall은 컨설팅 회사이자 개발 팀을 애자일 소프트웨어 제작에 최적화하는 데 있어 선구자적인 역할을 하는 Stelligent Incorporated의 CTO다. Paul Duvall은 Addison-Wesley Signature Series Book인 Continuous Integration: Improving Software Quality and Reducing Risk (Addison-Wesley, 2007)의 공동 저자다. 또 UML 2 Toolkit (Wiley, 2003)과 No Fluff Just Stuff Anthology (Pragmatic Programmers, 2007)에도 기여하였다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의