ASP.Net Core 3.0 MVC 프로젝트에서 Material Design Compoent를 사용하는 방법에 대해 알아봅니다.

기본적인 솔루션 및 패키지 구성은 이 글을 참고해 주세요.

 

 

 

1. package.json 수정

 

Material degisn을 사용하기 위해 NPM에서 "material-components-web"을 설치해야 합니다.

pakckage.json의 내용을 다음과 같이 변경합니다.

{
  "version": "1.0.0",
  "name": "asp.net",
  "private": true,
  "devDependencies": {
    "gulp": "4.0.2",
    "del": "5.1.0",
    "material-components-web": "4.0.0"
  }
}

이후 package.json 파일을 우클릭 후 패키지 복원을 클릭해 주세요.

 

 

 

2. css 생성

 

MDC을 사용할 CSS파일을 만듭니다.

 

"Styles"폴더를 생성하고 그 안에 "Home.css"파일을 생성한 후 다음과 같이 코딩합니다.

@import "../node_modules/material-components-web/dist/material-components-web.css";
body {
    margin: 0px;
}

 

 

 

3. gulpfile.js 수정

 

설치한 MDCWeb 패키지와 생성한 CSS파일을 빌드시 wwwroot 폴더로 복사해주는 코드를 작성합니다.

 

gulp.file.js를 다음과 같이 수정합니다.

/// <binding AfterBuild='default' Clean='clean' />
var gulp = require('gulp');
var del = require('del');
var paths = {
    scripts: ['scripts/**/*.js'],
    styles: ['styles/**/*'],
    MDCWeb: ['./node_modules/material-components-web/**/*'],
};
gulp.task('clean', function () {
    return del(['wwwroot/scripts/**/*', 'wwwroot/node_modules/**/*']);
});
gulp.task('default', function () {
    gulp.src(paths.scripts).pipe(gulp.dest('wwwroot/scripts'));
    gulp.src(paths.styles).pipe(gulp.dest('wwwroot/styles'));
    gulp.src(paths.MDCWeb).pipe(gulp.dest('wwwroot/node_modules/material-components-web'));
});

 

 

 

4. 페이지 수정.

 

예시에서는 기본 페이지를 사용합니다.

 

index.cshtml을 다음과 같이 수정합니다.

@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="~/styles/home.css">
    <title>Index</title>
</head>
<body>
    <header class=" mdc-top-app-bar">
        <div class="mdc-top-app-bar__row">
            <section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-start">
                <button class="mdc-icon-button material-icons mdc-top-app-bar__navigation-icon--unbounded">menu</button><span class="mdc-top-app-bar__title">San Francisco, CA</span>
            </section>
            <section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-end">
                <button class="mdc-icon-button material-icons mdc-top-app-bar__action-item--unbounded" aria-label="Download">file_download</button>
                <button class="mdc-icon-button material-icons mdc-top-app-bar__action-item--unbounded" aria-label="Print this page">print</button>
                <button class="mdc-icon-button material-icons mdc-top-app-bar__action-item--unbounded" aria-label="Bookmark this page">bookmark</button>
            </section>
        </div>
    </header>
    <script src="~/scripts/home.js"></script>
</body>
</html>

 

 

 

 

5. 빌드

 

이제 빌드 후 실행해봅시다.

 

다음과 같은 화면을 확인할 수 있습니다.

 

 

 

 

 

반응형

ASP.NET Core에서 TypeScript 사용하기

 

ASP.NET Core를 사용하는 솔루션에서 TypeScript를 사용하는 방법에 대해 알아봅니다.

 

 

 

0. 솔루션 및 프로젝트 생성.

 

TypeScript를 사용할 솔루션 및 프로젝트를 생성합니다.

예시에 사용된 솔루션은 ASP.Net Core 3.0을 사용하였으며 ASP.Net Core 웹 응용 프로그램 프로젝트중 웹 응용프로그램(Razor)을 사용하였습니다.

 

 

 

1. NuGet 패키지 설치

 

"프로젝트 -> NuGet 패키지 관리자"를 클릭해 NuGet 패키지 관리자를 엽니다.

 

"StaticFiles"와 "TypeScript.MsBuild"를 검색해 설치합니다.

 

 

 

 

2. Node.js 설치

 

TypeScript를 빌드하기 위해 gulp를 사용합니다. 여기에서 Nodejs를 설치하세요.

 

 

 

 

3. 외부 웹 도구 설정 변경.

 

