이더넷(Ethernet)이란 무엇인가?   

 

 데이터 링크 계층은 네트워크 장비 간에 신호를 주고 받는 규칙을 정하는 계층으로, 랜에서 데이터를 정상적으로 주고받기 위해 필요한 계층이다. 그 규칙들 중 일반적으로 많이 사용되는 규칙이 이더넷(Ethernet)이다. 즉, 랜에서 적용되는 규칙이다.

 

 

 

 

 이더넷은 허브와 같은 장비에 연결된 컴퓨터와 데이터를 주고 받을 때 사용한다. 하지만 허브는 전기 신호를 전달받을 포트뿐만 아니라 나머지 포트에도 전달한다는 문제점이 있다. 관계없는 다른 컴퓨터들도 데이터를 받으면 곤란한 상황이 발생할 수 있다.

 

 이러한 경우를 대비해 규칙을 정해둔다. 데이터에 목적지 정보를 추가해서 보내 목적지 이외의 컴퓨터는 데이터를 받더라도 무시하도록 말이다. 

 

 

 

 

 또한, 컴퓨터 여러 대가 동시에 데이터를 보내면 데이터들이 서로 부딪히는 충돌(collision)이 발생할 수 있다.

 

 

 

 이더넷은 데이터를 보내는 시점을 늦춰서 충돌을 방지하기 위한 구조로 설계되어 있다.  

 

 

 이러한 기법을 CSMA/CD라고 하는데 정의는 다음과 같다.

 

  • CS: 데이터를 보내려고 하는 컴퓨터가 케이블에 신호가 흐르고 있는지 아닌지를 확인하는 규칙
  • MA: 케이블에 데이터가 흐르고 있지 않다면 데이터를 보내도 좋다는 규칙
  • CD: 충돌이 발생하고 있는지를 확인하는 규칙

 하지만, 스위치(Switch)라는 네트워크 장비가 등장하면서 CSMA/CD는 거의 사용하지 않게 되었다. 

 


 

    MAC 주소란 무엇인가?   

 

 랜 카드는 비트열(0과 1)을 전기 신호로 변환한다. 이러한 랜 카드에는 MAC 주소라는 번호가 정해져 있는데, 이는 제조할 때 새겨지기 때문에 물리 주소라고 불리고 전 세계에서 유일한 번호로 할당되어 있다. MAC 주소는 48비트(6 바이트) 숫자로 구성되어 있으며, 그 중 앞 쪽 24비트는 랜 카드를 만든 제조사 번호이고 뒤 쪽 24비트는 제조사가 랜 카드에 붙인 일련 번호이다. 앞, 뒤쪽 모두 정해진 규칙이 있기 때문에 중복되지 않는다. 

 

  네트워크 통신에서 송신할 때에는 OSI 모델이나 TCP/IP 모델에서 필요한 정보를 헤더에 담아 데이터에 붙여나가는 작업인 캡슐화를 진행한다. OSI에서는 데이터 링크 계층, TCP/IP에서는 네트워크 계층에 해당하는데, 이 계층에서 이더넷 헤더와 트레일러를 붙이게 된다. 

 

 이더넷 헤더는 목적지의 MAC 주소(6 바이트), 출발지의 MAC 주소(6 바이트), 유형(2 바이트) 총 14바이트로 구성되어 있다. 

여기서 유형은 이더넷으로 전송되는 상위 계층 프로토콜의 종류를 나타낸다. 

 

 

 그리고 트레일러FCS(Frame Check Sequence)라고도 하는데, 데이터 전송 도중에 오류가 발생하는지 확인하는 용도로 사용한다. 

 

 이처럼 이더넷 헤더와 트레일러가 추가된 데이터를 프레임이라고 한다. 이 프레임은 네트워크를 통해 전송된다. 

 

 

 


 

    MAC 주소를 통한 프레임 전송 과정   

 

 

 아래 그림과 같이 컴퓨터 A에서 컴퓨터 B로 데이터 전송한다고 가정하면 이더넷 헤더에 목적지인 컴퓨터 B의 MAC 주소와 근원지인 컴퓨터 A의 MAC 주소 정보를 담는다. 그 후에 데이터에 이더넷 헤더와 트레일러를 추가하는 캡슐화 과정을 거쳐 프레임을 만들고 물리 계층에서 이 프레임 비트열을 전기 신호로 변환하여 네트워크를 통해 전송한다. 

 

 허브를 예로 들면 컴퓨터 A가 보낸 데이터를 컴퓨터 B~D에 다 전송하지만 컴퓨터 C, D는 이더넷 헤더에 붙어 있는 목적지 MAC 주소와 자신의 MAC 주소가 다르기 때문에 데이터를 파기한다. 컴퓨터 B는 목적지 MAC 주소와 자신의 MAC 주소가 일치하므로 데이터를 파기하지 않고 역캡슐화를 진행한다. 컴퓨터 B는 역캡슐화를 한 다음에 데이터를 수신한다.

 

 

 

 

 

 

 컴퓨터 A와 컴퓨터 C 동시에 컴퓨터 B로 데이터를 전송한다면 충돌이 발생할 것이다. 충돌을 방지하기 위해 CSMA/CD 규칙을 사용할 수 있다.

 


 

   스위치의 구조    

 

 스위치는 데이터 링크 계층에서 동작하며 레이어 2 스위치 또는 스위칭 허브라고 불린다. 겉모습만 봐서는 허브와 구별하기 힘들지만 허브와 다르게 데이터 충돌을 방지할 수 있다.

 

 

