[PHP:rfc] 더 짧은 속성 구문

원문: https://wiki.php.net/rfc/shorter_attribute_syntax

PHP 8.0에선 많은 내용들이 추가되면서, rfc들도 많이 요청되면서 다양한 토론들이 이루어지고 있습니다.
해당 rfc는 2020/06/03 23:24에 최초로 생성된 rfc이며, 내부 검토를 마치고 토론중에 있습니다.

주장도 함리적이고, 내용들에 대해서 자세한 예시까지 해줘서 해당 rfc를 간단한게 정리해보았습니다.


PHP RFC: Shorter Attribute Syntax


Introduction

우리는 PHP 8.0에서 속성 구문을 <<Attr>> 대신 @@Attr을 사용할 것을 제안합니다.

저번달 초, Attributes v2는 PHP 8.0적용되는 것이 승인되었으며, 투표 동안 <<Attr>>@:Attr의 구문중에서 <<Attr>>구문이 3/4에게 선택 되었습니다.
하지만, 이 구문은 몇 가지 주목할만한 단점이 있습니다.

1. 장황함 (Verbosity)

아래의 RFC 예시에선 속성의 이름 보다 시프트 토큰(<<>>)에 사용되는 문자가 더 많습니다.

<<Jit>>
function foo() {}

특히 하나 이상의 속성이 필요할땐 이 구문은 한눈에 보기 어려울 수 있습니다.
이를 완화 하기위해  속성 수정 RFC에선 여러개의 속성에서 하나의 시프트 토큰을 사용하는 방법을 제안 했습니다.

<<Attr1("foo"),
  Attr2("bar")>>
public function test() {}

하지만, 이 방법은 다른 문제가 있습니다. 속성을 추가, 삭제하려면 여러줄을 수정되어 diff에 노이즈가 생기게 됩니다.
다만, 이 제한은 후행 쉼표를 허용해 다음과 같이 작성 하여 해결 할 수 있습니다.

<<
  Attr1("foo"),
  Attr2("bar"),
>>
public function test() {}

하지만, 스프트 토큰에 두개의 추가 행이 필요하며, 속성끼리 서로 이동할 때에 여러 줄이 수정되어지게 됩니다.

2. 중접 된 속성의 부재 (Lack of nested attributes)

중접된 주석은 Doctrine에서 많이 이용 되고 있으며, 여기서 그 예를 볼 수 있다.

@JoinTable(
    name="User_Group",
    joinColumns={@JoinColumn(name="User_id", referencedColumnName="id")},
    inverseJoinColumns={@JoinColumn(name="Group_id", referencedColumnName="id")}
)

<<>>구문(및 잠재적 속성 그룹화)으로 속성을 중접하는 방법은 새로운 Attr 표현식을 허용하는 것입니다.
하지만, 구현하기 쉽지 않으며, 혼란을 야기할수 있습니다. (예시로 new Foo()는 허용되지만, Foo::create()는 작동되지 않습니다).
결국 이것은 const 표현식에 많은 변경이 필요하기에 구현 중 포기되었습니다.

3. 제너릭과의 혼동 (Confusion with generics)

속성과 제너릭의 구문간에 기술적으로 충돌은 없지만, PHP에서 제너릭이 지원되면 속성과 제너릭이 사용되는 위치를 한눈에 파악하기 더 여러울 수 있습니다.

4. 쉬프트 연산자와 const 인수와의 혼동 (Confusion with shift operators and const arguments)

시프트 토큰을 재사용 하면, 상수 표현식인지, 멀티 속성인지, 또는 쉬프트 토큰인지 식별하기 어려울 수 있습니다.

<<Bar(2 * (3 + 3)>>Baz, (4 + 5) * 2)>>
function foo() {}

물론 이 이런 상황에서의 쉬프트 토큰은 거의 사용되지 않으므로 마니어너한 문제입니다만,
만약 그룹화 된 속성 제한이 승인되면, 쉼표로 구분된 속성과 속성인수간의 유사한 혼동이 있을 수 있습니다.

<<Attr1(2 * 3 + 3), Bar(4 + 5 * 2)>>
<<Attr2(2 * (3 + 3), Baz, (4 + 5) * 2)>>
function foo() {}

