클래스 속성과 인스턴스 속성 알아보기

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


우선적으로 이야기 하자면

  • 클래스 속성 : 모든 인스턴스가 공유. 인스턴스 자체가 사용해야 하는 값을 저장할 때 사용
  • 인스턴스 속성: 인스턴스 별로 독립되어 있음. 각 인스턴스가 값을 따로 저장해야 할 때 사용

클래스 속성 사용하기

class 클래스이름:
  속성 = 값
class Person:
  bag = []


  def put_bag(self, stuff):
    self.bag.append(stuff)


jane = Person()
jane.put_bag('책')

mike = Person()
mike.put_bag('안경')

print(jane.bag)
print(mike.bag)
['책', '열쇠']
['책', '열쇠']

우리는 jane과 mike 각각의 인스턴스를 만들고자 put_bag 메서드에 물건을 넣었는데, 출력을 해보면 넣었던 물건들이 합쳐져서 나오는 것을 볼 수 있다. 즉, 클래스 속성은 클래스에 속해 있으며 모든 인스턴스에서 공유하고 있다.

그래서 우리가 put_bag 메서드에서 클래스 속성 bag 에 접근하기 위해 self를 사용했는데, 사실 self는 현재의 인스턴스를 뜻하는 것이기 때문에 클래스 속성을 지칭하기에는 조금 모호한 표현이다. 그래서 아래와 같이 클래스 속성에 접근할 때는 클래스 이름으로 접근하면 좀 더 코드가 명확해진다.

def put_bag(self, stuff):
  Person.bag.append(stuff)


print(Person.bag)

일반적으로 파이썬에서는 속성과 메서드 이름을 찾을 때 인스턴스 > 클래스 순으로 찾는다. 그래서 인스턴스 속성이 없으면 클래스 속성을 찾게 되므로 jane.bag혹은 mike.bag을 해도 문제없이 동작은 한다. 겉보기에는 인스턴스 속성을 사용하는 것 같지만 실제로는 클래스 속성이다.

인스턴스 속성 사용하기

class Person:
  def __init__(self):
    self.bag = []

  def put_bag(self, stuff):
    self.bag.appennd(stuff)


jane = Person()
jane.put_bag('책')

mike = Person()
mike.put_bag('안경')

print(jane.bag)
print(mike.bag)
['책']
['열쇠']

즉, 인스턴스 속성은 인스턴스별로 독립되어 있어 서로 영향을 주지 않는 것으로 볼 수 있다.

비공개 클래스 속성 사용하기

클래스 속성도 비공개 속성을 만들 수 있는데, 그 방법은 클래스 속성을 만들때 아래와 같이 만들면 된다. 이 속성은 클래스 안에서만 접근할 수 있고 클래스 바깥에서는 접근이 불가능하다.

class 클래스이름:  
  __속성 = 값

즉, 클래스에서 공개하고 싶지 않은 속성이 있다면 비공개 속성을 사용하면 된다.

class Knight:
  __item_limit = 10 # 비공개 클래스 속성

  def print_item_limit(self):
    print(Knight.__item_limit)  # 클래스 안에서는 접근 가능


x = Knight()
x.print_item_limit()

print(Knight.__item_limit) # 클래스 바깥에서는 접근 불가능
10
Traceback (most recent call last):
  File "C:\project\class_private_class_attribute_error.py ", line 11, in <module>
    print(Knight.__item_limit)
AttributeError: type object 'Knight' has no attribute '__item_limit'

실행을 하면 클래스 Knight의 비공개 클래스 속성 __item_limit는 클래스 안의 print_item_limit 메서드에만 접근할 수 있고 클래스 바깥에서 접근하면 에러가 발생한다. 아이켐의 보유 제한은 10개인데, 이 클래스를 사용하는 사람이 마음대로 수정하면 곤란하니 그럴때 사용하면 된다. 즉, 비공개 클래스 속성은 클래스 바깥으로 드러내고 싶지 않은 값에 사용한다

CSRF 공격이란?

|

