Tag Archives: AppStore

Apple 앱심사 14.3 리젝 사유 대응하기

애플의 앱스토어에 앱을 등록하기 위해서는 애플의 심사를 통과해야 합니다. 그리고 이 심사 규정이 해가 갈 수록 괴팍해져가는것 같습니다. 점점 애플의 앱 자체의 기획적인 부분까지 간섭하기 시작했달까요. 그중에 하나로 생각되는 특이한 리젝 사유 한가지에 대해 정리해 보겠습니다.

apple_review_reject_14.3

앱스토어 리뷰 가이드에 보면 Personal attacks 라는 항목이 있습니다. 이부분은 앱내에서 유저 개인에게 이루어지는 공격을 어떻게 대응해야 하는지에 대한 가이드라인입니다. 위의 가이드 내용만 보면 “유저가 생성한 컨텐츠를 보여주는 앱은 공격적인 컨텐츠를 차단하거나 폭력적인 행위를 하는 유저를 필터링 하는 방법을 반드시 포함해야 한다” 정도의 이미가 될 것 같네요.

실제로 리젝을 먹을 경우 다음과 같은 리젝 사유를 받게 됩니다. Detail 항목은 앱에 따라 다를 수 있습니다. Specifically 이후의 메시지를 특별하게 주목하시면 됩니다. 다음의 사례를 유저 생산 컨텐츠에 대해 차단할 수 있는 기능을 제공하지 않았다고 리젝을 받은 사례입니다.

14.3 – Apps that display user generated content must include a method for filtering objectionable material, a mechanism for users to flag offensive content, and the ability to block abusive users from the service

14.3 Details

We continue to find your app enables the display of user-generated content but does not have the required precautions in place.

Specifically, your app does not provide a blocking feature.

Next Steps

It is necessary that you put all of the following precautions in place:

– Require that users agree to terms (EULA) and these terms must make it clear that there is no tolerance for objectionable content
– Use moderators to flag and remove inappropriate content and offensive users
– Users need a mechanism to flag objectionable content and report users generating this content
– Users need a mechanism to block abusive users
– Developer must act on objectionable content reports within 24 hours by removing the content and ejecting the user who provided the offending content
– Developer needs a method for ejecting users who violate the terms of the EULA

이 문제를 해결하기 위해서 앱에 추가해야 하는 내용은 다음과 같습니다.

  • 사용자 동의 문구에 “불쾌한 컨텐츠를 허용하지 않는다”는 문구를 명확히 명시해야 한다.
  • 부적절한 컨텐츠나 공격적인 유저에 대해 표시나 삭제를 할 수 있는 어드민 같은것이 있어야 한다.
  • 사용자가 생산한 불쾌한 컨텐츠에 대해 표시하거나 신고할 수 있는 기능을 제공해야 한다.
  • 폭력적인 행위를 하는 유저를 차단할 수 있는 기능을 제공해야 한다.
  • 개발자는 신고된 불쾌한 컨텐츠에 대한 24시간 이내에 삭제해야 하고 이러한 컨텐츠를 제공한 유저를 차단해야 한다.
  • 개발자는 사용자 동의를 위한한 유저를 내쫓을 수 있는 방법을 제공해야 한다.

이 문제를 수정하기 위해서는 사용자 동의에 “다른 사용자를 불쾌하게 만들 수 있는 컨텐츠를 허용하지 않는다”라는 문구를 넣어주고 사용자가 생성하는 컨텐츠들에 대해 신고 버튼등을 넣어주어야 합니다. 유저들의 신고가 누적되면 자동 삭제되는 기능을 넣어주는것이 좋다고 생각하며 삭제가 정말로 되는지 애플 리뷰어가 끝까지 의심할 경우 Resolution Center를 통해 신고된 컨텐츠가 관리되고 있음을 증명할 수 있는 관리자 툴의 화면을 캡춰해서 보내주는것도 방법입니다.

[iOS] 앱스토어 링크 모달창으로 띄우기

내가 만든 어플리케이션에서 다른 어플리케이션의 다운로드를 유도할 때 다음과 같은 코드를 사용하여 앱스토어 다운로드뷰로 이동을 하는 경우가 있습니다.

NSString *appUrl = @"https://itunes.apple.com/kr/app/kukileon-for-kakao/id608808713";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:appUrl]];

하지만 이경우 앱간 전환하는 모션을 보여주게 되며 유저에게 부담스러운 행위로 인식될 수 있습니다. iOS 6.0 이상부터 제공 되는 SKStoreProductViewController를 이용하여 앱스토어 링크로의 이동을 모달뷰로 띄울 수 있게 되었습니다. SKStoreProductViewController를 사용하기 위해서는 StoreKit.framework의 추가가 필요합니다.

#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>

@interface ViewController : UIViewController <SKStoreProductViewControllerDelegate>

@end

헤더파일에는 StoreKit.h 파일을 임포트하고 SKStoreProductViewControllerDelegate 프로토콜을 추가해줍니다. 이 부분은 선택사항이 아니라 반드시 구현해야 하는 부분입니다.

- (IBAction)linkToAppstoreWithUrl:(id)sender {

    // 기존의 방식으로 앱스토어 이동을 위한 링크
    NSString *appUrl = @"https://itunes.apple.com/kr/app/kukileon-for-kakao/id608808713?mt=8";

    // iOS 6.0이상에서 SKStoreProductViewController를 이용하기 위한 어플리케이션 아이디
    NSString *appId = @"608808713";

    // SKStoreProductViewController를 사용할 수 있는지 여부 확인
    if(NSClassFromString(@"SKStoreProductViewController")) {

        SKStoreProductViewController *storeController = [[SKStoreProductViewController alloc] init];
        storeController.delegate = self;

        NSDictionary *productParameters = @{ SKStoreProductParameterITunesItemIdentifier : appId };

        [storeController loadProductWithParameters:productParameters completionBlock:^(BOOL result, NSError *error) {
            if (result) {
                [self presentViewController:storeController animated:YES completion:nil];
            } else {
                [[[UIAlertView alloc] initWithTitle:@"오류발생"
                                            message:@"앱스토어 링크를 여는데 오류가 발생하였습니다."
                                           delegate:nil
                                  cancelButtonTitle:@"Ok"
                                  otherButtonTitles: nil] show];
            }
        }];
    } else {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:appUrl]];
    }
}

#pragma mark SKStoreProductViewControllerDelegate

- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
    // 앱스토어 모달창에서 사용자가 취소버튼을 눌렀을 때 취할 행동 구현, 창을 닫습니다.
    [viewController dismissViewControllerAnimated:YES completion:nil];
}

iOS 6.0 미만 버전에서도 정상적으로 동작하도록 하기 위해 기존의 방식 또한 함께 구현하였습니다.  loadProductWithParameters:completionBlock: 이 호출되면 해당 앱스토어의 정보를 원격지에서 읽어옵니다. 이 과정이 끝나면 completionBlock으로 진입하게 되는데 result값에 정상적으로 로드가 되었는지 여부가 담겨오게 됩니다.

정상적으로 로드가 되었다면 위의 예시처럼 storeController를 띄워줍니다. 여기서 추가로 중요한 부분은 productViewControllerDidFinish: 의 구현입니다. 델리게이트를 통해 사용자가 앱스토어창을 닫을려고 시도할 때에 이 메소드에 진입하게 됩니다. 창을 닫아주시면 됩니다. 구현 화면의 예시는 다음과 같습니다.