Windows에 WSL (Windows Subsystem for Linux) 설치

Windows Subsystem for Linux

리눅스용 윈도우 하위 시스템 (Windows Subsystem for Linux, WSL)은 Windows 10 및 Windows Server 2019에서 네이티브로 리눅스 실행 파일을 실행하기 위한 호환성 계층이다.

Wikipedia

WSL은 Windows 10 및 Windows Server 2019 사용자는 별도의 가상화 환경을 구축할 필요 없이 리눅스 시스템을 사용할 수 있도록 한다. 초기에는 Ubuntu만 지원하였으나, 현재 openSUSE Leap 42, SUSE Linux Enterprise Server 12 등 다양한 리눅스 배포판을 지원한다. 아쉬운 점은 시스템 콜을 에뮬레이션 해 윈도우가 처리하는 방식으로, 리눅스의 모든 기능을 사용할 수는 없다. 다행히 이번에 WSL 2가 리눅스 커널을 포함하는 것으로 발표되어 앞으로의 기대감이 높은 상황이다.

Windows에 WSL 설치

윈도우에 WSL을 설치하기 위해선 먼저 Linux용 Windows 하위 시스템 기능을 켜야 한다.

그림 1. 설정의 앱 및 기능

설정의 앱 및 기능에서 우측 상단에 있는 프로그램 및 기능을 실행한다.

그림 2. 프로그램 및 기능

프로그램 및 기능에서 좌측 상단에 있는 Windows 기능 켜기/끄기를 실행한다.

그림 3. Windows 기능 켜기/끄기

상단의 Linux용 Windows 하위 시스템 항목을 체크한 후 확인 버튼을 누른다.

그림 4. Linux용 하위 시스템 항목 기능 설치

설치 과정을 거친 후 PC를 다시 부팅 한다.

그림 5. Microsoft Store에서 Ubuntu 검색 결과

부팅이 완료되었다면 Microsoft Store 앱에서 원하는 리눅스 배포판을 설치한다. 본 게시글에서는 Ubuntu를 설치하였다.

그림 6. Microsoft Store의 Ubuntu 앱
그림 7. Microsoft Store에서 Ubuntu 앱 설치

설치 버튼을 클릭하여 설치를 진행한다.

그림 8. Ubuntu 앱 설치

설치가 완료되었다면 설치한 앱을 실행한다.

그림 9. Ubuntu 앱 설치 완료

추가적인 설치 과정을 거친 후 리눅스 계정을 설정하면 설치가 완료된다.

Windows Subsystems for Linux 2

2019년 5월 초 WSL 2가 발표되었다. WSL과 차이점은 리눅스 커널을 포함한다는 점으로, 에뮬레이션 하던 시스템 콜을 직접 처리할 수 있다. Microsoft는 WSL 2가 WSL 1과 비교해 20배 빨라졌다고 한다. 자세한 내용은 Microsoft 개발자 블로그의 Announcing WSL 2나 ZDNet Korea의 기사 MS 윈도, 리눅스 커널 품는다 혹은 윈도10 속 리눅스커널로 되는 것, 안 되는 것에 자세히 설명되어있다.

Travis CI 맛보기

1. 지속적 통합 (Continuous Integration, CI)이란?

지속적 통합이란, 개발 중간 중간 작은 변경 사항을 합쳐나가는 행동이다. 이는 개발 과정의 마지막에 거대한 변경 사항을 한 번에 합치는 기존의 관습과는 반대되는 것이다. 지속적 통합을 적용하지 않은 프로젝트의 개발자들은, 개발 중인 소스 코드와 프로젝트의 소스 코드를 통합하기 위해 점점 더 많은 시간을 쏟아부어야 한다. 따라서 지속적 통합은, 프로젝트를 더 작고 자주 통합하면서 거대한 통합을 위한 시간을 단축시켜 준다. 즉, 지속적 통합의 목표는 더 작게 개발하고 테스트하면서 더 건강한 소프트웨어를 만드는 것이다.

