Babel

Babel  ES2015+ 문법을 ES5 지원 브라우저에서 해석할 수 있도록 변환해주는 트랜스파일러이다. 하지만 새롭게 추가된 전역 객체들(Promise, Map, Set..)과 String.padStart 등 전역 객체에 추가된 메서드들은 트랜스파일링만으론 해결하기 어렵기 때문에 core-js  regenerator-runtime 와 같은 별도의 polyfill 이 필요하다.

Babel 기반에서 폴리필을 추가하는 방법은 두 가지가 존재한다. babel-polyfill 을 사용하는 방법과 babel-plugin-transform-runtime 을 사용하는 방법이다. 차례대로 살펴보자.

 

 

 

babel-polyfill

babel-polyfill 은 내부적으로 페북에서 만든 Generator Function 폴리필인 regenerator runtime 과 ES5/6/7 폴리필인 core-js 를 주요 디펜던시로 가지고 있다. 가장 유명하고 안정적인 폴리필들을 사용하기 편리하게 랩핑해 놓은 모듈이라고 생각하면 편하다.

babel-polyfill을 사용하려면 먼저 아래와 같이 npm 으로 설치해준다.

# babel-polyfill 디펜던시 추가
$ npm
install --save babel-polyfill

 

그런 뒤에 스크립트 중 최상위 시작지점에 require 혹은 import 해주면, babel-polyfill 은 전역에 직접 폴리필을 추가한다. 즉, 전역 오염이 발생한다.

require('babel-polyfill');

//혹은

import 'babel-polyfill';

babel-polyfill 을 사용할 때의 장점은 어떤게 있을까?

core-js는 먼저 전역에 폴리필을 추가하기전에 해당 기능이 있는지를 체크하므로, 폴리필이 필요없는 최신 브라우저에서는 폴리필없이 동작하게 되어 (babel-plugin-transform-runtime 를 사용하는 것에 비해) 빠르다.

또 전역 객체를 직접 수정하기 때문에 Array.prototype.includes 등 ES2015+에서 새로 추가된 프로토타입 메서드도 문제없이 사용 가능하고, 덕분에 내가 짠 코드가 아닌 npm에서 디펜던시로 받은 라이브러리가 ES2015+ 에서 새롭게 추가된 객체나 프로토타입 메서드를 사용하는지 신경쓸 필요가 없게 되어 개발할 때도 편리하다.

babel-polyfill 을 사용할 때의 단점이라면 실제 사용하지 않는 폴리필도 몽땅 추가되므로 번들링되는 파일의 크기가 커지게 된다는 점이다.

 

 

 

babel-polyfill 사용 시 주의할 점

한가지 꼭 주의할 부분이 있는데, 한 페이지에서 딱 하나의 babel-polyfill 만 허용된다는 점이다. 두 개의 babel-polyfill 을 실행하게 되면 반복적인 전역 객체 수정을 막기 위해 아래의 오류를 발생시킨다.

Uncaught Error : only one instance of babel-polyfill is allowed

 

babel-polyfill 소스를 살펴보면 내부적으로 전역 변수 하나를 두어 babel-polyfill 이 이미 실행되었는지를 체크하고 이미 실행되었다면 무조건(!!!) 오류를 던지는 구조이다.

if (global._babelPolyfill) {
 
throw new Error("only one instance of babel-polyfill is allowed");
}
global._babelPolyfill =
true;

import "core-js/shim";
import "regenerator-runtime/runtime";

...

 

왜 이렇게 극단적으로 오류를 던지게 했을까?

babel-polyfill 의 디펜던시인 core-js 의 ES6/7 폴리필의 경우 두 번 호출되면 내부적으로 오류가 발생되어 정상적으로 폴리필이 적용되지 않는다. 아마도 core-js 가 가지는 이러한 문제점 때문에 babel-polyfill 에 이런 예외처리가 추가된 게 아닐까 추정된다. 

따라서 babel-polyfill 이 두 번 호출되지 않도록 주의해야 한다. 단순히 babel-polyfill 이 두 번 호출되는 것 뿐만 아니라 core-js 의 ES6/7 폴리필이 로드된 상태에서 babel-polyfill 이 로드되거나 babel-polyfill 이 로드된 상태에서 core-js 의 ES6/7 폴리필이 로드되는 것 역시 주의해야 한다.

