본문 바로가기

Study/개발일지

[백엔드온라인TIL] java 학습 45일차

docker 

 

터미널에서 컨테이너 생성 

 

docker run -p 5432:5432 -e POSTGRES_PASSWORD=pass -e POSTGRES_USER=rose -e POSTGRES_DB=messenger --name postgres_spr -d postgres

 

 

Windows Subsystem for Linux의 동작 원리

가상머신을 사용하지 않고도, 윈도우에서 리눅스가 네이티브하게 동작한다니 신기하지 않나요? WSL은 윈도우의 가상화 기술을 Hyper-V 아키텍처를 기반으로 동작합니다. 하지만 이 구조는 윈도우 내부에 잘 감춰져있고 윈도우와 통합도 잘 되어있기 때문에, 가상 머신을 사용하는 느낌은 받을 수 없습니다. 가상머신 부팅이 몇 분 정도가 걸린다면, WSL 리눅스는 몇 초 정도면 바로 사용할 수 있습니다.

WSL2의 아키텍처

마이크로소프트에서는 윈도우와 긴밀한 통합을 위해서 WSL2를 위한 리눅스 커널을 직접 개발하고 있습니다.

WSL 머신에서 uname 명령어를 실행해서 커널 버전을 출력해봅니다. 이를 통해 리눅스 커널 5.15 버전대를 기반으로 만들어진 WSL 전용 커널이 사용되는 것을 확인할 수 있습니다.

$ uname -r
5.15.90.1-microsoft-standard-WSL2

WSL 리눅스 커널이 별도로 개발되고 있습니다만, 기존 리눅스 배포판들을 그대로 가져와 사용할 수 있고 동작도 기존 리눅스 커널과 거의 차이가 없습니다. 또한 WSL에서는 다수의 리눅스 머신을 설치할 수 있는데, 이 리눅스 머신들은 모두 WSL의 리눅스 커널을 기반으로 동작합니다.

이 글에서는 편의상 WSL 머신이라고 표현합니다만, WSL은 어떤 면에선 가상 머신처럼 보이고, 어떤 면에서는 시스템 컨테이너처럼 보이기도 합니다. 크게 중요한 건 아닙니다. 윈도우에서 명령어 몇 개로 리눅스를 사용할 수 있다는 게 주목할만한 일입니다.

그럼 여기서부터는 직접 WSL을 설치하고 사용하는 방법을 소개하겠습니다.

윈도우 10 홈 에디션에서 WSL을 사용할 수 있나요?

WSL2는 Hyper-V를 기반으로 동작합니다만, 윈도오 10 홈 에디션에서는 Hyepr-V를 사용할 수 없습니다. 하지만 좀 더 정확히 이야기하면 WSL2의 요구사항은 Hyper-V 아키텍처로, 윈도우 10 프로페셔널 이상 에디션에서 제공하는 Hyper-V 추가 기능과는 별개입니다. 즉, 윈도우 10 홈 에디션에서도 WSL2를 사용할 수 있습니다. 더 자세한 내용은 WSL 공식 FAQ 문서를 참고해주세요.

WSL2 설치 가능 여부 확인(윈도우 10)

WSL을 설치하려면 윈도우 10의 20H1 이상 버전이어야합니다. 이 글은 윈도우 10을 기준으로 작성하였습니다만, 윈도우 11에서도 같은 과정으로 설치할 수 있습니다. 윈도우 11을 사용중이라면 버전 확인을 하지 않아도 괜찮습니다.

설치 전에 먼저 Windows + S 키를 클릭하고 PC 정보(설정)를 검색해서 실행합니다.

PC 정보 설정을 검색하고 실행합니다

오른쪽 정보 페이지에서 스크롤을 내리면 Windows 사양을 확인할 수 있습니다. 여기서 버전이 20H1, 20H2, 21H1 혹은 그보다 높은 버전인지 확인합니다.

Windows 사양에서 현재 버전을 확인합니다

이보다 낮은 버전을 사용중이라면 먼저 윈도우 업데이트 설정을 열어 최신 버전으로 업데이트해주시기 바랍니다.

윈도우에 WSL2 설치하는 방법(최신) WSL2를 설치하기 위해서는 가상 터미널을 사용해야합니다. 윈도우 터미널 사용을 추천합니다. 따로 설치가 되어있지 않다면 PowerShell을 사용해도 무방하지만 윈도우 터미널에서는 WSL2 셸을 바로 실행하는 것도 가능하기 때문에 미리 설치해두는 것을 강력 추천합니다.