위키피디아는 지속적 통합에 대해 다음과 같이 설명한다.

소프트웨어 공학에서, 지속적 통합은 지속적으로 퀄리티 컨르롤을 적용하는 프로세스를 실행하는 것이다. 작은 단위의 작업, 빈번한 적용, 지속적인 통합은 모든 개발을 완료한 뒤에 퀄리티 컨트롤을 적용하는 고전적인 방법을 대체하는 방법으로서 소프트웨어의 질적 향상과 소프트웨어를 배포하는데 걸리는 시간을 줄이는데 초점이 맞추어져 있다.

Wikipedia

Travis CI 또한, 이러한 목표를 달성하기 위해 나타났다.

2. Travis CI

Travis CI는 지속적 통합을 위한 서비스들 중 하나로, GitHub 기반으로 코드 변화를 자동으로 빌드하고 테스트하며, 즉각적으로 피드백을 제공하며 개발을 지원한다. 뿐만 아니라, 배포 관리, 알림 등 다양한 개발 과정을 자동화할 수 있도록 도와준다. 우리가 Travis 플랫폼에서 빌드를 실행하면, Travis CI는 GitHub 저장소를 완전히 새로운 가상 환경에 복제한다. 그 뒤, 코드를 빌드하고 테스트하기 위한 일련의 작업을 수행한다. 만약 작업들 중 실패가 발생할 경우 해당 빌드는 깨진broken상태가 되며, 모든 작업이 성공할 경우 빌드는 통과passed상태가 되어 배포 과정을 진행한다.

Travis CI는 GitHub 저장소에 훅hook을 설정하여 저장소에 푸쉬가 이루어질 경우 자동으로 통합 과정을 실행한다. 빌드가 통과될 경우, 우리는 배포, 알림 등 다양한 기능을 자동화할 수 있다.

2.1. Travis CI 시작하기

Travis CI는 GitHub 기반으로 동작하기 때문에, 사용하기 위해선 먼저 GitHub 계정으로 회원가입 한다. 우측 상단의 “Sign in with GitHub” 버튼을 클릭하여 회원가입을 진행할 수 있다.

Travis CI의 과금 정책은 GitHub와 비슷하다. 공개 저장소에 대해서는 무료로 기능을 제공하지만, 비공개 저장소에 적용하기 위해선 $69 이상의 비용을 지불해야 한다. 무료 사용을 위해 공개 저장소를 하나 만들자.

프로젝트를 등록하기 위한 “+” 버튼을 클릭하면, 연동된 GitHub 계정에 있는 저장소를 선택할 수 있다. 만약 저장소가 보이지 않는다면 “Sync account” 버튼을 클릭해 계정을 동기화하거나, 권한을 확인해보자. 저장소 우측에 있는 스위치를 활성화하면 Travis CI에 프로젝트가 추가된다.

처음 프로젝트를 등록하면 위와 같은 화면이 보일 것이다. 아직 저장소에 대한 훅을 설정하지 않았으므로 저장소에 빌드가 존재하지 않는 것을 확인할 수 있다.

먼저, Travis가 빌드를 수행할 수 있도록 간단한 계산기 프로그램과 테스트 케이스를 포함하는 간단한 Gradle 프로젝트를 작성한다. 소스 코드는 다음과 같다. 물론 아직 훅을 설정하지 않았기 때문에 GitHub에 푸쉬하더라도 Travis CI의 프로젝트에서는 빌드가 없다고 나올 것이다.

public class Calculator {
    public double add(double a, double b) {
        return a + b;
    }

    public double subtract(double a, double b) {
        return a - b;
    }

    public double multiply(double a, double b) {
        return a * b;
    }

    public double divide(double a, double b) {
        return a / b;
    }
}
public class CalculatorTest {

    private static final double DELTA = 0.0001d;

    @Test
    public void add() {
        Calculator calculator = new Calculator();
        assertEquals(6.0d, calculator.add(2, 4), DELTA);
    }

