웹성능최적화 20130405

Preview:

Citation preview

[명사] 개발의 요런 면 조런 면

전주형

1. NHN Convention Guide (Front-End)

2. Java Code Convention (Back-End)

3. 웹사이트 성능 최적화

4. Springframework Utils

코드를 최초로 작성한 사람이 끝까지 유지보수할 확률은?

빠르고 정확하게 이해할 수 있도록 작성하면 유지보수 비용은 절감되고 업무 효율은 높아진다.

멤버간 코드 공유가 쉬워짐

잘못된 예 올바른 예

Btn btn

2btn btn2

sectionLst section_lst

section_list_style_type Section_lst_type

section1, section2

영문 소문자로 시작, 단어와 단어사이는 underscore(_)로 구분

예약어 설명

wrap 감싸기

header 머리글

gnb Global Navigation Bar

sta Service Title Area

lnb Local Navigation Bar

container 컨테이너

spot 강조하는 상위 컨텐츠

snb Side Navigation Bar

nav Navigation

pop_wrap 팝업 페이지 전체 영역

잘못된 예 올바른 예 설명

on_recommend_tab1 tab1_recomm_on 형태_의미_상태

bnm.gif btn_naver_mail.gif 임의로 축약 금지

btn_search_naver_mail.gif

btn_srch_mail.gif 3단계 이하로 조정

btn_Search.gif btn_srch.gif

형태, 의미, 상태 순으로..

잘못된 예 올바른 예

<SPAN Class=“desc”> <span class=“desc”>

<img src=‘test.gif’ width=‘100’ <img src=“test.gif” width=“100”

<a href=“…&nid=2” <a href=“…&amp;nid=2”

<input type="text" id="user_id" name="user_id" onfocus="this.className='focus'">

<!-- [D] 입력 박스에 포커싱되었을 때, class="focus" 추가 --> <input type="text" id="user_id" name="user_id" class="focus">

자식 엘리먼트 들여쓰기는 1탭, 1탭은 공백 4칸

table, ul, ol, dl 등은 들여쓰기 하지 않음

<!-- GNB --> 시작 주석

<!-- //GNB --> 종료 주석

<!DOCTYPE html>

<html lang="ko">

<head>

<meta charset="utf-8">

<title>메뉴 :: 브랜드명 서비스</title>

<link rel="stylesheet" type="text/css" href="sevice_name.css">

</head>

<body>

<div id="wrap">

<!-- header -->

<div id="header">

</div>

<!-- //header -->

<!-- container -->

<div id="container">

<!-- content -->

<div id="content">

</div>

<!-- //content -->

</div>

<!-- //container -->

<!-- footer -->

<div id="footer">

</div>

<!-- //footer -->

</div>

</body>

</html>

<!doctype html> <html lang="ko"> <head> <meta charset="utf-8"> <meta name="viewport" content=".."> <title>상단: 헤더명</title> <link rel="stylesheet" type="text/css" href="css/.."> </head> <body class=".."> <div class="u_skip"><a href="#ct">본문 바로가기</a></div> <!-- header --> <header role="banner"> </header> <!-- //header --> <hr /> <!-- ct --> <div id="ct" role="main"> </div> <!-- //ct --> <hr /> <!-- footer --> <!-- //footer --> </body> </html>

일반

모바일

<input type="text" id="user_id" title="사용자ID" class="input_txt" style="width:100px">

class style은 맨 뒤로 순서는 class 뒤에 style

<table>

<tr>

<td></td>

</tr>

</table>

<TABLE>

<caption>table element</caption>

<COLGROUP >

<COL width=“20”>

<COL width=“20”>

</COLGROUP>

<THEAD>

<TR><td> ...header information... </td>

</THEAD>

<TFOOT>

<TR><td> ...footer information... </td>

</TFOOT>

<TBODY>

<TR><td> ...first row of block one data... </td>

<TR><td> ...second row of block one data... </td>

</TBODY>

<TBODY>

<TR><td> ...first row of block two data... </td>

<TR><td> ...second row of block two data... </td>

<TR><td> ...third row of block two data... </td>

</TBODY>

</TABLE>