PATH 환경 변수에서 npm을 찾도록 Visual Studio를 구성합니다. 기본적으로 Visual Studio는 설치 디렉터리에 있는 npm의 버전을 사용합니다.

 

도구 > 옵션 > 프로젝트 및 솔루션 > 웹 패키지 관리 > 외부 웹 도구로 이동한 후 목록에서 $(PATH) 항목을 선택합니다. 위쪽 화살표를 클릭하여 이 항목을 목록의 두 번째 위치로 이동합니다.

 

 

 

 

4. ts 파일 생성.

 

다음과 같이 프로젝트에 "scripts" 폴더를 추가한 후 "app.ts" 파일을 생성합니다.

 

그리고 다음과 같이 코딩합니다.

 

function sayHello() { 
    const compiler = (document.getElementById("compiler") as HTMLInputElement).value; 
    const framework = (document.getElementById("framework") as HTMLInputElement).value; 
    return `Hello from ${compiler} and ${framework}!`; 
}

 

 

 

5. TypeScript 구성 파일 생성.

 

이제 TypeScript 컴파일러 구성 파일을 생성합니다. "script" 폴더 내에 "tsconfig.json" 파일을 생성합니다.

 

새 항목 추가를 이용해 "TypeScript JSON 구성 파일"을 선택해서 생성하면 기본 설정을 자동으로 입력해 줍니다.

 

"tsconfig.json"의 설정을 다음과 같이 수정합니다.

 

{ 
  "compilerOptions": { 
    "noImplicitAny": true, 
    "noEmitOnError": true, 
    "removeComments": true, 
    "sourceMap": true, 
    "target": "es6" 
  }, 
  "exclude": [ 
    "wwwroot" 
  ], 
  "files": [ 
    "./app.ts" 
  ], 
  "compileOnSave": true 
} 

 

 

6. NPM 패키지 설치

 

이제 TypeScript 컴파일을 위한 npm 패키지를 설치해야 합니다.

 

프로젝트에 "package.json" 파일을 추가합니다. 새 항목 추가를 이용해 "NPM 구성 파일"을 선택해서 생성하면 기본 설정을 자동으로 입력해 줍니다.

 

"package.json"파일을 다음과 같이 수정해줍니다.

 

{ 
  "version": "1.0.0", 
  "name": "asp.net", 
  "private": true, 
  "devDependencies": { 
    "gulp": "4.0.2", 
    "del": "5.1.0" 
  } 
}

 

** "package.json" 파일을 수동으로 만들지 않고 npm cmd를 이용해서 생성해주셔도 됩니다.

 

수정이 끝났다면 "package.json" 파일을 우클릭 해 "패키지 복원"을 클릭합니다.

 

복원이 완료되면 프로젝트의 종속성에서 추가한 "del" 및 "gulp"를 확인할 수 있습니다.

 

 

 

 

 

 

 

7. gulp 설정

 

이제 설치한 gulp가 TypeScript를 빌드하도록 일을 시켜야 합니다.

 

프로젝트에 "gulpfile.js"를 추가한 후 다음과 같이 코딩합니다.

 

/// <binding AfterBuild='default' Clean='clean' />
var gulp = require('gulp');
var del = require('del');
var paths = {
    scripts: ['scripts/**/*.js', 'scripts/**/*.ts', 'scripts/**/*.map'],
};
gulp.task('clean', function () {
    return del(['wwwroot/scripts/**/*']);
});
gulp.task('default', function () {
    gulp.src(paths.scripts).pipe(gulp.dest('wwwroot/scripts'));
});

 

수정이 끝났다면 "gulpfile.js" 파일을 우클릭 해 "작업 러너 탐색기"를 클릭합니다.

 

 

 

 

 

 

 

 

 

 

정상적으로 적용되었다면 좌측 화면과 같은 내용이 보입니다.

만약 반영이 안 되었다면 하늘색 화살표를 눌러 새로고침을 해주세요.

 

 

 

 

 

 

 

 

 

8. HTML 작성

 

"Pages -> index.cshtml"파일을 수정합니다.

 

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <div id="message"></div>
    <div>
        Compiler: <input id="compiler" value="TypeScript" onkeyup="document.getElementById('message').innerText = sayHello()" /><br />
        Framework: <input id="framework" value="ASP.NET" onkeyup="document.getElementById('message').innerText = sayHello()" />
    </div>
</div>
<script src="~/scripts/app.js"></script>

 

 

 

9. 빌드 및 결과 확인.

 

이제 빌드 및 디버그를 수행합니다.

 