개인적인 연습 내용을 정리한 글입니다.
잘못된 내용이 있다면 편하게 댓글 남겨주세요!


CSRF

CSRF(Cross Site Request Forgery) 공격이란 웹 어플리케이션 취약점 중 하나로 인터넷 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만든는 공격이다.

이러한 CSRF를 통해 해커는 희생자의 권한을 도용해 중요 기능을 실행하는 것이 가능핟. 그치만 CSRF는 해커가 사용자의 컴퓨터를 감염시키거나 서버를 해킹해서 이뤄지는 공격은 아니다. 이러한 CSRF 공격이 이루어지려면 다음 조건이 만족되어야 한다.

  • 위조 요청을 전송하는 서비스에 희생자가 로그인한 상태
  • 희생자가 해커가 만든 피싱 사이트에 접속

이 두 조건을 모두 충족시키기는 어려워보이지만, 사실 그렇지도 않다. 예로들어 페이스북, 로그인과 같은 사이트에는 우리가 보통 자동 로그인을 해놓는 경우가 많다. 이렇게 자동 로그인이 되어있는 상태에서 해커가 만든 피싱사이트(메인, 음란 사이트 등)를 통해 접속을 하기만 하면 공격이 이루어지는 것이다. 또 사용자가 해커가 만든 피싱 사이트를 접속하지 않더라도 해커가 XSS 공격을 성공한 정상 사이트를 통해 CSRF 공격이 수행될 수도 있다.

CSRF 공격 방어

  • Referrer 검증
  • Security Token 사용(CSRF_token)

일반적으로 CSRF 공격 방어는 조회성 (HTTP GET Method) 데이터에는 방어 대상에 두지않고, 쓰기/변경이 가능한 POST, PATCH, DELETE Method에만 적용하면 된다. 물론 정말 중요한 데이터를 조회하거나 GET을 통해 쓰기/변경 등의 동작을 한다면 Get Method에도 방어를 해야할 수도 있다.

Referrer 검증

Back-end 단에서 request의 referrer을 확인하여 domain 이 일치하는 지 검증하는 방법이다.

일반적으로 referrer검증만으로 대부분의 CSRF 공격을 방어할 수 있다. 하지만 같은 도메인 내의 페이지에 XSS 취약점이 있는 경우는 CSRF 공격에 취약해질 수 있다. domain 단위 검증에서 좀 더 세밀하게 페이지 단위까지 일치하는 지 검증을 하면 도메인 내의 타 페이지에서의 XSS 취약점에 의한 CSRF 공격을 방어할 수 있다.

CSRF 토큰

Referrer 검증이 불가한 환경이라면, Security Token을 활용할 수 있다. 우선 사용자의 세션에 임의의 난수값을 저장하고 사용자의 요청마다 해당 난수 값을 포함시켜 전송한다. 이후 Back-end 단에서 요청을 받을 때마다 세션에 저장된 토큰값과 요청 파라미터에 전달되는 토큰값이 일치하는 지 검증한다. 이 방법 또한 같은 도메인 내에 XSS 취약점이 있다면 CSRF 공격에 취약해 진다.


<form>
    {% csrf_token %}
    <input type="text" name="text"/>
    <input type="submit" value="확인"/>
</form>

Django 에서는 자체적인 템플릿을 통해 {% csrf_token %}이라고 form에 넣는 것만으로도 토큰을 주고받을 수 있도록 쉽게 사용이 가능하다.

클라이언트에서 해당 페이지를 접속하게 되면 Django에서 자동으로 csrf 토큰을 클라이언트로 보내어 cookie에 저장하고, POST로 전송할 때 cookie의 csrf 토큰이 함께 전송되어 인증하는 방식이다.


XSS 공격이란?

XSS(Cross-site Scripting)는 웹 상에서 가장 기초적인 취약점 공격방법의 일종으로, 악의적인 사용자(권한이 없는 사용)가 공격하려는 사이트에 스크립트를 넣는 기법을 말한다. 공격에 성공하면 사이트에 접속한 사용자는 삽욉된 코드를 실행하게 되며, 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰 등의 민감한 정보를 탈취한다. (대부분 자바스크립트를 사용하여 공격하는 경우가 많다.)