정리해보면, 싱글 페이지 어플리케이션에서 또다른 폴리필이 호출될 염려가 전혀 없는 환경이라면, babel-polyfill 만으로 IE8 과 같은 레거시 브라우저에서 큰 문제없이 트랜스파일링된 코드를 실행시킬 수 있기 때문에 babel-polyfill 은 가장 편하고 빠르게 폴리필을 적용할 수 있는 방법으로 추천 할 만하다.

 

 

 

babel-plugin-transform-runtime

babel-polyfill 외에 또 하나의 방법은 babel-plugin-transform-runtime 플러그인을 사용해서 Babel 이 트랜스파일링을 하는 과정에서 폴리필이 필요한 부분을 내부의 헬퍼 함수를 사용하도록 치환해주는 방법이다.

Babel 은 내부적으로 _extend 처럼 공통 함수를 위한 작은 헬퍼들을 사용하는데, 기본적으로 모든 파일에 이런 헬퍼들이 추가되기 때문에 이런 낭비를 막기 위해 transform-runtime 플러그인을 사용해서 모든 헬퍼들을 babel-runtime 이라는 모듈을 참조하도록 해준다. babel-plugin-transform-runtime 은 플러그인 이기때문에 빌드 단계(트랜스파일링 단계)에서 동작하게 된다.

transform-runtime 은 코드에 대한 샌드박스도 제공해주는데 내부적으로 core-js 내장하고 여기에 대한 alias 를 생성해서 트랜스파일링 과정에서 폴리필이 필요한 부분들이 이 alias 를 참조하도록 변경해서 전역 오염없이 폴리필이 적용되도록 만들게 된다.

babel-plugin-transform-runtime 플러그인은 내부적으로 babel-runtime 을 디펜던시로 갖는데, babel-runtime 은 또 core-js 와 regenerator-runtime 을 디펜던시로 갖는다. 자동적으로 babel-runtime/regenerator 와 babel-runtime/core-js 를 내장하게 되며 트랜스파일링 과정에서 인라인 Babel 헬퍼들을 제거하고 babel-runtime/helper 들을 사용하도록 변경하게 된다.

 

babel-plugin-transform-runtime 플러그인을 사용하려면 디펜던시는 아래의 두 가지 모두가 필요하다.

# babel-plugin-transform-runtime 디펜던시 추가
$ npm
install --save-dev babel-plugin-transform-runtime

# babel-runtime 디펜던시 추가
$ npm
install --save babel-runtime

babel-plugin-transform-runtime 은 트랜스파일링 과정에서 헬퍼들을 babel-runtime 모듈이 참조하도록 변경해주는 역할을 하고, babel-runtime 은 실제 실행 환경에서 헬퍼함수들이 참조할 수 있는 폴리필을 내장한 모듈로서 동작한다.

babel-plugin-transform-runtime 을 설정하는건 웹팩 기준으로는 webpack config 에서 babel 의 plugins 에 추가해주기만 하면 된다. 웹팩 설정 파일은 1.x 버전 기준이다. 웹팩 2.x 버전부터는 IE8 지원을 하지 않기 때문에 IE8 지원을 위해 폴리필이 필요한 상황이라면 웹팩 1.x 버전을 사용하는 것이 좀더 안전할 것으로 보인다. (웹팩 2.x 이상 버전도 IE8 에서 동작하기는 하는 것 같다)

loaders: [
   
//Babel 변환
    {
        test:
/\.(js|jsx)$/,
        include: [
           
/src\/js/,
           
/node_modules\/axios/
        ],
        loader:
'babel',
        query: {
            cacheDirectory:
true,

//plugins는 presets 보다 먼저 실행되며,
           
//plugins내의 순서는 처음 -> 나중으로 실행된다.
            plugins: [
               
// ['transform-class-properties'],
               
// ['transform-object-rest-spread', { useBuiltIns: true }],
                [
'transform-runtime'],
            ],
           
           
//presets내의 순서는 나중 -> 처음으로 실행된다.
            presets: [
                [
'env', {
                    targets: {
                        browsers: [
'ie >= 8']
                    },
                    loose:
true,
                }],
               
// ['react'],
            ],
        }
    },

...
],