출처: 위키피디아

 

 

 

 스위치 내부에는 MAC 주소 테이블(Mac Address Table)이 존재하는데 이 MAC 주소 테이블은 스위치의 포트 번호와 해당 포트에 연결되어 있는 컴퓨터의 MAC 주소가 등록되는 데이터베이스이다. 

 

 맨 처음 전원을 킨 스위치 MAC 주소 테이블에는 아무것도 등록되어 있지 않지만 MAC 주소가 추가된 프레임이라는 데이터가 전송되면 MAC 주소 테이블에 포트 번호와 함께 추가가 된다. 만약 이미 등록되어 있는 MAC 주소라면 건너 뛴다. 이를 MAC 주소 학습 기능이라고 한다. 

 

 하지만 스위치도 피할 수 없는 것이 있다. MAC 주소 테이블에 MAC 주소가 등록되어 있지 않다면 허브와 같이 등록되어 있지 않은 포트 번호에 모두 전송된다는 것이다. 이를 플러딩(Flooding)이라고 부른다. 

 

 

 만약 MAC 주소 테이블에 컴퓨터 B의 MAC 주소가 등록되어 있고 컴퓨터 B로 데이터를 전송한다고 가정한다면 목적지 컴퓨터인 컴퓨터 B로만 전송하게 된다. 이를 MAC 주소 필터링이라고 한다. 즉, 불필요한 데이터를 네트워크에 전송하지 않게 되는 것이다. 

 

 

 그렇다면 지금의 MAC 주소 테이블 상태에서 만약 컴퓨터 A에서 컴퓨터 C로 데이터를 보낸다고 가정하면 어떻게 될까? MAC 주소에 해당 포트 번호의 목적지 MAC 주소가 없기 때문에 다시 플러딩이 발생한다.  

 

 



   데이터가 케이블에서 충돌하지 않는 구조   

 

 통신 방식에는 전이중 통신 방식과 반이중 통신 방식이 있다. 전이중 통신 방식은 데이터의 송, 수신을 동시에 통신하는 방식이고 반이중 통신 방식은 회선 하나로 송신과 수신을 번갈아가면서 통신하는 방식이다. 

 

 아래 그림과 같이 컴퓨터 1과 컴퓨터 2를 직접 랜 케이블로 연결한다면 선을 네 쌍을 사용하기 때문에 전이중 통신 방식이 된다. 

 