CSS 코드 작성 규칙

웹 접근성 보장 방법

CSS Sprites 사용 방법

예약어 목록

1. 시작 주석

2. package 와 import 문장

3. 클래스와 인터페이스 선언

/* * 클래스 이름 * * 버전정보 * * 날짜 * * 저작권 */

선언 설명

1 주석 (/*...*/) 하나의 클래스 또는 인터페이스 범위의 정 보들을 포함해야 한다.

2 클래스(static) 변수 public, protected, private 클래스 변수 순으로 선언

3 인스턴스 변수 클래스 변수와 동일

4 생성자

5 메서드 접근성보다는 기능별로 그룹화

들여쓰기는 4개의 스페이스를 사용해야 됨.

1탭은 8개의 스페이스를 써야된다고 함.

현재 eclipse의 1탭은 4스페이스

한 줄에 80 자 이상 쓰는 것은 대부분의 터미널과 툴에서 다룰 수 없기 때문에 피해야 함

콤마 후에 분리

연산자(Operator)전에 분리

레벨이 낮은 원칙 보다는 레벨이 높은 원칙에 따라서 분리

앞줄과 같은 레벨의 조건식이 시작되는 새로운 줄은 앞줄과 들여쓰기를 일치시킨다.

function(longExpression1, longExpression2, longExpression3, longExpression4, longExpression5); var = function1(longExpression1, function2(longExpression2, longExpression3)); longName1 = longName2 * (longName3 + longName4 - longName5) + 4 * longname6; longName1 = longName2 * (longName3 + longName4 - longName5) + 4 * longname6;

BAD

GOOD

//INDENT 8 SPACES TO AVOID VERY DEEP INDENTS private static synchronized horkingLongMethodName(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... }

//DONT USE THIS INDENTATION if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { //BAD WRAPS doSomethingAboutIt(); //MAKE THIS LINE EASY TO MISS } //USE THIS INDENTATION INSTEAD if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); } //OR USE THIS if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); }

Javadoc 툴을 이용해 html파일로 된 api문서를 만들 수 있음

/** ….. */

자세한 내용은 javadoc 문서 참고

int level,size; int level; int size; int level; // indentation level int size; // size of table Object currentEntry; // currently selected table entry int level; // indentation level int size; // size of table Object currentEntry; // currently selected table entry

GOOD

BAD