빌드가 완료되면 "webroot"에 "scripts"폴더가 생성되고 "app.js"파일이 생성된 것을 확인할 수 있습니다.

 

 

 

 

 

 

 

컴파일러 내의 문자열을 수정하면 위에 텍스트가 변경됩니다.

 

 

 

 

 

 

반응형

VisualStudio와 GitHub 연동하기

 

VisualStudio를 GitHub에 연동하는 방법을 알아봅니다.

 

 

 

0. GitHub 원격 저장소 생성 및 VS2019 설치

 

GitHub에 로그인한 후 사용할 원격 저장소를 미리 생성해 둡니다.

 

 

사용할 VS를 준비합니다. 해당 예시에서는 VS2019 CE버전을 사용하였습니다.

 

 

 

 

1. GitHub Extension 설치

 

VS2019를 킨 후 확장 -> 확장 관리를 연 후 "GitHub Extension for Visual Studio"를 설치합니다.

 

다운로드 버튼을 클릭한 후 VS2019를 끄면 자동으로 설치를 시작합니다.

 

 

 

2. 저장소 복제

 

재시작 후 "팀 탐색기" 창을 열어보면 "호스티드 서비스 공급자"에 "GitHub"이 추가된 것을 확인할 수 있습니다.

 

 

 

 

 

 

 

 

 

 

 

"연결..."을 클릭해 GitHub에 로그인 합니다. 성공적으로 연결이 되면 "팀 탐색기"에 "GitHub"이 추가됩니다.

 

이미 Git 원격 저장소가 있다면 "복제"를, 원격 저장소를 새로 만들려면 "만들기"를 클릭합니다. 

 

 

 

 

 

 

 

 

 

사용할 저장소를 선택 한 후 로컬 경로를 지정합니다. 

이후 "복제"버튼을 클릭합니다.

 

 

 

복제에 성공하면 "팀 탐색기"에서 좌측과 같은 화면을 확인할 수 있습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. 솔루션 생성 및 커밋

 

처음 생성된 저장소를 복제한 경우 빈 폴더만 생성됩니다.

팀 탐색기 -> 솔루션 -> 새로 만들기를 선택해 솔루션을 생성합니다.

 

솔루션을 생성한 후 "프로젝트"의 "변경 내용"을 선택합니다.

 

 

 

 

 

커밋 메시지를 입력합니다. 하단의 변경내용을 확인한 후 "모두 커밋" 버튼을 클릭해 커밋 작업을 수행합니다.

 

만약 해당 변경 내용을 바로 푸시하고 싶다면 "모두 커밋" 버튼의 삼각형을

눌러 "모두 커밋 후 푸시"를 선택합니다.

 

 

 

 

 

 

이후 GitHub을 확인하면 정상적으로 푸시된 것을 확인할 수 있습니다.

 

 

 

 

반응형

'Programming' 카테고리의 다른 글

Front-end: Tech Trends (2) - AMP, Babel, TypeScript  (0) 2019.12.10
Front-end: Tech Trends (1) - PWA, SPA, SEO  (0) 2019.12.10
[SPA] SPA에서 SEO 문제 해결  (2) 2019.10.04
[SPA] Single Page Application  (0) 2019.10.04
[Kotlin] 37. 제네릭  (0) 2019.09.17

References: 아하 프론트 개발기

SinglePageApplication에서 SerachEngineOptimization와 관련된 문제를 ServerSideRendering을 이용해 해결하는 방법에 대해 알아봅니다.

 

 

1. SSR(Server Side Rendering)

 

일반적인 웹페이지는 페이지를 이동할 때마다 새로운 페이지를 요청하고 서버에서 모든 탬플릿은 서버 연산을 통해서 렌더링하고 완성된 페이지 형태로 응답합니다. 이를 SSR이라 합니다.

 

 

 

2. 장단점

 

서버에서 완성된 페이지를 주기 때문에 검색엔진이 크롤링하기 매우 좋습니다.

 

그에 반해 매 페이지 요청마다 새로고침이 발생하며 서버에서 불필요한 탬플릿도 중복해서 로딩되고 렌더링에 따른 부하 문제가 발생합니다.

 

 

 

3. React에서의 SSR

 

next.js가 아주 좋은 해결책이 될 것이라 생각합니다.

공식 홈페이지에 따르면 Next.js 9가 불과 몇 달 전에 출시하였습니다.

자세한 내용은 Next.js 공식 홈페이지를 참고하시면 됩니다.

 

 

 

 

 

 

 

반응형