전이중 방식

 

 반면 허브 내부에는 송, 수신이 나누어져 있지 않기 때문에 컴퓨터 A와 B를 허브로 연결하면 동시에 데이터를 보낼 때 충돌이 난다. 이처럼 허브를 사용하면 회선 하나를 송신과 수신이 번갈아가면서 사용하는 반이중 통신 방식을 사용하게 된다. 

 

 

 스위치는 충돌이 일어나지 않는 구조로 되어 있기 때문에 전이중 통신 방식으로 데이터를 주고 받을 수 있다. 이처럼 허브를 사용하면 충돌로 인한 네트워크 지연이 발생하기에 최근에는 네트워크로 스위치를 사용한다. 

 

 

 

 


 

   충돌 도메인   

 

 충돌 도메인(Collision damain)은 충돌이 발생할 때 그 영향이 미치는 범위를 말한다. 허브와 스위치를 예로 들면 허브는 충돌의 영향이 모든 컴퓨터에 미치고 스위치는 전이중 통신 방식이며 접속되어 있는 모든 컴퓨터 영향을 미치지 않기에 충돌이 발생하지 않고 충돌 도메인의 범위도 컴퓨터 하나하나로 좁아진다. 

 

 

 

    (1)  그레이들(gradle) 버전 확인 및 변경   

 

  그레이들(gradle)의 버전을 확인하기 위해  [gradle]-[wrapper] 폴더의 gradle-wrapper.properties 파일을 찾아가 빨간색으로 표시된 부분을 확인한다. 

 

 

 만약 그레이들의 버전을 변경해야 한다면 터미널 창에서 다음 명령어를 입력해 준다.

 

    gradlew wrapper --gradle-version [버전명]

 


 

    (2) 깃과 깃허브 연동    

 

 먼저 윈도우에서는 ctrl + shift + A, 맥에서는 command + shift + A를 사용해 Action 검색창을 열어 share project on github를 검색한다. 

 

 

 해당 Action을 선택하면 깃허브 로그인 화면이 나온다. 본인의 깃허브 계정을 로그인한다. 

 

 

 로그인에 성공하면 다음과 같은 화면이 뜨는데 Repository name을 수정하고 share 버튼을 누른다.

 

 

 로그인에 성공하면 다음과 같은 화면이 뜨는데 Repository name을 수정하고 share 버튼을 누른다. 그 후에 .idea 폴더를 제외하고 Commit Message를 작성한 뒤 Add 버튼을 누른다. 

 

 

 로그인에 성공하면 다음과 같은 화면이 뜨는데 Repository name을 수정하고 share 버튼을 누른다. 그 후에 .idea 폴더를 제외하고 Commit Message를 작성한 뒤 Add 버튼을 누른다. 

 

 만약 다음과 같은 화면이 나오는데 여기서는 .gitignore이라는 파일을 추가할 것인지에 대한 것이므로 cancel을 눌러주고 위에서 다시 .gitignore 파일을 체크 해제를 한 뒤 커밋을 하면 된다. 

 

 

 여기까지 진행되었으면 github 레포지토리가 생성된 것을 확인할 수 있다.

 

 


 

    (4) .gitignore 세팅    

 

 깃허브와 동기화는 되었으면 이제 처음 커밋했을 때 제외했던 .idea 폴더를 앞으로의 모든 커밋 대상에서 제외되도록 처리를 해야한다. 만약 .gitignore가 생성되지 않았다면 플러그인에서 .gitignore를 지원 받아야 한다. 

 

 플러그인에 대한 정보는 여기서 참조하면 된다.

 

2020/09/16 - [IDE/IntelliJ] - 2. 플러그인(plugin)

 

2. 플러그인(plugin)

플러그인 인텔리제이에서 특정 기능에 대한 지원이 없으면 플러그인(plugin)에서 지원을 받는다. 예를 들어, .gitignore 파일에 대해 지원받고 싶다면 .ignore 플러그인에서 지원을 받으면 된다.  먼저

almotjalal.tistory.com

 

 

 윈도우는 Ctrl + Shift + A, 맥은  Command + Shift + A를 사용해 [Actions]탭 검색창을 열어 plugins를 검색하고 선택한다.

 

 

 

 [Marketplace]탭은 설치 가능한 플러그인 목록을 보여주며, [Installed] 탭은 이미 설치된 플러그인 목록을 나타낸다. [Marketplace]탭을 선택하고 .ignore을 검색하고 [install]을 클릭하여 설치한다. 

 

 

 

 설치가 완료 되었으면 인텔리제이를 다시 시작해야만 설치한 플러그인이 적용되므로 재시작을 한다. 

 

 

 

 재시작을 하면 프로젝트 왼쪽 위의 프로젝트 이름을 선택한 뒤, 마우스 오른쪽 버튼을 누르거나 단축키를 눌러 생성 목록을 연다. 단축키는 윈도우 Alt + Insert, 맥 Command + N이다. 생성 목록 아래에 [.ignore file], [gitignore file(git)]을 차례로 선택해 .gitignore 파일을 생성한다. 

 

 

    (1)  참고 사항   

 

  인텔리제이(IntelliJ)에는 이클립스(Eclipse)의 워크 스페이스와 같은 개념이 없고 프로젝트와 모듈의 개념만 있다. 즉, 모든 프로젝트를 한 번에 불러올 수 없으므로 한 화면에서는 하나의 프로젝트만 열린다. 

 


 

    (2) 프로젝트 생성    

 

 아래 그림에서 빨간 색으로 표시된 New Project를 선택한다. 

 

 

 왼쪽 목록에서 그레이들(Gradle)을 선택해주고 Next 버튼을 누른다. 

 

 

 

 다음은 프로젝트에 해당하는 이름을 적어준다. Name 항목과 ArtifactId 항목은 같은 값으로 입력이 된다. 다 입력 되었으면 Finish 버튼을 누른다. 

 

 


 

    (3) 그레이들(Gradle) 프로젝트를 스프링 부트 프로젝트로 변경    

 

 인텔리제이에서 build.gradle 파일을 열어보면 다음 화면과 같다.

 

 

 코드를 자세히 살펴보면 아직 자바 개발에 가장 기초적인 설정만 되어 있는 상태이다. 이제 여기에 스프링 부트에 필요한 설정들을 하나씩 추가해야 한다.

 