    @Test
    public void subtract() {
        Calculator calculator = new Calculator();
        assertEquals(-2.0d, calculator.subtract(2, 4), DELTA);
    }

    @Test
    public void multiply() {
        Calculator calculator = new Calculator();
        assertEquals(8.0d, calculator.multiply(2, 4), DELTA);
    }

    @Test
    public void divide() {
        Calculator calculator = new Calculator();
        assertEquals(0.5d, calculator.divide(2, 4), DELTA);
    }
}

이제 훅을 설정해보자. Travis CI는 GitHub 저장소의 루트 위치에 있는 `.travis.yml` 파일을 바탕으로 프로젝트를 설정한다. 간단한 프로젝트이기 때문에 설정 파일도 간단하다. 그저 프로젝트가 사용하는 언어와, 사용하는 Java 버전만 명시하면 된다.

language: java

jdk:
 - oraclejdk8

.travis.yml 파일을 생성하고 푸쉬해보자.

훅이 설정되면 Travis CI는 커밋이 푸쉬될 때 마다 빌드를 실행한다. Gradle 프로젝트를 사용하기 때문에 빌드를 수행하기 전 gradle assemble 명령을 실행한 후 gradle check 명령으로 프로젝트를 빌드한다. gradle check  명령은 프로젝트에 작성된 테스트 케이스를 실행하여 올바르게 테스트를 통과하는지 검사한다. 만약 모든 테스트 케이스가 성공할 경우 빌드는 통과되겠지만, 하나라도 실패할 경우 빌드는 깨질 것이다. 지금은 모든 테스트 케이스가 성공하기 때문에 프로젝트 빌드는 통과된다.

빌드 결과는 자동으로 메일로 전송된다.

2.2. Pull Request를 해보자

이제, 오픈 소스 프로젝트의 묘미인 Pull Request에서 Travis CI가 어떻게 동작하는지 알아보자. 같이 하는 친구가 있다면, 친구의 저장소에 PR을 날려도 좋고, 혼자라면 본인의 저장소에 PR을 날려도 괜찮다.

우리는 나눗셈의 제수가 0이 되는 경우 `IllegalArgumentException`을 발생시킬 것이다. 이를 위해 소스 코드를 조금 수정하자.

public double divide(double a, double b) {
    if (b == 0.0d) {
        throw new IllegalArgumentException("divisor must not be zero.");
    }
    return a / b;
}
@Test
public void divide() {
    Calculator calculator = new Calculator();
    assertEquals(0.5d, calculator.divide(2, 4), DELTA);
    assertEquals(0.0d, calculator.divide(2, 0), DELTA);
}

물론 0으로 나눌 경우에 대한 에러 처리를 하지 않으므로 테스트 케이스는 실패할 것이다. 이는 인위적으로 빌드를 깨트릴 목적이므로 같이 해보자. PR을 날리기 위해 본인의 저장소에 푸쉬할 경우 Travis CI가 동작하여 빌드가 깨질 것이지만, 잠시만 무시하고 PR을 날리자.

Travis CI의 Pull Reqeusts 메뉴를 클릭하면, 방금 날린 PR의 테스트 케이스가 실패해서 빌드가 깨진 것을 볼 수 있다.

또한 GitHub 저장소의 Pull Request 게시글에서도 볼 수 있어 굳이 Travis CI 프로젝트 페이지에 들어가지 않더라도 빌드 성공 여부를 볼 수 있다.

빌드가 깨진 것을 확인했으니 다시 수정해서 PR을 날려보자. divide 메소드를 실행할 때 IllegalArgumentException을 catch 하자. 만약 IllegalArgumentException이 catch되지 않으면 테스트 케이스를 실패시킨다. 0으로 나눌 경우 IllegalArgumentException이 throw 되어야 하므로 이 테스트 케이스는 성공한다.