'Programming' 카테고리의 다른 글

Front-end: Tech Trends (1) - PWA, SPA, SEO  (0) 2019.12.10
VisualStudio와 GitHub 연동하기  (0) 2019.10.28
[SPA] Single Page Application  (0) 2019.10.04
[Kotlin] 37. 제네릭  (0) 2019.09.17
[Kotlin] 36. 연산자 오버로딩  (0) 2019.09.16

References: 아하 프론트 개발기

 

 

1. SPA

 

Single Page Application. 페이지가 하나만 있는 웹페이지.

Client Side Rendering 방식으로 생명주기동안 리소스를 딱 한번만 로딩한다.

그 이후부턴 데이터를 받아올때만 서버와 통신하며 페이지를 이동하면 기존 페이지 내부를 수정하여 보여준다.

 

 

 

2. 장점

 

  • 자연스러운 사용자 경험(UX)
  • 필요한 리소스만 부분적으로 로딩(성능)
  • 서버의 탬플릿 연산을 클라이언트로 분산(성능)
  • 컴포넌트별 개발 용이(생산성)
  • 모바일 앱 개발을 염두에 둔다면 동일한 API를 사용하도록 설계 가능(생산성)

 

3. 단점

 

  • JavaScript 파일을 번들링해서 한 번에 받기 때문에 초기 구동 속도 느림(webpack 의 code splitting으로 해결)
  • 검색엔진최적화(SEO)가 어려움 (SSR 로 해결)
  • 보안 이슈 (프론트엔드에 비즈니스 로직 최소화)

 

 

 

 

반응형

'Programming' 카테고리의 다른 글

VisualStudio와 GitHub 연동하기  (0) 2019.10.28
[SPA] SPA에서 SEO 문제 해결  (2) 2019.10.04
[Kotlin] 37. 제네릭  (0) 2019.09.17
[Kotlin] 36. 연산자 오버로딩  (0) 2019.09.16
[Kotlin] 35. 어노테이션 클래스  (0) 2019.09.16

 

1. Redux란 무엇인가.

 

한 문장으로 말하자면 "Redux는 상태를 좀 더 효율적으로 관리할 수 있게 해주는 라이브러리"입니다.

 

 

 

2. Flux 패턴

 

Redux 공식 홈페이지의 소개에 따르면 "Redux는 Flux의 중요한 특징들로부터 영감을 얻었습니다. Flux와 마찬가지로 Redux에서는 애플리케이션의 특정 레이어에 있을 모델 업데이트 로직에 집중할 수 있도록 해줍니다"라고 명시되어 있습니다.

그렇다면 Flux란 무엇일까요?

 

Flux 패턴은 MVC 패턴의 양방향 통신이 가진 복잡함을 제거하기 위해 컴포넌트 간 통신을 단일화시킨 패턴을 말합니다.

위의 그림과 같이 데이터는 디스패처에 의해 단방향으로 흐르게 되는 것이 Flux 패턴의 핵심입니다.

 

 

 

3. Redux

 

다시 Redux로 돌아와서 결국 Redux는 Flux패턴의 구현체 중 하나란 것이다.

물론 공식 홈페이지에 따르면 "Redux를 Flux의 구현 중 하나라고 생각할 수 있을까요? 그렇기도 하고, 아니기도 합니다."라고 적혀있습니다. 

Redux는 Flux패턴의 철학을 추구한 구현체가 맞습니다만 정확히 같지는 않습니다. 가장 큰 차이점은 Flux와 달리 Redux에는 디스패처라는 개념이 존재하지 않는다는 것입니다.

좀 더 명확히 하자면  "Flux는 (state, action) => state 형식으로 묘사되곤 합니다. 따라서 Redux 역시 Flux 아키텍처라고 이야기할 수 있지만, 순수 함수를 통해 이를 더 간단하게 만듭니다"라고 설명되어 있습니다.

 

 

 

 

반응형

References: Do it! 코틀린 프로그래밍

코틀린에서의 제네릭에 대해 알아봅니다.

 

 

1. 제네릭

 

제네릭(Generic)은 클래스 내부에서 사용할 자료형을 나중에 인스턴스를 사용할 때 확정합니다.

자료형의 객체들을 다루는 메서드나 클래스에서 컴파일 타임에 자료형을 검사해 적당한 자료형을 선택할 수 있도록 하기 위해 제네릭이 도입되었습니다.

제네릭을 사용하면 객체의 자료형을 컴파일 타임에 체크하므로 객체 자료형의 안정성을 높이고 형 변환의 번거로움이 줄어듭니다.

 