앞서 설명한 것처럼 babel-plugin-transform-runtime 플러그인은 plugins 항목에 transform-runtime 을 추가해주는 것만으로 충분하다.

 

그 외에 주목해서 볼 부분은, include 로 node_modules 아래에 위치한 axios 를 추가해준 부분이다. 보통 트랜스파일링 대상에서 node_modules 아래에 있는 모듈들은 제외하는 것이 상식이다. 그런데 왜 추가해줬을까? 

axios 는 내부적으로 Promise 를 사용하는 라이브러리인데 Promise 가 전역 레벨에 선언되어 있지 않으면 오류가 발생하게 된다. 앞서 설명한 것처럼 babel-plugin-transform-runtime 플러그인은 전역 레벨에 폴리필을 적용하는 방식이 아니기 때문에 axios 가 실행될 때 Promise 를 찾지 못해 오류가 발생하게 되는 것이다. 이런 오류를 막기 위해 axios 도 babel-plugin-transform-runtime 플러그인을 통해 트랜스파일링 될 수 있도록 include를 사용해서 트랜스파일링 대상으로 추가해주어야 하는 것이다. 이런 부분이 babel-plugin-transform-runtime 플러그인을 사용할 때 주의할 부분이다.

 

babel-plugin-transform-runtime 플러그인은 아래와 같이 추가적인 옵션을 지정해줄 수 있으나 대부분 기본값으로 충분하다.

["transform-runtime", {
   
"helpers": true, // 인라인 바벨 헬퍼 (classCallCheck, extends, 등)을 moduleName. 으로 치환
   
"polyfill": true, // Promise, Set, Map 과 같은 새로운 내장 객체를 전역 오염없이 내부 객체를 참조하도록 변환
   
"regenerator": true, // generator 함수를 전역 오염없이 regenerator runtime 을 사용하도록 변환
   
"moduleName": "babel-runtime" // 헬퍼를 가져올 때 사용할 모듈의 이름
}]

 

 

 

babel-plugin-transform-runtime 플러그인이 적용된 코드

아래와 같은 간단한 코드를 babel-plugin-transform-runtime 을 사용하면 어떻게 트랜스파일링 될까?

class Person {
}

 

앞서 설명한 것처럼 babel-plugin-transform-runtime 은 트랜스파일링 과정에서 헬퍼들을 babel-runtime 모듈이 참조하도록 변경해주는 역할을 하고, babel-runtime 은 실제 실행 환경에서 헬퍼함수들이 참조할 수 있는 폴리필을 내장한 모듈로서 동작하게 된다.

"use strict";

var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var Person = function Person() {
  (
0, _classCallCheck3.default)(this, Person);
};

 

babel-plugin-transform-runtime 을 사용하게 되면 트랜스파일링이 필요한 부분이 너무 많을 경우 용량이 증가할 수 있으나 대체적으로 babel-polyfill 을 사용할 떄보다는 용량이 줄어든다.

하지만 babel-polyfill 과 달리 최신 브라우저에 관계없이 폴리필 코드가 무조건 물려서 동작하기 때문에 더 느려질 수 있다.

 

 

 

babel-plugin-transform-runtime 사용 시 주의할 점

그리고 치명적인 단점이 있는데, Object.assign 처럼 내장 객체의 static 메서드는 사용가능하지만, 새롭게 추가된 인스턴스 메서드 예를들면, [1,2,3,4,5].includes(3) 과 같은 메서드는 트랜스파일링 되지 않기 때문에 오류가 발생한다. 따라서 새롭게 추가된 프로토타입 메서드들은 사용하지 않도록 주의해야 한다.

또 한가지 주의할 점은 디펜던시들의 ES2015 기능들 사용 여부이다. babel-polyfill 은 전역을 직접 수정하기 때문에 npm 을 통해 설치한 디펜던시들이 Promise 와 같은 새로운 내장 객체를 사용하는지 여부를 걱정할 필요가 없지만, babel-plugin-transform-runtime 을 사용하면 이 부분까지 고려해주어야 한다. 예를들어 내부적으로 Promise 를 사용하는 디펀덴시가 있다면 이 디펜던시도 함께 트랜스 파일링 될 수 있도록 바벨 설정을 추가해주어야 한다. 앞의 예시에서는 axios 가 Promise 를 사용하기 때문에 include 로 트랜스파일링 대상에 추가해주었었다.