void myMethod() { int int1 = 0; // 메서드 블록의 시작

if (condition) { int int2 = 0; // if 블록의 시작 ... } }

변수사용 바로 전에 선언 하는 것이 아님

• 메서드명과 그 메서드의 “(“ 사이에는 스페이스가 없어야 한다.

• 여는 중괄호 “{“ 는 선언문과 같은 줄의 끝에 위치

• 닫는 괄호 “}” 는 “}” 가 “{“ 후에 즉시 나타나야 하는 null 문장일 경우를 제외하고는 여는 문장과

일치하는 들여쓰기를 하는 새로운 줄에서 시작해야 한다.

class Sample extends Object { int ivar1; int ivar2; Sample(int i, int j) { ivar1 = i; ivar2 = j; } int emptyMethod() {} ... }

argv++;

argc--;

argv++; argc--;

GOOD

BAD

if (condition) statement;

if (condition) { statement;

}

BAD

GOOD

switch (condition) {

case ABC: statements; /* 다음 문장 수행됨 */

case DEF: statements; break;

case XYZ: statements; break;

default: statements; break;

}

모든 switch문에 default 포함

2개의 빈줄

소스 파일의 섹션들 사이

클래스와 인터페이스의 정의 사이

1개의 빈줄

메서드들 사이 메서드 안에서의 지역 변수와 그 메서드의 첫 번째 문장 사이

block 주석 또는 single-line 주석 전

가독성을 향상시키기 위해서 메서드 내부의 논리적인 섹션들 사이

괄호뒤에 나오는 키워드는 스페이스로 나눔

while (true) {

...

}

메서드 호출과 키워드를 구분하는데 도움

a += c + d;

a = (a + b) / (c * d);

while (d++ = s++) {

n++;

}

prints("size is " + foo + "\n");

연산자는 스페이스로 분리, 단항연산자는 제외

for (expr1; expr2; expr3)

myMethod((byte) aNum, (Object) x);

myFunc((int) (cp + 5), ((int) (i + 3))

+ 1);

식별자 형태 이름 붙이는 규칙 예제

Packages 유일한 패키지 이름의 앞 부분은 항상 모두 소문자 ASCII 문자로 쓰고, 가장 높은 레벨의 도메인 이름 중 하나이어야 한다. 현재는 com, edu, gov, mil, net, org, 또는 1981 년 ISO Standard 316 에 명시화 된 나라 구별 코드 영어 두문자가 쓰인다. 패키지 이름의 나머지 부분은 조직 내부의 naming convention 을 따르면 된다. 이러한 convention 은 디렉토리 이름 구조로 명시화 될 것이다. 예를 들어 국, 부서, 프로젝트, 기계, 또는 로그인 이름 등이다.

com.sun.eng com.apple.quicktime.v2 edu.cmu.cs.bovik.cheese

Interfaces 인터페이스 이름도 클래스 이름처럼 대문자화 되어야 한다.

interface RasterDelegate; interface Storing;

식별자 형태 이름 붙이는 규칙 예제

Classes 클래스명은 명사이어야 하며, 복합 단어일경우 각 단어의 첫 글자는 대문자이어야 한다. 클래스 이름은 간단하고 명시적이어야 한다. 전체 단어를 사용하고 두문자어와 약어는 피해라(만약 약어가 URL 이나 HTML같이 더 많이 넓게 사용되어진다면 사용해도좋다).

class Raster; class ImageSprite;

Methods 메서드명은 동사이어야 하며, 복합된 경우 첫 문자는 소문자이고 각각 내부 단어의 첫 문자는 대문자로 써야 한다.

run(); runFast(); getBackground();

식별자 형태 이름 붙이는 규칙 예제

Variables 변수 이름의 첫 번째 문자는 소문자로 시작 하고, 각각의 내부 단어의 첫 번째 문자는 대 문자로 시작해야 한다. 변수 이름이 _ 또는 달러 표시 문자로 시작하는 것이 허용되기는 하지만 이것으로 시작해서는 안 된다. 변수 이름은 짧지만 의미 있어야 한다. 변수 이름의 선택은 그 변수의 사용 의도를 알아 낼 수 있도록 의미적이어야 한다. 한 문자 변 수 이름은 임시적으로 쓰고 버릴 변수일 경 우를 제외하고는 피해야 한다. 보통의 임시 변수들의 이름은 integer 일 경우에는 i, j, k, m, m 을 사용하고, character 일 경우에는 c, d, e를 사용한다.

Int i; char c; float myWidth;

식별자 형태 이름 붙이는 규칙 예제

Constants 클래스 상수로 선언되어진 변수들과 ANSI 상수들의 이름은 모두 대문자로 쓰고 각각의 단어는 언더바(“ _” )에 의해 분리 되어져야한다(디버깅을 쉽게 하기 위해서 ANSI 상수들은 피해야 한다.)

static final int MIN_WIDTH = 4; static final int MAX_WIDTH = 999; static final int GET_THE_CPU = 1;

괄호 if (a == b && c == d)

if ((a == b) && (c == d))

반환값 if (condition) {

return x;

}

return y;

return (condition ? x : y);

GOOD

BAD

BAD

GOOD

과거엔 주로 백엔드(back-end) 요소인 서버 프로그램이나 데이터베이스 등에 초점을 맞춤

야후 성능개선팀 조사결과 프런트엔드(front-end) 영역에서 대기하는 시간이 웹페이지 속도의 80~90%를 차지함

현재는 웹사이트 성능 최적화 시에 야후의 우수 사례를 많이 사용함

많은 시간을 image, stylesheet, script, flash 파일들을 다운 받는데 사용함

Script와 css 파일을 결합

Image를 CSS Sprite 기법과 Image map을 만들어서 사용함

네이버 메일 이미지

Javascript 와 css 파일을 결합하고 최소화시켜줌

http://code.google.com/p/minify/

Combine CSS

https://developers.google.com/speed/docs/pss/CombineCSS

ExpiresByType text/html "access plus 1 month 15 days 2 hours"

Header set Cache-Control “max-age=86400, public”

잘못 사용하면 파일명을 바꿔야 되기 때문에 common_1.0.0.js 와 같이 파일명을 정함

<IfModule mod_deflate.c>

SetOutputFilter DEFLATE AddOutputFilterByType text/html text/plain text/xml text/javascript AddType text/javascript .js AddType text/css .css

</IfModule>

ms 정도의 미미한 성능 향상

HTML 명세서에도 스타일시트는 page의 HEAD 안에 포함되어 있어야 한다고 함

실제 야후 성능개선팀에 연구한 결과 HEAD에 있을 때 속도가 가장 빨랐음.

문서의 하단에 놓았을 때 style이 변경됐을 때 제대로 rendering이 안되는 경우가 있음.

Script를 위쪽에 두게 되면 다운로드 시간만큼 페이지 rendering이 지연됨.

현재 대부분의 브라우저에서 hostname 당 최대 6개의 동시 접속이 가능함.

http://www.browserscope.org/?category=network

특별한 경우가 없는 한 script는 문서의 아래쪽에 위치함.

브라우저에 의해 캐쉬되기 때문에 외부 파일로 정의해야 함.

보통 hostname을 가지고 ip를 검색하는데 소요되는 시간이 20~120ms 임.

DNS lookup도 캐쉬(os, browser)가 되기 때문에 특별히 문제가 되지 않음

현재 서비스 중인 도메인 외의 외부 도메인 사용을 줄이라는 얘기임.

JSMin, YUI Compressor 를 이용해 javascript 에서 불필요한 내용을 제거한다.

YUI Compressor는 css 압축도 지원함.

미국 상위 10개의 웹사이트 중 2곳이 중복된 스크립트가 있다고 함.

Entity Tags(ETags) 는 브라우저에 캐쉬된 자원이 서버의 것과 맞는지 확인하는데 사용함.

HTTP/1.1 200 OK

Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT

ETag: "10c24bc-4ab-457e1c1f"

Content-Length: 12195

GET /i/yahoo.gif HTTP/1.1

Host: us.yimg.com

If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT

If-None-Match: "10c24bc-4ab-457e1c1f"

HTTP/1.1 304 Not Modified

최초 응답

캐쉬 후 요청

캐쉬 후 응답

POST 방식은 Header를 먼저 보내고 data를 보냄

GET 방식은 쿠키가 많지 않다면 하나의 TCP Packet만 보냄

IE에서 URL 최대 길이는 2K 이기 때문에 사용시 주의 해야함.

자바스크립트에서 DOM 접근 시 느려짐.

레이아웃을 위한 table 태그 사용은 지양해야됨.

<img width="100" height="100" src="mycat.jpg" alt="My Cat" />

mycat.jpg는 500 x 500 px

host의 root에 favicon 파일을 만들어 놓음

최대한 작게 그리고 Expire 등 헤더값을 셋팅해서 캐쉬되게 만듬.

YSlow

http://developer.yahoo.com/yslow/

if(userName != null && userName.equals(""))

import org.springframework.util.StringUtils; if(StringUtils.hasText(userName))

try { Assert.isTrue(i > 0, "The value must be greater than zero");

Assert.notNull(userName, “username is required");

…… } catch(IllegalArgumentException ex) { logger.error(ex.getMessage());

}

Assertion utility class that assists in validating arguments

File originFile = new File(/svc/originFile.txt);

File copiedFile = new File(/svc/copiedFile.txt);

FileCopyUtils.copy(originFile, copiedFile);

int pageNo = 1;

if(StringUtils.hasText(request.getParameter("pageNo"))) { pageNo = Integer.parseInt(request.getParameter("pageNo"));

}

import org.springframework.web.bind.ServletRequestUtils; int pageNo = ServletRequestUtils.getIntParameter(request, “pageNo”, 1);

DigestUtils

FileSystemUtils

AntPathMatcher

StopWatch

Nobody is better than you

Nobody is smarter than you

- Brian tracy -

Recommended