제네릭은 앵글 브래킷(<>) 사이에 형식 매개변수를 넣어 선언합니다.

이때 형식 매개변수는 하나 이상 지정할 수 있습니다.

형식 매개변수는 자료형을 대표하는 용어로 T와 같은 특정 영문의 대문자로 사용합니다. 이는 나중에 필요한 자료형으로 대체됩니다.

 

제네릭은 다양한 자료형을 다워랴하는 컬렉션에 많이 사용됩니다.

컬렉션은 List, Set, Map등으로 다수의 데이터를 다루는 특별한 클래스로 제네릭을 사용해 정의되어 있습니다.

 

다음 예시를 통해 제네릭에 대해 알아보겠습니다.

 

class Box<T>(t: T) { var name = t }
fun main() {
    val box1: Box<Int> = Box<Int>(1) // Box(1)
    val box2: Box<String> = Box<String>("Hello") // Box("Hello")
    println(box1.name)
    println(box2.name)
}

 

  • Box<T>(t: T): 제네릭 사용. 형식 매개변수로 받은 인자를 name에 저장.

 

위 코드를 실행하면 다음과 같은 결과를 확인할 수 있습니다.

형식 매개변수는 T입니다. T는 보통 Type을 줄인 것을 의미하며 강제적인 것은 아닙니다.

형식 매개면수는 관습적으로 다음을 사용합니다.

  • 요소(Element) - E
  • 키(Key) - K
  • 숫자(Number) - N
  • 형식(Type) - T
  • 값(Value) - V

 

앞선 예제에서의 Box<T>를 제네릭 클래스라고 합니다.

제네릭 클래스는 형식 매개변수를 하나 이상 받는 클래스입니다.

클래스를 선언할 때 자료형을 특정하지 않고 인스턴스를 생성하는 시점에서 자료형을 정합니다.

 

 

2. 자료형 변환

 

제네릭 클래스는 가변성을 지정하지 않으면 형식 매개변수에 상, 하위 클래스가 지정되어도 서로 자료형이 변환되지 않습니다.

다음 코드를 통해 확인해 보겠습니다.

 

open class Parent
class Child: Parent()
class Cup<T>
fun main() {
    val obj1: Parent = Child()
    val obj2: Child = Parent()
    val obj3: Cup<Parent> = Cup<Child>()
    val obj4: Cup<Child> = Cup<Parent>()
    val obj5 = Cup<Child>()
    val obj6: Cup<Child> = obj5
}

 

  • obj1: Parent 형식은 Child의 자료형으로 변환될 수 있습니다.
  • obj2: 자료형이 불일치해 오류가 발생합니다.
  • obj3: 자료형이 불일치해 오류가 발생합니다. 
  • obj4: 자료형이 불일치해 오류가 발생합니다.
  • obj5: obj는 Cup<Child> 자료형이 됩니다.
  • obj6: 자료형이 일치해 오류가 발생하지 않습니다.

 

obj3, obj4에서 보듯이 제네릭 클래스에서는 형식 매개변수인 T에 상위와 하위 클래스를 지정해도 서로 관련 없는 형식이 되어 형식이 일치하지 않는 오휴가 발생합니다.

또한 제네릭 형식 매개변수는 기본적으로 Null을 허용합니다. 만약 Null을 허용하지 않게 하고 싶다면 T: Any 형식을 사용하면 됩니다.

 

 

3. 제네릭 함수 및 메서드

 

형식 매개변수를 받는 함수나 메서드를 제네릭 함수 또는 메서드라고 합니다.

제네릭 함수나 메서드는 해당 함수나 메서드 앞에 <T>와 같이 형식 매개변수를 지정합니다.

<K, V>처럼 여러 형식 매개변수를 사용할 수도 있습니다.

자료형의 결정은 함수가 호출될 때 컴파일러가 자료형을 추론할 수 있습니다.

 

다음 예시를 통해 확인해 보도록 하겠습니다.

 

fun <T> find(a: Array<T>Target: T): Int{
    for( i in a.indices ) {
        if ( a[i] == Target ) { return i }
    }
    return -1
}
fun main() {
    val arr1: Array<String> = arrayOf("Apple", "Banana", "Cherry", "Durian")
    var arr2: Array<Int> = arrayOf(1, 2, 3, 4)
    println("arr.indices ${arr1.indices}")
    println(find<String>(arr1, "Cherry"))
    println(find(arr2, 2))
}

 

  • fun <T> find: 제네릭 함수
  • Array<T>: 배열을 위한 클래스
  • a.indices: a배열의 유효 범위

 