이런 불편함이 있지만, 전역을 오염시키지 않기 때문에 라이브러리 형태로 동작하는 경우 babel-polyfill 보다는 babel-plugin-transform-runtime 을 사용하는게 바람직하다. 내 라이브러리가 사용될 곳에서 이미 babel-polyfill 을 쓰고 있을 수도 있기 때문이다.

 

 

 

babel-plugin-transform-runtime 과 IE8

babel-plugin-transform-runtime 을 사용해서 IE8을 지원하려면, babel 은 기본적으로 ES5 환경이라고 가정하므로 core-js 의 es5 polyfill 은 필수적으로 필요하다. 앞서 core-js 가 여러번 호출될 경우 오류가 발생한다고 했었는데, 다행히 core-js 의 ES5 폴리필은 여러번 호출되어도 오류가 발생하지 않는다.

import 'core-js/es5';

babel 설정은 앞서 살펴본 것처럼 ES2015+ 관련 프리셋의 loose 모드를 활성화하고, transform-runtime 플러그인을 추가해주면 된다. 여기에서는 바벨의 env 프리셋으로 ES2015 관련 프리셋들을 추가해주고 있다. loose 모드를 활성화하지 않으면 IE8 과 호환성이 없는 코드로 트랜스파일링 되므로 주의해야 한다.

loaders: [
   
//Babel 변환
    {
        test:
/\.(js|jsx)$/,
        include: [
           
/src\/js/,
           
/node_modules\/axios/
        ],
        loader:
'babel',
        query: {
            cacheDirectory:
true,
            plugins: [
                [
'transform-runtime'],
            ],           
            presets: [
                [
'env', {
                    targets: {
                        browsers: [
'ie >= 8']
                    },
                    loose:
true,
                }],
            ],
        }
    },

...
],

그런데 이렇게 Babel을 사용해서 transform을 해줘도 실제로 번들링된 결과물에는 여전히 IE8 에서 오류가 발생하는 default, catch 등의 키워드에 대한 처리가 이루어지지 않는다.

그래서 한번더 최종적으로 es3ify-loader 혹은 babel-plugin-transform-es3-member-expression-literals, babel-plugin-transform-es3-property-literals 플러그인으로 트랜스파일링을 해주어야 완전하게 IE8과의 호환성을 갖추게 된다.

postLoaders: [
    {
        test:
/\.js$/,
        loader:
'es3ify-loader',
    }
]

또 uglify 를 해줄 경우 screw_ie8 옵션을 true 로 줄경우 IE8에서 오류가 발생하므로 반드시 이 옵션을 false 로 주어야 한다.

new webpack.optimize.UglifyJsPlugin({
    compressor: {
        screw_ie8:
false,
        warnings:
false
    },
    mangle: {
        screw_ie8:
false
    },
    output: {
        comments:
false,
        screw_ie8:
false
    }
}),

 

 

 

마치며

IE8 을 지원해야 하는 안타까운 상황이 꽤 오래 가고 있다. 점점 라이브러리들이 IE8 지원을 중단해가는 상황인데 국내에서도 IE8 을 지원하지 않는 상황이 빨리 오기를 기대한다. (최근 개편한 네이버 메인 페이지가 IE7을 지원하는 상황이니 언제쯤에야 그런 날이 올지 모르겠다) 

 

 

 

참조

https://babeljs.io/docs/usage/caveats/

https://babeljs.io/docs/usage/polyfill/

http://babeljs.io/docs/plugins/transform-runtime/

 BABEL, BABEL-PLUGIN-TRANSFORM-RUNTIME, BABEL-POLYFILL, ES2015, WEBPACK

 

출처: <https://programmingsummaries.tistory.com/401>

Posted by 철냄비짱
,

@babel/polyfill

카테고리 없음 2019. 12. 30. 07:45

https://babeljs.io/docs/en/babel-polyfill

 

 

@babel/polyfill

🚨 As of Babel 7.4.0, this package has been deprecated in favor of directly including core-js/stable(to polyfill ECMAScript features) and regenerator-runtime/runtime (needed to use transpiled generator functions):