공격 방법이 단순하고 가장 기초적이지만, 많은 웹사이트들이 XSS에 대한 방버조치를 해두지 않아 공격을 받는 경우가 많다. 여러 사용자가 접근 가능한 게시판 등에 코드를 삽입하는 경우도 많으며, 경우에 따라서는 메일과 같은 매체를 통해서도 전파가 된다.

XSS 공격은 주로 CSRF 공격을 하기 위해 사용되기 때문에 혼동되기가 쉬운데, CSRF는 특정한 행동을 시키는 것이고 XSS는 자바스크립트를 실행시키는 것으로 이해하면 된다.

git flow 사용해보기

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


git flow install

  • 홈페이지: git flow install
  • macOS: brew install git-flow-avh
  • linux: apt-get install git-flow

Git-flow 구성 살펴보기

git-flow에는 5가지 종류의 브랜치가 존재한다.
항상 유지되는 메인브랜치(master, develop)과 일정 기간동안만 유지되는 보조브랜치(feature, release, hotfix)

master

master 브랜치에 merge된 내역은 새로운 버전이 갱신되었다는 것을 의미한다. 즉, master 브랜치에 변경된 내역이 생기면 최종 버전인 Tag를 통해 Production에 배포된다.

develop

hotfix를 제외한 모든 변경내역이 출발하는 지점이다. develop브랜치의 코드가 안정화되고 배포할 준비가 되면 master를 통해 배포 버전의 태그를 단다.

feature

feature 브랜치는 배포하려고 하는 기능을 개발하는 브랜치다. 기능을 개발하기 시작할 때는 언제 배포할 수 있을지 알수 없다. 기능을 다 완성할 때까지 유지하고 있다가 다 완성되면 develop 브랜치로 병합한다.

  • 브랜치가 생성되는 대상: develop
  • merge 대상: develop

release

release 브랜치는 실제 배포할 상태가 된 경우에 생성하는 브랜치이다.

  • 브랜치가 생성되는 대상: develop
  • merge 대상: develop, master

hotfix

미리 계획되지 않은 브랜치다. 기본적인 동작방식은 release와 비슷하다. 배포 이후에 생긴 치명적인 버그는 즉시 해결해야하기 때문에 문제가 생기면 master 브랜치에 만들어둔 태그 tag로 부터 긴급 수정을 위한 브랜치를 생성한다.

  • 브랜치가 생성되는 대상: master
  • merge 대상: develop, master

즉, 처음에는 master와 develop 브랜치만 존재한다. 이때 develop 또한 master에서부터 시작된 브랜치이다.

새로운 기능에 대한 추가 작업이 있는 경우 develop에서 feature브랜치를 생성하고 해당 feature브랜치에서 새로운 기능을 개발한다. 즉, feature 브랜치는 항상 develop브랜치에서부터 시작하게 된다. 기능 추가 작업이 완료되었다면 feature브랜치는 develop 브랜치로 merge를 하게된다.

develop 브랜치에 feature 브랜치에서 만든 기능들이 merge 되었다면 QA를 하기 위해 develop브랜치에서부터 release 브랜치를 생성한다. QA를 진행하면서 발생한 버그들은 모두 release 브랜치에서 수정이 된다. QA를 무사히 통과했다면 release 브랜치를 master와 develop 브랜치에 merge를 한다.

마지막으로 출시된 master 브랜치에서 버전 태그를 추가하면 최종적으로 우리가 개발하고자했던 모든 기능들은 master 브랜치에 포함됨으로써 해당 기능을 출시할 수 있게 된다.

git flow 흐름 살펴보기

git flow

이미지원본: 우아한형제들 기술블로그

  • Upstream Remote Repository: 개발자들이 공유하는 저장소, 최신 코드가 저장되어 있는 원격저장소
  • Origin Remote Repository: Upstream Repository를 Fork한 원격 개인 저장소
  • Local Repository: 내 컴퓨터에 저장되어있는 개인 저장소