5. 다른 언어와 유사하지 않음 (Dissimilarity to other languages)

대부분의 C 패밀리 언어들은 속성 구문에 [Attr] 또는 @Attr 를 사용하며ㅡ, 4개가 아닌 1~2개의 문자만 필요합니다. (아래의 비교 참고)


Proposal

PHP8.0에서 <<Attr>> 구문 대신에 @@Attr구문을 사용합시다.

그렇게하면 위의 문제가 해결되며, 속성이 있는 대부분읜 다른 언어와 비교하여 절반 정도의 문자만 필요하므로 장황함이 줄어들게 됩니다.

@@Jit
function foo() {}

@@구문은 충접된 속성과 충돌 하지않아, 원하는 경우 나중에 지원을 추가하는 것이 간단해집니다. (특이 케이스나 const 표션식을 변경할 필요없이)

@@JoinTable(
    "User_Group",
    @@JoinColumn("User_id", "id"),
    @@JoinColumn("Group_id", "id"),
)
private $groups;

더 짧은 구문은 제너릭 또는 스프트 토큰과 달리 속성이 사용되는 위치를 쉽게 알 수 있어 코드 가독성을 향상 시킬 수 있습니다.

@@Attr1("foo")
@@Attr2("bar") // 이 라인은 다른줄과 독립적으로 추가, 삭제할 수 있습니다.
public function test() {}

Discussion

왜 “@:” 구문을 반대 합니까?

우선 “@;”와 같은 실수로 오타가 발생하기 쉽다는 것입니다.
일부 사람들의 경우 비대칭적인 문법을 싫어 하기 때문이기에 PHP의 토큰들과 잘 맞지 않기 때문입니다.
@@문법은 위 두가지 사항을 모두 해결합니다.

왜 키워드로 대신 사용하지 않습니까?

기호 대신 키워드를 사용하는것은 좋습니다.

attribute Foo();
function myFunc() {}

하지만, 제안의 목적은 덜 일반적이고 다른 언어들에서 공통적으로 사용되는 속성 구문과 더 잘맞는 구문에 도달 하는 것입니다.
키워드를 사용하게되면 이러한 목표를 충족하지 못하게됩니다.

구문의 선택은 우리가 주관이 아닌 익숙한것으로 해야하지 않습니까?

어느정도 동의합니다. 하지만 이 RFC가 간략화 하려는 짧은 구문을 선호하는 객관적인 이유도 있을 것입니다.

다른 언어들과의 비교

속성이 있는 다른 언어들은 구문에 [Attr] 혹은 @Attr을 변형하여 사용합니다.
Hack은 <<Attr>>을 사용하는 유일한 언어이지만 PHP와의 호환을 지향하지 않기 때문에 @Attr로 이전 하는 것 같습니다.

  • C#: [Attr] 1
  • C++: [[attr]] 2
  • Hack: <<Attr>> 3 (하지만, @Attr로 변경 중에 있습니다.) 4
  • Java: @Attr 5
  • Kotlin: @Attr 6
  • Python: @attr 7
  • Rust: #[attr] 8
  • Swift: @attr 9
  • TypeScript/JS: @Attr 10

Backward Incompatible Changes (이전 버전과 호환되지 않는 변경점)

이론적으로 BC(하위호환) 오류가 적습니다.
이후 다중 오차 억제 연산자들은 추가적인 영향이 추가될 수 있다. (예: @@@@@really_suppress_me()). (의역)
하지만 이렇게 사용하는 것은 유용하지 않으며, 어느 곳에서도 사용되지 않을 것이다.


Vote

PHP 8.0에서 속성 구문으로 제안된 @@ 를 사용 하시겠습니까? Yes/No [현재(2020/06/04)는 토론중입니다]


References


내용이 재미 있어보이고 좋은 의견이여서 번역해 봤습니다만,
개인적인 의견으론 Hack처럼 @ 연산자를 버리고 @Attr로 가는것도 괜찮아 보이는것같습니다. ㅎㅎ

Get started learning Python with the Jobtensor Python Tutorial. The tool is interactive and allows beginners as well as advanced coders to start practicing right away. There are also sections specifically focused on Data Science.