먼저 가상 터미널을 관리자 권한으로 실행해주세요. Windowsn + S 키로 윈도우 터미널이나 PowerShell을 검색한 후 오른쪽 버튼을 눌러 ’관리자로 실행’을 선택합니다.

PowerShell을 검색해서 관리자 권한으로 실행합니다

wsl 명령어로 WSL2 설치하는 방법(최신)

윈도우 10 버전 2004(빌드 19041 이상) 이상이나 윈도우 11에서는 wsl 명령어 하나로 WSL2를 설치할 수 있습니다.

$ wsl --install

설치가 끝나고 다음 명령어를 실행해, WSL 버전 기본값을 2로 변경해줍니다.

$ wsl --set-default-version 2

문제가 없었다면, 바로 마이크로소프트 스토어에서 리눅스 설치 절로 넘어가주세요.

윈도우에 WSL2 수동 설치하는 방법(예전 방법)

 

wsl 명령어가 없거나, 정상적으로 설치가 되지 않는다면 수동으로 한 단계 씩 WSL2를 설치해봅니다.

DISM으로 WSL 관련 기능 활성화

DISM(배포 이미지 서비스 및 관리) 명령어로 Microsoft-Windows-Subsystem-Linux 기능을 활성화합니다.

$ dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
버전: 10.0.19041.844

이미지 버전: 10.0.19043.928
기능을 사용하도록 설정하는 중
[==========================100.0%==========================]

다음으로 dism 명령어로 VirtualMachinePlatform 기능을 활성화합니다.

$ dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
배포 이미지 서비스 및 관리 도구

이미지 버전: 10.0.19043.928

기능을 사용하도록 설정하는 중
[==========================100.0%==========================]
작업을 완료했습니다.

작업이 정상적으로 완료되었는지, 메시지를 꼭 확인해주세요. 터미널이 관리자 권한이 아닌 경우 작업이 실패합니다. 작업이 정상 완료되었다면 이 시점에 재부팅을 한 번 해줍니다.

WSL2 Linux 커널 업데이트

다음으로 WSL2 Linux 커널 업데이트를 진행해야합니다. 첫 번째로 링크는 마이크로소프트의 공식 WSL2 설치 가이드이며, 두 번째 링크는 이 문서에 포함된 wsl_update_x64.msi 파일입니다. 아래 파일을 다운로드 받아 안내에 따라 설치를 진행합니다.

WSL2 Linux 커널 업데이트 패키지를 설치합니다

윈도우 터미널을 열고, 다음 명령어를 실행해, 기본적으로 사용할 WSL 버전을 2로 변경해줍니다.

$ wsl --set-default-version 2

마지막으로 wsl 업데이트를 진행합니다.

$ wsl --update

마이크로소프트 스토어에서 우분투 리눅스 설치

다음으로 WSL에서 사용할 리눅스 배포판을 설치해야합니다. 리눅스 배포판을 설치하는 방법은 두 가지가 있습니다. 하나는 마이크로소프트 스토어에 업로드 되어있는 리눅스 배포판을 설치하는 방법이고, 다른 하나는 직접 리눅스 배포판 이미지를 구해서 WSL로 임포트하는 방법입니다. 여기서는 첫 번째 방법으로 우분투 리눅스 배포판을 설치해보겠습니다.

마이크로소프트 스토어(Microsoft Store) 앱을 열고 Ubuntu를 검색합니다.

Microsoft Store에서 Ubuntu 앱을 검색합니다

WSL2에서는 다양한 리눅스 배포판을 사용할 수 있습니다. 여기서는 가장 많이 사용되는 리눅스 배포판인 Ubuntu를 설치해보겠습니다(Ubuntu는 무료로 사용할 수 있지만, 리눅스 배포판에 따라서 유료인 경우도 있습니다). 맨 앞의 패키지를 선택하고 상세 페이지에서 설치를 진행합니다.

Ubuntu 앱을 설치합니다

설치가 끝나고 앱이 실행되면 터미널이 하나 열리고 설치가 자동적으로 진행됩니다. 이 창을 끄지 말고 기다려주세요. 앱이 자동으로 실행되지 않는다면 Windows +S 키를 입력하고 Ubuntu를 검색해서 실행해줍니다.

Ubuntu 앱을 검색해서 실행합니다

처음에 ’Installing. this may take few minutes…’이라는 메시지가 나옵니다. 조금 시간이 지나면 에서 사용할 사용자 이름과 패스워드를 지정하는 입력창이 나타납니다. 사용하고자 하는 사용자 이름과 패스워드를 입력하면 passwd로 패스워드가 업데이트됩니다.

