pystructs는 파이썬에서 쉽게 bytes-marshalling을 쉽게 할 수 있도록 도와주고자 만든 파이썬 라이브러리이다. 이것을 왜 개발하게 되었고 무엇을 배웠으며 앞으로의 방향에 대해 정리하며 글을 써보고자 한다.

🤔 파이썬에서는 너무 힘들어

학교 과목 중 포렌식이라는 과목이 있었다. 그리고 FAT32 구조를 분석하는 과제가 있었는데 디스크 이미지 덤프파일을 읽어 포맷에 맞게 파싱할 필요가 있었는데 슬라이싱을 통하여 값을 가져오니 다음과 같은 코드를 작성하게 되었다.

class PartitionTableEntry:
    ...
    @staticmethod
    def from_bytes(raw: bytes):
        def to_int(raw: bytes) -> int:
            return int.from_bytes(raw, byteorder='little')

        return PartitionTableEntry(raw[0], to_int(raw[1:4]), raw[4], to_int(raw[5:8]), to_int(raw[8:12]),
to_int(raw[12:]))

반면 C에서는 아래와 같이 작성하면 된다.

// 사람마다 작성하는 방법이 다를수 있습니다
struct partition_table_entry {
        int BOOT_INDICATOR: 8,
            STARTING_CHS_VALUES: 24,
            PARITION_TYPE: 8,
            ENDING_CHS_VALUES: 24,
            STARTING_SECTOR,
            PARTITION_SIZE;
};

struct partition_table_entry* entry = (struct partition_table_entry*) bytes;

파이썬으로 작성했을 때는 다음과 같은 문제가 있었다.

  1. 일일이 슬라이싱 해주기 때문에 소스가 보기 안 좋아진다.
  2. 슬라이싱 및 변환후 생성자의 인자에 넣어주기 위해 해당 구조체가 가지고 있는 필드들의 순서를 외우고 있어야 한다.
  3. 슬라이싱 과정이 어떤 필드를 파싱하는 것인지 눈에 보이지 않는다.

MBR만해도 저런데 FAT32의 많은 속성을 파싱할때는 얼마나 고생해야 할지 감이 오질 않았다. 이렇게 하면 안 된다를 절실히 느꼈다 🙅

반면 c언어의 경우에는 struct를 작성하고 포인터 타입을 바꿔주는 것만으로 특별한 파싱 과정 없이 쉽게 사용할 수 있는 점으로 인해 많은 친구들이 c언어로 해당 과제를 구현하기 시작했다. 하지만 나는 파이썬으로도 충분히 할 수 있지 않을까 생각하고 방법을 찾아보기 시작하였다. 그러나 내가 원하는 편한 라이브러리는 보이지 않았다.

그래서

내가 직접 만들어보자

라고 생각하게 되었다.

쉽게 사용할 수 있는 라이브러리는 어떤 것일까 생각하던 중 django의 model을 떠올렸다.
각 필드의 속성을 쉽게 정의하고 struct 같이 class를 정의해주기만 하면 되기 때문에 이거다! 라는 느낌을 받았다.

carbon(1).png

그리고 프로젝트를 시작하였다.

🙏 오픈소스 프로젝트!

차츰 개발하고 인터페이스의 윤곽이 잡혀가자 이 프로젝트도 컨트리뷰터들의 참여를 기대할 수 있지 않을까 하는 기대, 욕심이 생겨났다! 그래서 쉽게 개발할 수 있는 필드, 기능 구현 이슈 몇가지를 GFI 로 열어놓았다.

그랬더니 실제로 어떤 분이 해당 이슈를 도와주고 싶으시다고 comment를 남겨주셨다!

image.png

그래서 이야기를 나눈뒤 PR을 올려주셨는데 아직 git 사용이 어색하신지 불필요한 커밋을 함께 주셔서 rebase 해서 수정해주실 수 있으신지 여쭤봤는데 내가 영어 이해력이 부족하여 잘 못 말씀드린건지 지금은 커뮤니케이션이 진행되고 있지 않다 ㅠㅠ

image.png

처음 컨트리뷰션하시는 분들을 위해 github 외에 slack이나 gitter같은 커뮤니케이션할 장소가 필요하다는 생각이 들었다. 그래서 slack 서버를 만들어 README에 추가해 놓았다. 또한 CONTRIBUTION guide 나 COC도 마련해야 겠다는 생각이 들었다. 이는 다른 오픈소스 프로젝트를 참고하여 작성해보기로 하였다.

📝 문서화는 필요해!

아직 1.x대 버전도 아니기에 더 나은 라이브러리를 만들기 위해 인터페이스와 구조를 자주 바꾸고 있다.
물론 지금 아무도 사용하는 사람이 없기에 개의치 않고 하고 있지만 사용하는 사람이 있다면 CHANGELOG 가 필요할 것이다. 그저 버전을 올렸을 뿐인데 갑자기 에러가 터지고 무엇이 바뀌었는지가 릴리즈에 적혀있지 않다면 정말 난감할 것이다.

그 외에 간단한 예제 코드들과 docs를 작성해보았다. 어떤 api를 제공하고 있는 지, 얼마나 편하게 짤 수 있는지를 알아야 라이브러리를 사용할 지 않을지 고려라도 보지 않을까? 라는 생각에 작성했다. 하지만 아직 잘 감이 안오고 앞으로 고쳐나가야 할 방향이라고 생각한다.

⛳️ 개선할 점

pystructs를 만들었고 사용을 할 수는 있지만 아직 여전히 개선해야 할 여지가 많다.

성능 향상

우선 순수 파이썬으로 작성되어있기 때문에 c 확장으로 만들어진 모듈들 보다는 성능면에서 확실히 문제가 있을 것이다. 이를 위해 내부파트를 c++ 로 작성하고, python에서 바인딩하여 사용할 수 있게 하는 방법으로 개선하는 것을 생각하고 있다.

인터페이스 개선 및 필드 추가

현재 필드를 몇가지 지원하지 않고 있다. 아까 그 PR도 IntField의 확장을 작성하기 위한 PR이었고, 더 많은 필드를 지원해야할 필요가 있을 것 같다

또한 좀 더 사용하기 쉬운 인터페이스로 개선할 수 있어 보인다. 지금은 따로 lazy하게 해주는 initializegetattr 부분에서 자동으로 해주는 것 같은 이슈들이 될 것 같다.

문서화 정리

아직 모든 필드를 문서화 하고 있지도 않고, 부족한 영어 실력으로 짤막히 적어놓은 소개글도 있다. 이런 부분들을 다시 작성, 추가하여 개선할 필요가 있어 보인다.

버그 수정

어딘가에 숨어있을 버그🐞.. 를 잡아야 한다. bug report, feature request를 위한 github issue_template를 마련해 놓았지만 아무 이슈도 생겨나지 않는다 😢

👍 글을 마무리 하며

학교의 수행평가 과제를 할 때 한 불편함으로 인해 만들기 시작한 프로젝트를 통해 여러 가지를 해봤던 경험을 짧게 나마 글로 적어보았다. 작은 프로젝트고 사용자도 없지만 나름 의미 있는 프로젝트라고 생각한다. 테스트 커버리지와 문서화에 신경 써본 첫 개인프로젝트이고 첫 PR을 받아본 프로젝트이기 때문이다.

오픈소소를 좋아해서 현재 오픈소스 프로젝트를 하고 있는 회사에서 협업을 하고 있다. 좋은 분들과 함께 많은 것을 배워가는 중이고 앞으로도 오픈소스에 많은 관심을 가지고 기여할 예정이다. 😀

오타 있으면 알려주세요!
글을 잘 쓰고 싶다