import "core-js/stable";
import "regenerator-runtime/runtime";

Copy

Babel includes a polyfill that includes a custom regenerator runtime and core-js.

This will emulate a full ES2015+ environment (no < Stage 4 proposals) and is intended to be used in an application rather than a library/tool. (this polyfill is automatically loaded when using babel-node).

This means you can use new built-ins like Promise or WeakMap, static methods like Array.from or Object.assign, instance methods like Array.prototype.includes, and generator functions (provided you use the regenerator plugin). The polyfill adds to the global scope as well as native prototypes like String in order to do this.

Installation

npm install --save @babel/polyfill

Copy

Because this is a polyfill (which will run before your source code), we need it to be a dependency, not a devDependency

Size

The polyfill is provided as a convenience but you should use it with @babel/preset-env and the useBuiltInsoption so that it doesn't include the whole polyfill which isn't always needed. Otherwise, we would recommend you import the individual polyfills manually.

TC39 Proposals

If you need to use a proposal that is not Stage 4, @babel/polyfill will not automatically import those for you. You will have to import those from another polyfill like core-js individually. We may work towards including this as separate files in @babel/polyfill soon.

Usage in Node / Browserify / Webpack

To include the polyfill you need to require it at the top of the entry point to your application.

Make sure it is called before all other code/require statements!

require("@babel/polyfill");

Copy

If you are using ES6's import syntax in your application's entry point, you should instead import the polyfill at the top of the entry point to ensure the polyfills are loaded first:

import "@babel/polyfill";

Copy

With webpack, there are multiple ways to include the polyfills:

      • When used alongside @babel/preset-env,
      • If useBuiltIns: 'usage' is specified in .babelrc then do not include @babel/polyfill in either webpack.config.js entry array nor source. Note, @babel/polyfill still needs to be installed.
      • If useBuiltIns: 'entry' is specified in .babelrc then include @babel/polyfill at the top of the entry point to your application via require or import as discussed above.
      • If useBuiltIns key is not specified or it is explicitly set with useBuiltIns: false in your .babelrc, add @babel/polyfill directly to the entry array in your webpack.config.js.

module.exports = {
 
entry: ["@babel/polyfill", "./app/js"],
};

Copy

      • If @babel/preset-env is not used then add @babel/polyfill to webpack entry array as discussed above. It can still be added at the top of the entry point to application via import or require, but this is not recommended.

We do not recommend that you import the whole polyfill directly: either try the useBuiltIns options or import only the polyfills you need manually (either from this package or somewhere else).

Usage in Browser

Available from the dist/polyfill.js file within a @babel/polyfill npm release. This needs to be included before all your compiled Babel code. You can either prepend it to your compiled code or include it in a <script> before it.

NOTE: Do not require this via browserify etc, use @babel/polyfill.

Details

If you are looking for something that won't modify globals to be used in a tool/library, checkout the transform-runtime plugin. This means you won't be able to use the instance methods mentioned above like Array.prototype.includes.

Note: Depending on what ES2015 methods you actually use, you may not need to use @babel/polyfill or the runtime plugin. You may want to only load the specific polyfills you are using (like Object.assign) or just document that the environment the library is being loaded in should include certain polyfills.

 CLITRANSFORM-RUNTIME →

 

 

출처: <https://babeljs.io/docs/en/babel-polyfill>

 

 

Posted by 철냄비짱
,

창 크기 조절

Front-End 2019. 12. 30. 07:43

 

 

 

샘플 코드 작성시 사용된 주요객체의 프로퍼티와 메서드 

 

 

screen.availWidth, screen.availHeight

실제로 사용할 수 있는 디스플레이의 크기

이 크기에는 데스크톱의 작업 표시줄 등에 의해 사용되는 공간이 제외되어있다. 

 

 

window.​open(url, name, features, replace) 새창을 생성하여 화면에 띄운다.​

url : 새창에서 보여줄 URL을 지정하는 문자열이며 생략 가능. 이 전달인자가 생략되거나 빈문자열이로 지정되면 새창의 화면에는 아무 문서도 출력되지 않는다.

 

