알아두면 쓸 데 있는 잡다한 개발지식

개발자라면, 아는 만큼 보인다는 말에 다들 공감하실 겁니다. 평소에 그냥 썼던 코드 한 줄도 나중에 ‘이게 이런 의미였구나~’ 하고 깨닫게 되는 경험을 다들 해보셨을 겁니다.

또 그만큼, 우리 주변에는 아직 알지 못하는, 또는 잘못 알고 있는 개발 지식들이 넘쳐납니다.

이를 조금이라도 더 많이 알고 있다면, 우리는 문제 상황에 직면했을 때 더욱 효율적으로 그 문제를 해결할 수 있을 겁니다.

더불어 개발자들 간의 커뮤니케이션도 더욱 원활해지고 이는 제품의 퀄리티 향상과도 직결될 것입니다.

이러한 생각을 토대로, 저희 스터디(var)는 다양한 개발 지식들을 함께 탐구하고 공유하며, 이를 통한 구성원들의 성장과 사내 서비스의 퀄리티 향상을 도모하고자 합니다.

Python Scraping Library

Python에서 Scraping할 때 대표적으로 사용되는 라이브러리는 다음과 같습니다.

각 라이브러리는 서로 다른 특징을 가지고 있어서 상황에 맞는 라이브러리를 선택하는 것이 의미가 있습니다.

Scrapy

  • 크롤링을 위해 개발된 프레임워크.
  • 병렬처리, robots.txt 준수여부, 다운로드 속도 제어 등 설정 가능.
  • 플러그인들이 호환이 잘 안되는 편.

bs4

  • HTML, XML 파일의 정보를 추출해내는 python 라이브러리
  • python 내장 모듈일 requests나 urllib을 이용해 HTML을 다운 받고, Beautiful Soup으로 데이터를 추출.
  • 서버에서 HTML을 다운 받기 때문에 서버사이드 렌더링을 사용하지 않는 SPA 사이트나, javascipt 렌더링을 필요로 하는 사이트들은 크롤링하기 까다로움.

Selenium

  • 자동화 테스트(버튼 클릭, 스크롤 조작 등등)에 사용되는 프레임워크.
  • 웹 페이지에서 javascript 렌더링을 통해 생성되는 데이터들을 손쉽게 가져올 수 있음.
  • 웹 브라우저를 실제로 진행시키는 방법이기 때문에 속도도 많이 느리고, 메모리도 상대적으로 많이 차지함.

싱글톤 디자인 패턴

싱글톤 디자인 패턴이란, 객체의 인스턴스가 오직 1개만 생성되는 패턴을 의미합니다. 싱글톤 패턴으로 객체를 선언하게 되면 해당 객체는 전역적으로 사용할 수 있게 됩니다. 즉, 해당 객체를 사용하는 곳에서는 모두 같은 데이터를 공유하게 됩니다.

이러한 패턴을 사용했을 때 얻을 수 있는 이점은 다음과 같습니다.

  • 메모리 상의 이점
    • 고정된 메모리 영역에 저장된 객체를 계속해서 사용하기 때문에 메모리 낭비를 방지할 수 있다.
  • 데이터 공유의 이점
    • 전역 인스턴스이기 때문에 데이터 공유가 쉽고 데이터 정합성 이 보장된다.

하지만 이 패턴은 다음과 같은 문제점을 지닙니다.

  • 싱글톤 인스턴스가 너무 무거워 지는 경우 인스턴스들 간에 결합도가 높아져 개방-폐쇄 원칙 을 위배하게 된다.
  • 많은 지점에서 데이터를 공유하기 때문에 테스트하기 어려워진다.
  • 멀티쓰레드 환경에서는 메모리 주소 공유가 안되기 때문에 동기화를 시켜주는 코드가 필요하다.
  • 클래스의 상속이 불가능하고 확장성이 떨어진다.

이러한 이유로 싱글톤 패턴은 객체지향에 위반되는 사례가 많고, 이를 단독으로 사용하는 것은 안티패턴으로 지양해야 합니다. 다만 이 패턴이 갖는 장점도 존재하기 때문에 이를 토대로 싱글톤 패턴이 사용되면 좋을 것 같은 상황을 정리해 보았습니다.

  • 대다수의 코드에서 공통적으로 동일한 동작이 필요한 경우 (ex. DB 커넥션 생성 객체)
  • 관리 포인트가 한 군데여야 하는 경우 (ex. 내부 이벤트를 스케쥴링하고 처리하는 객체)

PHP Trait 패턴

PHP는 Traits 라는 코드를 재사용 하는 방법을 지원합니다. 단일상속 언어인 PHP에서 다중 상속의 컨셉을 가져갈 수 있게 해 주는 메커니즘으로, 사용 방법은 다음과 같습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
trait Hello {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait World {
    public function sayWorld() {
        echo 'World';
    }
}

class MyHelloWorld {
    use Hello, World;
    public function sayExclamationMark() {
        echo '!';
    }
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();

코드 중복을 피하기 위한 방법으로 Class 상속과 Trait 활용을 비교해 볼 수 있습니다.

Class 상속

  • 단일 상속만 가능하다.
  • 상수나 동적인 변수를 가질 수 있다.
  • Method 오버라이딩이 가능하다.

Trait 활용

  • 다중 상속이 가능하다.
  • 상수나 동적인 변수를 가질 수 없다.
    • Trait을 활용하는 Class에서 선언한 상수나 변수를 이용할 수 있다. 하지만 이는 안티패턴으로 취급된다.
  • Method 오버라이딩이 가능하다.

이러한 이유로 Trait은 주로 중복되어 사용되는 Method들을 재사용하기 위한 목적으로 활용됩니다.

Trait을 활용했을 때 경험적으로 느낀 문제점은, 여러개의 Trait을 상속받는 경우 호출한 Method가 어느 Trait의 Method인지 구별하기가 힘들어 유지보수성이 낮아진다는 점입니다. 이러한 문제를 해결하기 위해 다음과 같은 구현 원칙을 제안해 봅니다.

  • 하나의 Trait에는 하나의 Method만 포함하도록
  • Trait명과 Method명이 같도록