Ubuntu 리눅스의 초기 셋업을 진행합니다

다시 터미널을 실행해주세요(이 때는 관리자 모드를 사용하지 않아도 됩니다). 이제 WSL을 관리하기 위한 wsl 명령어를 사용할 수 있습니다. wsl -l -v로 현재 설치된 리눅스를 확인해봅니다.

$ wsl -l -v
NAME      STATE           VERSION
* Ubuntu    Running         2

앞의 *는 디폴트 머신을 의미합니다. 여기서 버전 컬럼은 WSL의 버전을 의미합니다. 2가 출력된다면 그대로 사용하면 됩니다. 만약 버전이 1이라고 나온다면 다음 명령을 실행해줍니다.

$ wsl --set-version Ubuntu 2
변환이 진행 중입니다. 몇 분 정도 걸릴 수 있습니다...
WSL 2와의 주요 차이점에 대한 자세한 내용은 https://aka.ms/wsl2를 참조하세요
변환이 완료되었습니다.

실행 후 ’변환이 완료되었습니다’라는 출력 결과를 꼭 확인해주세요. 다시 wsl -l -v 명령어로 확인해봅니다. 변환이 잘 되었는지 확인해보겠습니다.

$ wsl -l -v
NAME      STATE           VERSION
* Ubuntu    Running         2

WSL을 사용할 때 하나 알아두어야 하는 점은, WSL이 Hyper-V 기반의 경량화된 리눅스 머신이라는 점입니다. 따라서 WSL 머신은 상태를 가집니다. 처음 wsl 명령어를 실행하면 머신이 Running 상태가 됩니다.

머신을 종료할 때는 -t 옵션을 사용합니다. Ubuntu 머신을 종료하고 상태를 확인해보겠습니다.

$ wsl -t Ubuntu
$ wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Stopped         2

Running 상태에서 Stopped 상태가 되었습니다. WSL 머신의 시작/종료/재부팅 등 기본적인 조작법에 대해서는 다음 글에서 더 자세히 소개합니다.

여기까지 WSL2 및 Ubuntu 설치를 마쳤습니다.

WSL2로 Ubuntu 리눅스 맛보기

 

이제 WSL2로 리눅스를 활용하면 됩니다. 먼저 wsl 명령어로 Ubuntu 머신에 명령을 실행해보겠습니다. 앞서 작업하던 터미널에서 아래 명령어를 실행합니다.

$ wsl cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.2 LTS"

cat은 리눅스 명령어입니다. wsl 다음에 리눅스 명령어를 입력하면 기본 WSL 리눅스에서 명령어가 실행됩니다. 여기서는 현재 사용중인 Ubuntu 버전이 출력됩니다. 현재 설치된 Ubuntu는 Ubuntu 20.04.2 LTS 버전인 것을 확인할 수 있습니다.

다음과 같이 명령어로 Bash 셸을 실행하는 것도 가능합니다. 그냥 wsl만 실행해도 기본 WSL 리눅스에서 셸이 실행됩니다.

$ wsl
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

## 저자 주: 여기서부터 WSL2 리눅스 셸 프롬프트입니다.
lainy@DESKTOP-DSP22P:/mnt/c/Users/lainy$

이 내용을 자세히 보면 디렉터리가 /mnt/c/Users/lainy로 실행됩니다. 즉, Windows 10 메인 디스크가 리눅스와 연결되어있으며, WSL2 Linux에서 Windows의 파일을 사용하는 것도 가능합니다.

여기서는 WSL 리눅스가 하나만 설치되어있는 상황입니다만, 여러 리눅스가 설치되어있다면 -d 옵션으로 특정한 리눅스를 지정해 줄 수 있습니다. 아래의 사용 팁을 참고해주세요.

서비스 관리나 네트워크 환경 등 약간의 차이는 있지만 WSL 리눅스도 다른 리눅스와 사용방법은 같습니다. 특히 셸에서는 리눅스 커맨드라인 환경을 그대로 사용할 수 있습니다. 디렉터리 관련 명령어부터, 파일 출력 명령어, 시스템 관련 명령어 등 리눅스 주요 명령어들은 다음 글을 참고해주세요.

WSL2 사용 팁들

여기까지 WSL 리눅스를 설치했습니다. 여기서부터는 WSL2를 사용할 때 알아두면 유용한 팁들을 몇 가지 더 소개해보고자 합니다.

팁: Windows Terminal로 WSL 리눅스 셸 바로 사용하기