name : 새창의 이름, 만약 특정 이름의 창이 이미 열려있는 상태라면, open()은 새창을 생성하지 않고 해당 이름의 창에 대한 참조를 반환한다. 이때 features 전달인자는 무시된다.

 

features : 새 창에 표준 브라우저 창의 어떤 특성들을 보여줄지를 지정하는 문자열이다. 

width, height , left, top, location, menubar, resizable, scrollbars, status

 

replace : 창에 로딩되는 URL이 창의 방문 기록에 새내용을 생성할지 방문 기록의 현재 내용을 대체해야할지 지정하는 불리언 값이면 생략 가능. 이 전달 인자의 값이 true이면, 새기록이 만들어지지 않는다. 이 전달 인자는 이름 붙은 기존 창의 내용을 바꾸는데 사용하기 위해 만들어졌다는점을 명심.

 

window.​moveTo(x, y창을 절대위치로 이동 

window.moveBy(x, y) 창을 상대적인 크기만큼 이동한다.

window.resizeTo(width, height) 창 크기를 지정된 크기로 재조정한다.

window.resizeBy(width, height창 크기를 지정한 양만큼 재조정한다.

 

 

 

열리는 문서에 다음 스크립트를 추가하면 열리는 창을 최대화 시킬수 있다. 

 

      1. <script type="text/javascript">
      2.     self.moveTo(0,0); //창위치
      3.     self.resizeTo(screen.availWidth, screen.availHeight); //창크기
      4. </script>

 

단지 열리는 문서를 바로 실행한다면 위 코드가 있다고 하더라도 바로 적용되지 않을것이다.

 

출처: <https://m.blog.naver.com/PostView.nhn?blogId=javaking75&logNo=220077600650&proxyReferer=https%3A%2F%2Fwww.google.com%2F>

 

 

 

Posted by 철냄비짱
,

브라우저 확인

Front-End 2019. 12. 30. 07:43

// 익스플로러 체크

var agent = navigator.userAgent.toLowerCase();

if ( (navigator.appName == 'Netscape' && navigator.userAgent.search('Trident') != -1) || (agent.indexOf("msie") != -1) ) {

  alert("인터넷 익스플로러 브라우저 입니다.");

}

else {

  alert("인터넷 익스플로러 브라우저가 아닙니다.");

}

 

// 크롬 체크

var agent = navigator.userAgent.toLowerCase();

if (agent.indexOf("chrome") != -1) {

  alert("크롬 브라우저입니다.");

}

 

// 사파리나 체크

var agent = navigator.userAgent.toLowerCase();

if (agent.indexOf("safari") != -1) {

  alert("사파리 브라우저입니다.");

}

 

// 파이어폭스 체크

var agent = navigator.userAgent.toLowerCase();

if (agent.indexOf("firefox") != -1) {

  alert("파이어폭스 브라우저입니다.");

}

Posted by 철냄비짱
,

JSP의 위치 

src/main/webapp/WEB-INF/jsp

 

기존 SpringBoot는 src/main/resources/teamplates에 타임리프가 들어가면 간단하게 조회된다.

 

그렇다면 JSP는 위치가 다른데 어떻게?

 

1. gradle, maven이면 디펜던시를 추가해야한다.

 

gradle의 경우

compile("javax.servlet:jstl")

compile("org.apache.tomcat.embed:tomcat-embed-jasper")

- 필요하다면 버전을 추가한다, 필자의 경우 springboot 플러그인으로 알아서 버전을 찾아준다.

 

maven의 경우

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

</dependency>

<dependency>

<groupId>org.apache.tomcat.embed</groupId>

<artifactId>tomcat-embed-jasper</artifactId>

</dependency>

- maven도 마찬가지로 버전이 필요하면 추가한다.

 

 

 

2. 자바 설정 혹은 application.properties에 경로를 지정한다.

@Configuration

public class SpringConfig extends WebMvcConfigurerAdapter {

@Bean

public ViewResolver getViewResolver() {

InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

viewResolver.setPrefix("/WEB-INF/jsp/");

viewResolver.setSuffix(".jsp");

return viewResolver;

}

}

 

혹은

 

spring.mvc.view.prefix: /WEB-INF/jsp/

spring.mvc.view.suffix: .jsp

 

 

 

참고)

 

시작점 코드(com.mysample.root)

@SpringBootApplication

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

}