@Test
public void divide() {
    Calculator calculator = new Calculator();
    assertEquals(0.5d, calculator.divide(2, 4), DELTA);
    try {
        calculator.divide(2, 0);
        fail();
    } catch (IllegalArgumentException e) {
    }
}

테스트 케이스가 성공하도록 수정한 뒤 푸쉬하면 PR이 자동으로 업데이트 된다.

이제 모든 테스트 케이스가 성공해서 빌드가 통과된다.

마찬가지로 GitHub Pull Request 게시글에서도 빌드가 통과됬음을 알 수 있다. 프로젝트 관리자는 빌드 통과 여부를 바탕으로 머지 여부를 판단할 것이다.

2.3. Build Status 이미지 붙이기

마지막으로, 오픈 소스 프로젝트의 README에서 자주 보이는 빌드 상태 이미지를 붙여보자.

Travis CI 프로젝트 페이지의 이름 우측에 빌드 상태 이미지를 클릭하면 붙여넣기 쉽도록 링크를 제공한다.

복사해서 GitHub 저장소의 README.md의 적절한 위치에 추가하자.

이제 우리 저장소에도 멋진 빌드 상태 이미지가 추가되었다!

Hello World!

2019년 들어 시작한 프로젝트들 중 하나로 나만의 웹사이트를 만들고 있다. 2018년 1월 1일에 구매한 gihwan.kr 도메인을 잘 사용하지 못하고 거의 일년 간 방치하다가 이번에 가비아로 도메인 기관이전을 진행하면서 개인 웹사이트 구축을 같이 진행하였다. 포트폴리오 웹사이트 프로젝트와 블로그 프로젝트를 진행하고 있으며 포트폴리오 웹사이트는 Jekyll을 사용해서 Github Pages에서 호스팅하고, 블로그는 WordPress를 사용해서 Amazon Lightsail에서 호스팅하고 있다.

블로그를 구상할 때 꽤 많은 고민을 했었는데, 사용자가 많고 편리하지만 PHP 기반인 WordPress를 사용할지, 혹은 다른 유망한 프레임워크 기반의 CMS를 사용할지, 심지어 직접 만드는 것 혹은 가입형 블로그까지 고려해보았다. 그러나 결론적으로 블로그는 사이트를 만드는 것 보다 그 내용이 더 중요한 것이라 판단하고 제일 수월하고 편한 WordPress를 선택하였다.

하지만 이게 끝이 아니었다.

블로그를 선택하고 나니 호스팅이 문제가 되었다. 기존에는 닷홈의 무제한 웹호스팅 서비스를 사용하고 있었으나 무료인 만큼 속도도 느리고 그 무엇보다 HTTPS를 적용할 수 가 없어 대안을 찾아야만 했다. 처음에는 워드프레스 닷컴을 생각했으나 개인 도메인을 적용하기 위해선 업그레이드가 필수적인데, 1년 계약 시 $100 이상의 꽤 비싼 비용이 들었다. 아직까지는 그정도 비용을 투자할 만큼 매력이 없다 생각하여 다른 대안을 찾던 중 Amazon Lightsail을 발견하였다. 꽤 간단하게 WordPress 블로그를 생성할 수 있었으며, 그 무엇보다 요금이 1달에 $3.5 정도로 저렴하고 학교에서 AWS Educate 프로그램으로 $100 크레딧을 지원받을 수 있었다. 실제로 몇 번의 클릭 만으로 호스팅되는 것을 보며 Amazon Web Services의 위력을 다시 한 번 느낄 수 있었다.

결과적으로 이 블로그는 Amazon Lightsail에서 호스팅되며, Let’s Encrypt로 HTTPS 적용까지 완료하였다. 소문으로만 듣던 AWS를 직접 사용해보니 가격에 비해 생각보다 많이 쾌적하고, 편리하며, 많은 기능을 지원한다. 물론 이제 첫 걸음이고 더 큰 웹사이트가 되어 업그레이드 할 때 비용 문제가 다시 발생할 수 있겠지만, 일단 지금은 만족이다.