앞서 짧게 언급 했습니다만, Windows Terminal은 WSL2도 기본적으로 지원하고 있습니다. 따라서 WSL2로 리눅스 배포판을 설치하고 나면, Windows Terminal에서 이 리눅스를 바로 사용하는 게 가능합니다.

Windows Terminal을 설치하고 실행합니다. 탭 바 오른쪽의 아래쪽 화살표를 누르면, WSL2로 설치된 Ubuntu가 보입니다.

이제 Windows Terminal에서 Ubuntu를 사용할 수 있습니다

Ubuntu를 선택하면, WSL2로 설치된 Ubuntu 셸이 바로 실행됩니다.

-- mybatis 는 테스트 환경말고 

별도의 프로젝트 생성하여 테스트 할것 

 

package com.test.api.domain;

public class Test {

    private String column1;
    private String column2;

    public String getColumn1() {
        return column1;
    }

    public String getColumn2() {
        return column2;
    }

    public void setColumn1(String column1) {
        this.column1 = column1;
    }

    public void setColumn2(String column2) {
        this.column2 = column2;
    }
}

 

[lombok 사용]

  • 사용 전 인텔리제이 초기 설정
  • File > Settings(preference) > Build, Execution, Deployment > Compiler > Annotation Processors

package com.test.api.domain;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Test {

    private String column1;
    private String column2;
}

2. Mapper Interface 생성

  • Mapper 설정 파일(xml)에 있는 SQL 쿼리문을 호출하기 위한 인터페이스를 생성합니다.
  • DAO 대신 @Mapper 어노테이션을 사용합니다. (mybatis 3.0 이상)
  • @Mapper 어노테이션을 사용하면 빈으로 등록되며 Service단에서 Autowired 하여 사용할 수 있습니다.
  • 메소드 명은 Mapper xml 파일의 id와 맞춰줘야 합니다.
  • @Mapper 가 아닌 @MapperScan 어노테이션을 이용할 수도 있습니다. 
  • com/test/api/mapper/TestMapper.java
package com.test.api.mapper;

import com.test.api.domain.Test;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface TestMapper {
    Test test() throws Exception;
}

 

[@MapperScan 사용 시]

  • DB 설정 클래스 파일에 @MapperScan(value="매퍼 인터페이스 경로")를 추가해 줍니다.
package com.test.api.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@Configuration
@PropertySource("classpath:/application.properties")
@MapperScan(value="com.test.api.mapper")
public class DBConfig {

    private final ApplicationContext applicationContext;

    @Autowired
    DBConfig(ApplicationContext applicationContext){
        this.applicationContext = applicationContext;
    }

    @Bean
    @ConfigurationProperties(prefix="spring.datasource.hikari")
    public HikariConfig hikariConfig() {
        return new HikariConfig();
    }

    @Bean
    public DataSource dataSource() throws Exception {
        DataSource dataSource = new HikariDataSource(hikariConfig());
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTypeAliasesPackage("com.test.api.domain");
        sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:/mapper/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

 

[Mapper Interface]

package com.test.api.mapper;

import com.test.api.domain.Test;
import org.mybatis.spring.annotation.MapperScan;

@Component
@MapperScan
public interface TestMapper {
    Test test() throws Exception;
}

3. Mapper xml 생성

  • 쿼리를 작성할 매퍼 xml을 설정 파일에 지정한 경로로 생성합니다.
  • mapper namespace 값을 Mapper Interface와 맞춰 줍니다.
  • id는 Mapper Interface 클래스에서 선언한 메서드의 이름과 동일하게 맞춰줍니다.
  • resources/mapper/TestMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.api.mapper.TestMapper">

    <select id="test" parameterType="map" resultType="Test">
        SELECT 1 AS 'column1', 2 AS 'column2'
    </select>

</mapper>

4. 서비스 생성

  • Mapper Interface를 주입받아 사용할 서비스를 생성합니다.
  • com/test/api/service/TestService.java
package com.test.api.service;

import com.test.api.domain.Test;
import com.test.api.mapper.TestMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    private final TestMapper testMapper;

    @Autowired
    public TestService(TestMapper testMapper){
        this.testMapper = testMapper;
    }

    public Test test() throws Exception {
        return testMapper.test();
    }
}

5. 컨트롤러 생성

  • 테스트 및 서비스를 사용하기 위해 컨트롤러를 생성해줍니다.
  • com/test/api/controller/TestController.java
package com.test.api.controller;

import com.test.api.domain.Test;
import com.test.api.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    private final TestService testService;

    @Autowired
    public TestController(TestService testService){
        this.testService = testService;
    }

    @GetMapping(value = "/test")
    public Test test() throws Exception {
        return testService.test();
    }

}
728x90