@SpringBootApplication에는 

@EnableAutoConfiguration

@ComponentScan이 포함되어 자동으로 하위  package 경로(com.mysample.root이하)는 자동으로 읽는다.

 

출처: https://seongtak-yoon.tistory.com/23 [테이키스토리]

Posted by 철냄비짱
,

Spring Annotation

JAVA 2019. 9. 30. 20:48

1. HttpServletRequest, HttpServletResponse


 

2. HttpSession


 

3. Local

 - java.util.Locale 지역 정보


 

4. InputStream, Reader

 - HttpServletRequest의 getInputStream(), Reader


 

5. OutputStream, Writer

 - HttpServletResponse의 getOutputStream(), Writer - 서블릿 형태로 만들때 사용한다.


 

6. @PathVariable

 - @RequestMapping의 URL {} 부분의 패스 변수를 받는다.

    만약 타입이 틀린 값이 들어오면 HTTP 400 - Bad Request 가 전달 된다.

?

1

2

@RequestMapping("/board/{id}")

public void view( @PathVariable("id") int id ) {...}

 


 

7. @RequestParam

 - 스프링 내장 변환기가 다룰 수 있는 모든 타입을 지원한다.

   해당 파라미터가 없다면 HTTP 400 - Bad Request 가 전달 된다.

 -  file의 경우는 <input type="file" name="file" /> 에 매핑 된다.

?

1

2

3

public String edit( @RequestParam("id") int id,

            @RequestParam("title") String title,

            @RequestParam("file") MultipartFile file ) {...}

 

 -  맵 형태로 받으면 모든 파라미터 이름은 맵의 키에 파라미터 값은 맵의 값에 담긴다. 

?

1

public String add( @RequestParam Map<String, String> params ) {...}


 

-  파라미터가 필수가 아니라면 required = false 로 지정하면 된다. 

   이때 파라미터가 없으면 NULL이 들어간다. default 값을 지정 할 수도 있다. 

?

1

2

3

public void view( @RequestParam(value = "id",

                        required = false,

                        defaultValue = "0" )  int id) {..}.

 


 

8. @CookieValue

 - @RequestParam과 동일 하며 쿠키값을 가져올 때 사용한다.

?

1

2

public String check( @CookieValue("check") String check,

                required = false, defaultValue = "" ) {...}

 


 

9. @RequestHeader

 - 헤더 정보를 메소드 파라미터에 넣어 준다. Ajax로 처리할때 $.ajax(...) 에서 head에 특정 값을 넣고 여기서 받아서 

   있으면 ajax이고 없으면 일반페이지라는 식으로 이용하면 된다.

?

1

public String header( @RrequestHeader("ajax") String ajax ) {...}

 


 

10. Map, Model, ModelMap

 - view를 String으로 리턴해 주고 Attribute를 Map, Model, ModelMap 에 담을 수 있다.

 

11. @ModelAttribute

 - 파라미터를 Object형태로 받을때 사용된다. 일반적인 파라미터 형태로 쓰인 경우 타입이 일치하지 않으면 객체에 매핑 되지 

   않으며 에러는 발생 시키지 않는다. 자동으로 ModelMap에 담기므로 modelMap.addAttribute를 해 줄 필요가 없다.

?

1

public void update( @ModelAttribute("board") Board board) {...}


 

 - 메소드에도 @ModelAttribute를 설정 할 수 있다. 리턴값이 항상 나머지 컨트롤러에 자동 추가 되며 보통 참조용 데이터 등에 

   이용된다.

?

1

2

@ModelAttribute("emailList")

public Map<String, String> getEmailList() { ... }

 


 

12. Errors, BindingResult

  - 모델의 값을 검정한다. 이때 BindingResult나 Errors의 파라미터 값의 위치는 반드시 @ModelAttribute 뒤에 위치해야 한다. 

     자신의 바로 앞에 있는 @ModelAttribute 파라미터의 검정 작업만 하기 때문이다.

?

1

2

@RequestMapping(value = "/board/add", method = RequestMethod.POST)

public String add( @ModelAttribute("board") Board board, BindingResult result ) {...}

 


 