git flow 간단하게 시작해보기

  • Local Repository에서 작업을 완료한 후 작업 브랜치를 Origin Repository에 push
  • Github에서 Origin Repositorydp push한 브랜치를 Upstream Repository로 merge하는 pull request 생성
  • 코드리뷰를 거친 뒤 merge
  • 다시 새로운 작업을 할때 Local Repositorydptj Upstream Repository를 pull
1. Upstream Repository를 나의 Origin Remote Repository에 Fork
2. 해당 git url을 clone

git flow init

# 기본 설정이 develop에 되어있을 것
git flow feature start [생성할 branch name]
git merge develop
git flow feature finish [삭제할 branch name]

# release
git flow release start [생성할 release name]

# release를 master, develop에 merge
# tag로 master의 버전 확인
git flow release finish [완료할 release name]


git pull origin develop #이 상황 무한 반복

feature 브랜치에서의 참고사항

  • feature 브랜치에서 작업을 하는 동안은 develop 브랜치의 변경사항을 자주 동기화해준다.
  • 반대로 feature 브랜치의 변경사항은 develop 브랜치로 merge하는 경우는 기능 구현이 끝났을때, 딱 한번이다.
  • 작업을 완료한 feature브랜치는 삭제해도 괜찮다.

release 브랜치에서의 참고사항

  • release의 수정사항들은 develop으로 자주 동기화해준다.
  • 하지만 release 브랜치 생성 후의 develop 브랜치의 수정사항은 동기화 하지 않는다.
    • 해당 develop 브랜치의 변경사항은 다음 배포 버전에 대한 것이기 때문에 다음 release 생성까지 merge하지 않는다.

non-fast-forward 에러 해결하기

|

개인적인 연습 내용을 정리한 글입니다.
잘못된 내용이 있다면 편하게 댓글 남겨주세요!


문제 상황

  • github에서 저장소 생성 후 저장소 주소를 remote에 입력(git remote add origin https://github…..)
  • 로컬에서도 정상적으로 초기화(git init)
  • git pull 또는 git merge 명령이 동작하지 않음
  • git push origin master시 [rejected] master -> master (non-fast-forward)에러 발생
git push -u origin master  

To github.com:
! [rejected]        master -> master (non-fast-forward)

error: 레퍼런스를 'git@github.com:'에 푸시하는데 실패했습니다
힌트: 현재 브랜치의 끝이 리모트 브랜치보다 뒤에 있으므로 업데이트가
힌트: 거부되었습니다. 푸시하기 전에 ('git pull ...' 등 명령으로) 리모트
힌트: 변경 사항을 포함하십시오.
힌트: 자세한 정보는 'git push --help'"Note about fast-forwards' 부분을
힌트: 참고하십시오.

원인

깃헙에 생성된 원격 저장소와 로컬에 생성된 저장소 간 공통분모가 없는 상태에서 병합하려는 시도로 인해 발생.
기본적으로 관련 없는 두 저장소를 병합하는 것은 안되도록 설정되어 있음.

해결방법

아래와 같이 git pull 시에 –allow-unrelated-histories 옵션 추가하여 관련 없었던 두 저장소를 병합하도록 허용

git pull origin master --allow-unrelated-histories

pycharm 글자가 안써지는 경우 (IdeaVim 해제)

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


맥북 초기화를 한 다음 파이참을 재 설치하고나니 갑자기 파이참에 글자가 써지질 않는다.

  • 경로: Preferences > Plugins > IdeaVim 체크 옵션 해제
pycharm_preferences

체크 박스 해제 후 하단의 apply 또는 OK버튼을 눌러주면 되며,

이후 파이참을 재시작하겠냐는 메시지와 함께 재시작하면 적용되어 사용가능하다.

ideavim 해제를 하지않고 사용할 경우 a를 누르면 글자 입력이 가능하다.