plugins {
    id 'java'
}

group 'com.daldalhada.book'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

 

 

 코드를 자세히 살펴보면 아직 자바 개발에 가장 기초적인 설정만 되어 있는 상태이다. 이제 여기에 스프링 부트에 필요한 설정들을 하나씩 추가해야 한다.

 

 물론 스프링 이니셜라이저(start.spring.io/)를 통해 진행할 수 있지만 bulid.gradle 파일의 코드들이 각각 무슨 역할을 하는지, 이니셜라이저 외에 추가로 의존성 추가가 필요하면 어떻게 해야 하는지에 대해 알아보기 위해 이니셜라이저를 쓰지 않았다.

 

 먼저 build.gradle 파일 맨 위에 위치할 코드는 다음과 같다.

buildscript {
    ext {
        springBootVersion = '2.1.7.RELEASE'
    }
    repositories {
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

 위의 코드는 이 프로젝트의 플러그인 의존성 관리를 위한 설정이다. ext라는 키워드는 build.gradle 파일에서 사용하는 전역변수를 설정하겠다는 의미이다. 즉, 위에 코드에서는 spring-boot-gradle-plugin이라는 스프링 부트 그레이들 플러그인의 2.1.7.RELEASE를 의존성으로 받겠다는 의미이다. 

 

 다음은 앞서 선언한 플러그인 의존성들을 적용할 것인지를 결정하는 코드이다.

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

 io.spring.dependency-management 플러그인은 스프링 부트의 의존성들을 관리해주는 플러그인이라 꼭 추가해야만 한다. 위의 3개를 포함하여 총 4개의 플러그인은 자바와 스프링 부트를 사용하기 위해 필수이므로 항상 추가해야 한다. 

 

repositories {
    mavenCentral()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

 

 repositories는 각종 의존성(라이브러리)들을 어떤 원격 저장소에서 받을지를 정한다. mavenCentral을 많이 사용하지만 최근에는 라이브러리 업로드 난이도 때문에 jcenter도 많이 사용한다고 한다. 

 

 mevenCentral은 이전부터 많이 사용하는 저장소지만, 본인이 만든 라이브러리를 업로드하기 위해서는 정말 많은 과정과 설정이 필요하다. 그러다보니 개발자들이 직접 만든 라이브러리를 업로드 하는 것이 힘들어 점점 공유가 안되는 상황이 발생한다. 

 

 최근에 나온 jcenter는 이런 문제점을 개선하여 라이브러리 업로드를 간단하게 할 수 있다. 또한, jcenter에 라이브러리를 업로드 하면 mavenCentral에도 업로드 될 수 있도록 자동화 할 수 있다. 

 

 여기서는 mavenCentral과 jcenter 둘 다 등록해서 사용할 것이다. 

 

 dependencies는 프로젝트 개발에 필요한 의존성들을 선언하는 곳이다. compile 메소드 안에 라이브러리의 이름의 앞부분만 추가한 뒤 자동완성(ctrl + space)을 사용하면 라이브러리의 목록을 볼 수 있다. 의존성 코드를 작성할 때 주의해야 할 점은 버전을 명시해야 하지 않아야 한다. 그래야만 맨 위에 작성한 classpath 메소드의 ${springBootVersion}의 버전을 따라가며 버전 충돌 문제가 발생하지 않는다. 

 

 지금까지의 최종 작성된 코드는 다음과 같다.

 

buildscript {
    ext {
        springBootVersion = '2.1.7.RELEASE'
    }
    repositories {
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group 'com.daldalhada.book'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

 

 

 맨 오른쪽에서 Gradle 버튼을 클릭해서 의존성을 확인한다.