위의 코드를 실행시키면 다음과 같은 결과를 확인할 수 있습니다.

 

 

4. 제네릭과 람다식

 

형식 매개변수로 선언된 함구의 매개 변수를 연산할 경우 자료형을 경정할 수 없어 오류가 발생합니다.

 

fun <T> add ( a: T, b: T): T { 
    return a + b // 자료형을 아직 결정할 수 없어 오류 발생. 
}

 

하지만 람다식을 매개변수로 받으면 자료형을 결정하지 않아도 실행 시 람다식 본문을 넘겨줄 때 결정되므로 이런 문제를 해결할 수 있습니다.

 

다음과 같이 코드를 작성해 봅시다.

 

fun <T> add( a: T, b: T, op: ( T, T ) -> T ): T{
    return op( a, b )
}
fun main() {
    val result = add2, 3, { a, b -> a + b } )
    println(result)
}

 

  • op: ( T, T ) -> T: 매개변수에 람다식을 받습니다.
  • { a, b -> a + b }: 매개변수에 람다식을 전달합니다.

 

람다식은 add 함수가 실행될 때 넘겨지는 인자이므로 연산식을 함수 선언부에 직접 구현하지 않고 전달하는 방법을 사용합니다. 따라서 함수의 형식 매개변수의 자료형을 특정하지 않아도 실행 가능합니다.

 

함루의 람다식 매개변수를 좀 더 읽기 좋게 단순화할 수 있습니다.

다음 예제 코드는  typealias를 사용해 람다식 매개변수에 다른 이름을 사용한 예시입니다.

 

typealias arithmetic<T> = ( T, T ) -> T
fun <T> add( a: T, b: T, op: arithmetic<T> ): T{
    return op( a, b )
}
fun main() {
    val sumInt1: (Int, Int) -> Int = { a, b -> a + b }
    val sumInt2 = { a: Int, b: Int -> a + b
}

    val result = add(2, 3, { a, b -> a + b } )
    val result1 = add( 2, 3, sumInt1 )
    val result2 = add( 2, 3, sumInt2 )

    println(result)
    println(result1)
    println(result2)
}

 

  • typealias: typealias를 사용해 람다식 매개변수를 단순화하였습니다.
  • sumInt1, sumInt2: 람다식을 간소화 후 변수에 저장해 사용하였습니다.

 

 

 

 

반응형

References: Do it! 코틀린 프로그래밍

코틀린에서 연산자를 오버 로딩하는 법에 대해 알아봅니다.

오버 로딩에 대한 내용은 여기서 확인해 주세요.

 

 

1. 연산자 오버 로딩

 

말 그대로 오버 로딩을 연산자에 적용하는 것을 말합니다.

사실 코틀린에선 이미 여러 연산자가 많이 오버 로딩되어 있습니다.

 

'+'를 예시로 살펴보겠습니다.

지금까지 +연산을 직접 구현한 적이 있나요?

사실 A + B는 A.plus(B)와 같습니다. A와 B엔 다양한 자료형이 올 수 있습니다.

코틀린은 편의를 위해 이미 여러 자료형에 대해 오버 로딩을 구현해 두었습니다.

Byte, Short, Int, Long, Float, Double, Any 등 이미 오버 로딩된 '+'를 바로 사용할 수 있습니다.

 

만약 사용자가 정의한 객체에 대해 '+'연산을 수행하고 싶으면 어떻게 해야 할까요?

이런 경우에 연산장 오버 로딩이 필요합니다.

다음 예시를 통해 직접 정의한 클래스에 대해 연산자 오버 로딩을 해 봅시다.

 

class Point(var x: Int = 0, var y: Int = 0) {
    operator fun plus(p: Point): Point { return Point( x + p.x, y + p.y) }
}
fun main() {
    val p1 = Point(3, -8)
    val p2 = Point(2, 9)
    var point = Point()
    point = p1 + p2
    println("point = (${point.x}, ${point.y})")
}

 

Point 클래스에 대해서 plus 연산자를 오버 로딩하였습니다.

위의 코드를 실행하면 다음과 같은 결과를 확인할 수 있습니다.

 

* 연산자의 종류

  • a + b = a.plus(b)
  • a - b = a.minus(b)
  • a * b = a.times(b)
  • a / b = a.div(b)
  • a % b = a.rem(b)
  • a .. b = a.rangeTo(b)
  • ...

 

 

 