https://jobtensor.com/Python-Introduction

[번역] 스팸과 싸우는 5가지 방법

원본글 : 5 Ways of Battling Form Spam

만약 여러분이 웹 어플리케이션을 만든다면, 스팸 봇들에게 점렴당하는 것들을 막을순 없을것입니다.

내 프로젝트 중 하나는 회원가입 폼 부분을 당해서 17,000여개의 가짜 유저을 정리하는 것은 정말 힘들었습니다.
이를 해결 하기위해 스팸 봇과 싸우는 방법을 트위터에 물어보았고, 많은 반응과 좋은 아이디어들을 얻을 수 있었습니다.
나는 언급된 방법들을 공유해 만약 여러분이 공격 당했을 때 어떻게 방어해야하는지 알게 될 수 있을 것입니다.

1. Cloudflare

만약 여러분이 클라우드플레어와 같은 서비스를 사용하고 있으면, “page rules”을 설정해 URL과 양식 제출을 중단 할 수 있습니다.

다만, 나는 잘 다른 방법들 처럼 잘 작동 하지 않을 것 이라고 생각합니다.
하지만, 이 방법은 이미 운영중인 서비스에 어떠한 영향도 없이 신속하게 구현이 가능합니다.

2. Honeypot

허니팟은 최우선 방어 방법이고 설치 또한 간단합니다.
폼 안에 아무런 값이 없는 hidden 타입에 input 태그를 두고, 만약 hidden 필드 안에 값과 함께 제출 된다면, 거의 봇일 것이다.

직접 이를 구현 할 수 있지만, spatie/laravel-honeypot과 같은 패키지가 조내하여 손쉽게 통합된 환경에서 구현 할 수 있습니다

‘name’이라는 input필드가 있다면 봇은 그 필드를 체워야 하는 필드로 생각한다는 것을 기억하시기 바랍니다.

3. Validate Emails(이메일 인증)

만약 이메일을 요구하는 양식이라면, 사용자 이메일로 메일을 보내어 이메일 안에 있는 버튼을 클릭하여 진짜인지 확인 할 수 있습니다.
이 방법은 Laravel Newsletter를 포함해 많은 뉴스레터가 사용하는 방식입니다.

사용자는 이메일을 입력하고, 우리의 서비스는 이메일을 보내면, 사용자는 승인버튼을 눌러 우리의 서비스에 가입 할 수 있다.

이렇게 하면 가입되는 유저는 봇이 아니라 실제 사용자들일 것 입니다.

다른 방법으론 API를 통해 이메을 확인해주는 identibyte와 같은 서비스를 사용하는 방법입니다.
이런 방법을 통해 사용자들은 추가적인 단계없이 가입 할 수 있습니다.

4. Capcha

이 방법은 제가 가장 좋아하는 방법입니다. 왜냐하면, 내가 캡차를 싫어하기 때문입니다.
Google가 가지고 있는 invisible reCaptcha는 아마 제일 좋은 캡차 옵션일 것입니다.

5. Dedicated Spam Services (스팸 차단 서비스)

두 가지의 유명한 스팸 서비스인 AkismetStop Forum Spam이 있습니다.
Akismet은 유료이고 Stop Forum Spam은 무료 입니다.

나는 Akismet 모든 워드프레스 사이트에 사용했습니다. 하지만, 워드프레스가 아닌 라라벨에서도 사용할 수 있습니다.
여러분은 들은 Akismet의 API를 사용하거나 nickurt/laravel-akismet과 같은 것을 사용하면 됩니다.

Stop Forum Spam은 무료 서비스 이며, Akismet와 유사합니다.
그리고 라라벨 페키지 nickurt/laravel-stopforumspam가 존재하며, 통합 적으로 사용할 수 있게 도움을 줍니다.


모든 옵션들은 honeypot을 해본 후 부터 사용하는것이 좋습니다.
만약 honeypot이 실패하면 봇이 공격을 막을때 까지 다른 옵션들을 사용하세요.
다만, 오늘 동작하는것이 내일엔 안할수도 있다는 것을 기억하고, 매일 봇들과 싸워야 한다는것을 잊지 마세요.