13. SessionStatus

 - 모델 오브젝트를 세션에 저장하여 계속 사용한다. 더이상 모델 오브젝트를 사용하지 않을 때는 세션에서 제거해 줘야 한다.


 

14. @RequestBody

 - HTTP body 부분만 전달 한다. XML 이나 JSON 으로 출력 할 경우 사용한다.

   리턴타입의 @ResponseBody 를 참조하자.

 

15. @Value

 - 프로퍼티값이나 값을 파라미터에 적용한다.

?

1

2

3

4

5

6

7

8

9

public class BoardController {

    @Value("${eng.url}")

    String engUrl;

 

    @RequestMapping(..)

    public String gotoEng() {

        return this.engUrl;

    }

}

 

 - 위는 프로퍼티중 eng.url 의 값을 String engUrl에 매핑 시키고 메소드에서 사용한 케이스다. 파라미터에도 적용 된다.

?

1

2

3

public String gotoEng( @Value("${eng.url}") String engUrl ) {

    return engUrl;

}

 


 

16. @Valid

 - JSR - 303 검증기를 이용해서 @ModelAttribute를 검정하도록 한다.

?

1

public String add( @Valid @ModelAttribute("board") Board board, BindingResult result ) { ...}


 

Posted by 철냄비짱
,

로컬개발 후 서버 적용을 지키기 위해

데이터베이스 덤프와 밀어넣는 작업을 자주 한다.

 

MySQL Error 2006 : MySQL server has gone away

상기 에러는 대용량 작업이 패킷사이즈보다 커서 생기는 에러.

 

 

set GLOBAL max_allowed_packet = 1024 * 1024 * 64;
set SESSION max_allowed_packet = 1024 * 1024 * 64; 

 

 

Posted by 철냄비짱
,

1. my.cnf 파일 내용을 아래와 같이 수정한다.(Mysql, MariaDB 설정 파일)


명령어 : vi /etc/my.cnf [엔터]


[client]

default-character-set = utf8


[mysqld]

init_connect = SET collation_connection = utf8_general_ci

init_connect = SET NAMES utf8

character-set-server = utf8

collation-server = utf8_general_ci


[mysqldump]

default-character-set = utf8


[mysql]

default-character-set = utf8


2. 위 내용을 추가 한 후, my.cnf 파일을 저장 한다.

3. 내용을 추가 한 뒤, 설정한 내용을 적용 하기 위해 mysql을 재시작 한다.

   - 명령어 :  service mysqld restart 또는 /etc/init.d/mysql restart

                   (MariaDB도 Mysql 명령과 동일 함.)

4. DB에 접속 하여 정상적으로 적용 되었는지 확인 한다.

   - 명령어 :  mysql -u root -p [엔터]


> show variables like 'c%';

+--------------------------+-----------------------------------------+

| Variable_name            | Value                                   |

+--------------------------+-----------------------------------------+

| character_set_client     | utf8                                    |

| character_set_connection | utf8                                    |

| character_set_database   | utf8                                    |

| character_set_filesystem | binary                                  |

| character_set_results    | utf8                                    |

| character_set_server     | utf8                                    |

| character_set_system     | utf8                                    |

| character_sets_dir       | /usr/local/server/mysql/share/charsets/ |

| collation_connection     | utf8_general_ci                         |

| collation_database       | utf8_general_ci                         |

| collation_server         | utf8_general_ci                         |

| completion_type          | NO_CHAIN                                |

| concurrent_insert        | AUTO                                    |

| connect_timeout          | 10                                      |

+--------------------------+-----------------------------------------

Posted by 철냄비짱
,

Groupby

예약어가 무조건 전체 그룹으로 묶여야만 하는 설정 해제

 

[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

Posted by 철냄비짱
,

시작 프로그램 삭제

Windows 2019. 9. 30. 13:31

윈도우키 + R --> 실행창 띄우기

실행창에서 + msconfig --> 시스템 구성 유틸리티

 

시스템 구성 유틸리티를 실행한 후,

시작프로그램 확인.

 

윈도우 + R --> 실행창

regedit 실행

 

1. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

2. HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

3. HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run

3. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\MSConfig\startupreg

4. 윈도우 > 모든 프로그램 > 시작프로그램 에 있는 경우

Posted by 철냄비짱
,