반응형

'Programming' 카테고리의 다른 글

[SPA] Single Page Application  (0) 2019.10.04
[Kotlin] 37. 제네릭  (0) 2019.09.17
[Kotlin] 35. 어노테이션 클래스  (0) 2019.09.16
[Kotlin] 34. 봉인 클래스와 열거형 클래스  (0) 2019.09.16
[Kotlin] 33. 내부 클래스  (0) 2019.09.16

References: Do it! 코틀린 프로그래밍

코틀린에서의 어노테이션 클래스에 대해 알아봅니다.

 

 

1. 어노테이션(Annotation) 클래스

 

어노테이션은 코드에 부가 정보를 추가하는 역할을 합니다.

@기호와 함께 나타내는 표기법입니다.

주로 컴파일러나 프로그램 런타임에서 사전 처리를 위해 사용합니다.

 

 

2. 어노테이션의 사용

 

사용자 정의 어노테이션을 만들기 위해서는 annotation 키워드를 사용해 클래스를 선언합니다.

선언한 어노테이션 클래스는 @기호와 함께 사용할 수 있습니다.

 

annotation class AnnoTest
...
@AnnoTest class MyClass{ ... }

 

어노테이션은 다음과 같은 속성을 사용해 정의될 수 있습니다.

  • @Target : 어노테이션이 지정되어 사용할 종류를 정의
  • @Retention : 어노테이션을 컴파일된 클래스 파일에 저장할 것인지 런타임에 반영할 것인지 정의
  • @Repeatable : 어노테이션을 같은 요소에 여러번 사용 가능하게 할지를 정의
  • @MustBeDocumented : API의 일부분으로 문서화하기 위해 사용.

위와 같은 속성과 함께 정의된 어노테이션 클래스의 예는 다음과 같습니다.

 

@Target( AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
             AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION )
@Retention( AnnotationRetention.SOURCE ) // or RUNTIME
@MustBeDocumented
annotation class AnnoTest

 

 

3. 어노테이션의 위치

 

어노테이션이 들어갈 수 있는 위치는 다음과 같습니다.

 

@AnnoTest class MyClass {
    @AnnoTest fun myMethod( @AnnoTest myProperty: Int): Int {
        return( @AnnoTest 1 )
    }
}

 

어노테이션은 클래스앞, 메서드 앞, 프로퍼티 앞에서 사용 가능하며 반환 시 반환 값 앞에 표기하고 소괄호로 감싸줍니다.

 

만약 생성자 앞에 어노테이션을 사용하면 constructor 키워드를 반드시 명시해야 합니다.

 

class MyClass @AnnoTest constructor( dependency: MyDependency ) { ... }

 

어노테이션은 게터/세터에서도 사용할 수 있습니다.

 

class MyClass {
    var x: MyDependendcy? = null
        @AnnoTest set
}

 

 

4. 어노테이션의 매개변수와 생성자.

 

어노테이션에 매개변수를 지정하려면 다음과 같이 생성자를 통해 지정할 수 있습니다.

 

annotation class Special( val why: String )
@Special( "example" ) class MyClass{ ... }

 

매개변수로 사용될 수 있는 자료형은 다음과 같습니다.

  • 기본 자료형
  • 열거형
  • 문자형
  • 기타 어노테이션
  • 클래스
  • 위의 목록을 갖는 배열

 

 

 

 

반응형

'Programming' 카테고리의 다른 글

[Kotlin] 37. 제네릭  (0) 2019.09.17
[Kotlin] 36. 연산자 오버로딩  (0) 2019.09.16
[Kotlin] 34. 봉인 클래스와 열거형 클래스  (0) 2019.09.16
[Kotlin] 33. 내부 클래스  (0) 2019.09.16
[Kotlin] 32. 데이터 클래스  (0) 2019.09.12

References: Do it! 코틀린 프로그래밍

코틀린에서의 봉인 클래스와 열거형 클래스에 대해 알아봅니다.

 

 

1. 봉인(Sealed) 클래스

 

실드(Sealed) 클래스는 미리 만들어 놓은 자료형들을 묶어서 제공합니다.

따라서 어떤 의미에서는 열거형(Enum) 클래스의 확장으로 볼 수도 있습니다.

 

실드 클래스는 sealed 키워드를 통해 선언할 수 있습니다.

실드 클래스는 추상 클래스와 같기 때문에 객체를 만들 수 없습니다.

실드 클래스는 private 이 아닌 생성자는 허용하지 않습니다.

실드 클래스는 같은 파일안에서만 상속을 허용합니다.

 

다음 예제를 통해 실드 클래스에 대해 알아보도록 하겠습니다.

 

sealed class Result{
    open class Success(val message: String): Result()
    class Error(val code: Int, val message: String): Result()
}
class Status: Result()
class Inside: Result.Success("Status")
fun eval(result: Result): String = when(result) {
    is Status -> "in progress"
    is Result.Success -> result.message
    is Result.Error -> result.message
}
fun main() {
    val result = Result.Success("Good!")
    val msg = eval(result)
    println(msg)
}

 

  • sealed class Result: 실드 클래스를 선언합니다.
  • class Stauts: Result(): 실드 클래스를 상속합니다. 같은 파일에서만 가능합니다.
  • class Inside: Result.Success("Status"): 내부 클래스 상속

위의 코드를 실행하면 다음과 같은 결과를 확인할 수 있습니다.

실드 클래스는 특정 객체 자료형에 따라 when문과 is에 의해 선택적으로 실행할 수 있습니다.

 

 

2. 열거형 클래스

 

열거형 클래스는 여러 상수를 선언하고 열거된 값을 조건에 따라 선택할 수 있는 특수한 클래스입니다.

 

열거형 클래스는 실드 클래스처럼 다양한 자료형을 다룰 순 없습니다.

열거형 클래스는 enum 키워드와 함께 선언됩니다.

열거형 클래스의 상수값은 매개변수를 통해 초기화될 수 있습니다.

열거형 클래스의 상수값의 끝은 세미콜론을 통해 알립니다.

열거형 클래스는 필요한 경우 메서드를 포함할 수 있습니다.

 

다음 코드를 통해 열거형 클래스에 대해 알아보도록 합시다.

 

enum class Color(val r: Int, val g: Int, val b: Int){
    RED(255, 0, 0), ORANGE(255, 165, 0), YELLOW(255, 255, 0),
    GREEN(0, 255, 0), BLUE(0, 0, 255), INDIGO(75, 0, 130), VIOLET(238, 130, 238);
    fun rgb() = (r * 256 + g) * 256 + b
}
fun getColor(color:Color) = when(color) {
    Color.RED -> color.name
    Color.ORANGE -> color.ordinal
    Color.YELLOW -> color.toString()
    Color.GREEN -> color
    Color.BLUE -> color.r
    Color.INDIGO -> color.g
    Color.VIOLET -> color.rgb()
}
fun main() {
    println(Color.BLUE.rgb())
    println(getColor(Color.BLUE))
}

 

  • enum class Color: enum 키워드를 이용해 열거형 클래스를 선언합니다.
  • VIOLET(238, 130, 238); : 세미콜론을 통해 끝을 알려줍니다.

위의 코드를 실행하면 다음과 같은 결과를 확인할 수 있습니다.

열거형 클래스에서 인터페이스의 메서드를 구현할 수도 있습니다.

다음 예제를 통해 인터페이스의 메서드를 구현하는 방법을 알아봅시다.

 

interface ScoreScore { fun getScore(): Int}
enum class MemberType(var prio: String): Score {
    NORMAL("Third"){ override fun getScore(): Int = 100},
    SILVER("Second"){ override fun getScore(): Int = 500},
    GOLD("First"){ override fun getScore(): Int = 1500}
}
fun main() {
    println(MemberType.NORMAL.getScore())
    println(MemberType.GOLD)
    println(MemberType.valueOf("SILVER"))
    println(MemberType.SILVER.prio)
    for( grade in MemberType.values() ){ println("grade.name = ${grade.name}, prio = ${grade.prio}") }
}

 

  • interface Score: 인터페이스를 선언합니다.
  • enum class MemberType: 인터페이스를 구현하는 열거형 클래스입니다.
  • for( grade in MemberType.values() ): 열거형 클래스의 모든 값을 가져오는 반복문입니다.

위의 코드를 실행하면 다음과 같은 결과를 확인할 수 있습니다.

 

 

 

 

 

반응형

'Programming' 카테고리의 다른 글

[Kotlin] 36. 연산자 오버로딩  (0) 2019.09.16
[Kotlin] 35. 어노테이션 클래스  (0) 2019.09.16
[Kotlin] 33. 내부 클래스  (0) 2019.09.16
[Kotlin] 32. 데이터 클래스  (0) 2019.09.12
[Kotlin] 31. 인터페이스  (0) 2019.09.12

+ Recent posts