반응형
AspectJ Pointcut 표현식(aspectj expression), execution, within, bean

pointcut :  이란 충고를 받을 메소드를 정의한 것이다.
execution: 메소드 실행 결합점(join points)과 일치시키는데 사용된다.
within: 특정 타입에 속하는 결합점(join point)을 정의.

execution(public * *(..)) : public 메소드가 포인트 컷

execution(* onj.spring.aop.*.*(..)) : onj.spring.aop 패키지의 모든 메소드가 포인트 컷

execution(* onj.spring.aop..*.*(..)) : onj.spring.aop 패키지와 하위 패키지의 모든 메소드가 포인트 컷

execution(public void insert*(..)) : public에 리턴값, 패키지명 없고 메서드 이름은 insert로 시작, 인자값은 0개 이상인 메서드가 포인트 컷

execution(* onj.spring.aop.*.*()) : 리턴형 관계없고 onj.spring.aop 패키지의 모든 클래스, 인자값이 없는 모든 메서드가 포인트 컷

execution(* onj.spring.aop..*.*(..)) : 리턴형 관계없고 onj.spring.aop 패키지 및 하위 패키지에 있는 모든 클래스,  인자값이 0개 이상인 메서드가 포인트 컷

execution(* delete*(*)) : 메서드 이름이 delete으로 시작하는 인자값이 1개인 메서드가 포인트 컷

execution(* delete*(*,*)) : 메서드 이름이 delete로 시작하는 인자값이 2개인 메서드가 포인트 컷

execution(* onj*(Integer, ..)) : 메서드 이름이 onj로 시작하고 첫번째 인자값의 타입이 Integer, 1개 이상의 매개변수를 갖는 메서드가 포인트 컷

within(onj.spring.aop.*) : onj.spring.aop 패키지 내의 모든 메소드가 포인트 컷

within(onj.spring.aop..*) : onj.spring.aop패키지 및 하위 패키지의 모든 메소드가 포인트 컷

bean(oraclejava*) : 이름이 oraclejava로 시작되는 모든 빈의 메소드가 포인트 컷

bean(*dataSource) || bean(*DataSource) : 빈 이름이 “dataSource” 나 “DataSource” 으로 끝나는 모든 빈의 메소드가 포인트 컷

!bean(onjoraclejava) : onjoraclejava빈을 제외한 모든 빈의 메소드가 포인트 컷


출처 : http://www.oraclejavanew.kr/bbs/board.php?bo_table=LecSpring&wr_id=330

반응형
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,
반응형

1. 프로젝트 개요

- 프로젝트명    :    웹사이트 제작도구

- 설명             :    drag & drop, WYSIWYG 기반 웹사이트 제작툴

2. 개발환경

- 개발언어       :   JSP, javascript

- 데이터베이스 :    Oracle 10g XE 

- 프레임워크    :    Spring FrameWork 3.1 

 - 웹서버 : Tomcat 6.0

3. 개발목적 및 특징

사용된 라이브러리 

  - Jquery

  - Bootstrap

  - Dynadiv

  - ckeditor



4. 비고 

- 2013 강원대학교 IT대학 졸업작품 경진대회 최우수상 수상

반응형
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,
반응형

1. 프로젝트 개요

- 프로젝트명    :    조경 매물 거래사이트

- 설명             :    위치기반 조경수를 거래하는 사이트

2. 개발환경

- 개발언어       :    JSP

- 데이터베이스 :    Oracle 10g XE 

- 프레임워크    :    Spring FrameWork 3.1

3. 개발목적 및 특징

 사용된 라이브러리 

  - Jquery

  - 구글맵 API




4. 기타

- 외주


반응형
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,
반응형

1. 프로젝트 개요

- 프로젝트명    :   교육용 과학언어 분석 프로그램

- 설명             :    교육용 과학언어 분석

2. 개발환경

- 개발시기       :    2012.09 - 2012.12

- 개발언어       :    JSP

- 데이터베이스 :    Oracle 10g XE 

- 프레임워크    :    Spring FrameWork 3.1

3. 개발목적 및 특징

사용된 라이브러리 

  - Jquery

  - 한나눔 형태소 분석기(카이스트)




4. 기타

- 연구실 외주


반응형
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,
반응형

자바의 메모리구조를 이야기하기전에 JVM에대해서 설명해보자


JVM은 Java Virtual Machine의 약자로써

일반적인 프로그램이 OS위에서 동작하는데 반해

자바 프로그램은 OS위의 JVM에서 동작한다.


이것은 플랫폼에 독립적인 자바의 특징을 보여주며,

자바로 작성된 프로그램이 플랫폼에 무관하게 동작하고,

이러한 프로그램이 최적의 성능으로 돌아가기 위해서는

JVM의 동작을 잘 이해하는 것이 필요하다.


JVM의 영역은 크게 아래와 같이 나뉜다.

1. Class Loader

 > JVM에서 Runtime Data영역으로 클래스를 로드하고 Linking한다. 

 > Runtime시 동적으로 로드가 가능하다.

2. Execution Engine

 > Class Loader에서 Runtime Data영역으로 로드된 클래스의 바이트 코드를 실행 

 > 실행 엔진은 자바의 바이트코드를 명령어 단위로 읽어서 실행

3. Garbage Collector

 > Garbage Collection을 수행하는 모듈 쓰레드를 지칭한다.

 > 사용되지 않는 메모리를 확보하는등의 메모리 관리를 수행한다.

4. Runtime Data Area

 > JVM이 OS로부터 할당받는 메모리 영역으로 6가지로 나뉜다.


JVM의 기본적인 수행 절차는 다음과 같다.

1. 자바로 프로그램 코드를 작성(.java)

2. 컴파일 과정을 통해 바이트코드 생성(.class)

3. 클래스 로더에서 런타임 데이터 영역으로 적재한다.

4. 적제된 코드에 대한 정보를 런타임 영역이 가지고 있고

5. Execution Engine을 통해 실행된다.


JVM의 런타임 영역은 다음과 같이 나뉜다.

1. 클래스 영역

2. 스태틱 영역

3. 상수 영역

4. 힙 영역

5. native 메소드 영역

6. PC 레지스터


힙 영역에서 GC가 일어나는데

힙은 기본적으로 Young영역과 Old 영역으로 나뉜다.


이렇게 두가지로 나뉜 배경에는

첫째로 대부분의 객체는 금방 접근 불가능한 상태가 되며,

두번째는 오래된 객체에서 신규 객체로의 참조는 거의 없다는 것을 전재로 한다.


객체가 Young영역에서 Old영역으로 이동하는것을 Minor GC라고 하고

Old영역이 가득차 객체가 삭제되는 것을 Major GC라고 한다.


Young영역은 또 크게 3가지 영역으로 나뉘는데,

객체가 가장 먼저 등록되는 Eden영역,

그리고 이 객체들이 이동하는 두개의 Survivor영역이다.

하나의 Survivor영역이 가득차면 살아남은 객체를 두번째 Survivor영역으로 이동하고

가득찬 Survivor영역에서 GC가 일어난다.

그렇기때문에 두개의 Survivor영역중 하나는 무조건 비어있어야한다.


Major GC가 일어나면 STW(Stop the world)라는 현상이 발생하는데

JVM내에서 GC를 제외한 어플리케이션이 멈추는 현상으로

이는 서비스에 치명적이기 때문에 Major GC를 최소화하는 전략이 중요하다.


GC의 알고리즘은 몇가지로 나뉘는데 

1. 시리얼 알고리즘

- 적은 메모리와 적은 코어에 적합 (정렬방식)

2. 병렬 알고리즘

- GC를 처리할때 멀티 쓰레드를 지원

3. CMS 알고리즘

-  STW 시간이 짧지만 메모리와 CPU의 사용이 많음 (바둑판방식)

4. G1(Garbage First)알고리즘

- 최신 알고리즘. 성능이 가장 좋다. 대규모에 적합

- Young영역을 나눠서 GC. STW 발생

- Old 영역을 나눠서 STW없이 GC. 


등이 있다.


반응형
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,

게임 용어

IT 2017. 9. 5. 12:38
반응형

[유저관련 지표]


UV (Unique visitor) : 일정기간 내에 게임의 접속(방문)한 실제 유저 수로 한 유저가 여러번 방문해도 1로 카운트 한다.


DAU (Daily Active User) : 일단위로 측정한 UV


WAU (Week Active User) : 주단위로 측정한 UV


MAU (Monthly Active User) : 월 단위로 UV 측정


RU (Registered User) : 일정기간내에 게임에 등록된 유저 수


NRU (New Registered User) : 일정기간내에 등록된 신규 유저 수.


ARU (Accumulate Register User): 해당 기간까지의 등록된 누적 유저 수


재방문 UV : 해당 기간 동안 게임 클라이언트에 2회 이상 로그인한 회원 수


MUV (Multigame Unique Visitor): 해당 기간 동안 게임 클라이언트에 로그인하여 실제 게임을 플레이 한 회원 수


MTS (Mutigame Time Spent): 해당 기간 동안의 평균 실제 플레이 타임


TS(Time Spent) : 해당기간 동안의 유저1인당 플레이 타임


CCU (Concurrent User) : 특정 시점에 접속한 동시 접속자 수


MCU (Maxium Concurrent User) : 하루 동안 가장 높은 동시접속자 수치.


PCU (Peak Concurrent User) : MCU 동일어


ACU (Average Concurrent User) : 1일 동안의 평균 동시 접속자 수


Stickness : 고착도


EU (Executed User) : 인게임을 플레이한 유저로UV와 같이 비교대상으로 분석


 


 [매출 관련 지표]


BU (Buying user) : 구매유저, 일정기간내에 게임에 아이템 구매, 월정액 결제 등 돈을 지불한 유저


PU (Paying User) : BU 동일어


BU rate = BU/UV (순방문자대비 결제 유저 비율)


CAC(Customer Acquisition Cost) : 유저 확보 비용으로 유저 1인을 확보하는데 소모되는 비용


CRC (Customer Retention Cost) : 유저 유지 비용으로 일정기간내에 유저1인을 유지하는데 소모되는 비용


ARPU (Average Revenue Per User) : 일정 기간 내 유저 1인당 평균 수입


ARPPU (Average Revenue Per Paying User) :일정 기간내에 게임에 비용을 지불한 유저의 1인당 평균 수입


PPU (Percentage of Paying Users) : DAU 내에서 결제한 비율 또는 비율


LTV (Life time value) : 유저 1인당 게임에서 완전히 이탈할 때까지 지불하는 비용


Entry Cost : 여러 가지 가격대의 상품을 제공할 때 유저의 최초 구매가 어떤 가격대에서 많이 일어나는지 측정


Sales by Purchase : 사용자의 구매 활동을 통해 집계된 매출


Sales by Advertisement : 광고 노출을 통해 집계된 매출


CPI (Cost per Install) : 게임 다운로드 후 설치하면 보상


CPA (Cost per Action) : 설치된 앱을 실행하면 보상


CPP (Cost per Play) : CPA 이후 일정 기간 한번씩 실행할 때마다 보상


CPL (Cost per Level) : 정량적인 플레이에 대한 레벨을 설정한 뒤 보상


 


[투자 퍼블리싱 관련 용어]


MOU (Memorandum of understanding) : 투자 등 거래에 관해 합의한 사항을 명시한 사전 협의문서로 법적 구속력이 없으며 정식 계약 전 업무 준비/친선관계 개선/대외 홍보의 역할로 활용 한다.


Initial fee : 판권 제공/계약 체결 시 판권 부여를 대가로 수령하는 금액으로 흔히 계약금이라고 한다.


Running Royalty : 퍼블리셔가 개발사에게 매출액의 일정 비율을 지급하는 비용으로 러닝 개런티랑 동일하다.


MG(Minimum Guarantee) :  판권 제공자의 최소 러닝 로얄티를 보장해 주는 금액


RS (Revenue Share) : 판권제공사/퍼블리셔 간의 수익 분배 비율


PF (Project Financing) : 회사 지분에 대한 투자가 아닌 프로젝트 성공 수익에 대해 투자하는 투자 방식


KPI(Key Performance Indicator) : 핵심실행지표로 기업이나 조직의 목표달성과 전략을 위한 핵심측정지표


반응형

'IT' 카테고리의 다른 글

유용한 링크  (0) 2013.01.27
[팀블로그] 구글 에드센스 핀 등록  (0) 2013.01.20
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,

[secmon] 상태값

코드자료실 2017. 8. 28. 13:04
반응형

Category ID

프로세스 생성 (Process Create) 1

파일 생성 시간 변경 (File creation time changed) 2

네트워크 연결 탐지 (Network Connection Detected) 3

시스몬 상태 변경 (Sysmon service state changed) 4

프로세스 종료 (Process terminated) 5

드라이버 로드 (Driver loaded) 6

이미지 로드 (Image loaded) 7

스레드이벤트 생성 (CreatRemoteThread) 8

Disk/Volume Read 이벤트 (RawAccessRead*) 9

반응형
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,
반응형

// 사업자등록번호 검사
 function checkBizID(bizID)
 {
  var re = /-/g;
  var bizID = bizID.replace(re,'');
  var checkID = new Array(1, 3, 7, 1, 3, 7, 1, 3, 5, 1);
  var tmpBizID, i, chkSum=0, c2, remander;

  for (i=0; i<=7; i++){
   chkSum += checkID[i] * bizID.charAt(i);
  }

  c2 = "0" + (checkID[8] * bizID.charAt(8));
  c2 = c2.substring(c2.length - 2, c2.length);

  chkSum += Math.floor(c2.charAt(0)) + Math.floor(c2.charAt(1));

  remander = (10 - (chkSum % 10)) % 10 ;

  if (Math.floor(bizID.charAt(9)) == remander){
   return true; // OK!
  }
  return false;
 }

 

 // 법인번호 검사
 function isRegNo(sRegNo)
 {
  var re = /-/g;
  sRegNo = sRegNo.replace('-','');

  if (sRegNo.length != 13){
   return false;
  }

  var arr_regno  = sRegNo.split("");
  var arr_wt   = new Array(1,2,1,2,1,2,1,2,1,2,1,2);
  var iSum_regno  = 0;
  var iCheck_digit = 0;

  for (i = 0; i < 12; i++){
    iSum_regno +=  eval(arr_regno[i]) * eval(arr_wt[i]);
  }

  iCheck_digit = 10 - (iSum_regno % 10);

  iCheck_digit = iCheck_digit % 10;

  if (iCheck_digit != arr_regno[12]){
    return false;
  }
  return true;
 }

 

//주민등록번호 체크
//111111-1111118
function chkJumin(jumin) {
 if(jumin.match(/^\d{2}[0-1]\d[0-3]\d-[1-4]\d{6}$/) == null) {
  return false;
 }

 var chk = 0;
 var i;
 var last_num = jumin.substring(13, 14);
 var chk_num = '234567-892345';

 for(i = 0; i < 13; i++) {
  if(jumin.charAt(i) != '-')
   chk += ( parseInt(chk_num.charAt(i)) * parseInt(jumin.charAt(i)) );
 }

 chk = (11 - (chk % 11)) % 10;

 if (chk != last_num) return false;

 return true;
}

출처 : http://thdwns2.springnote.com/pages/894862

반응형

'코드자료실 > javascript' 카테고리의 다른 글

[jquery]onload 시점  (0) 2014.09.29
[jquery] ie7, ie6 json is undefined  (0) 2013.03.13
[jquery] long polling 기법 구현  (0) 2013.02.13
[jquery] jsonp 사용  (0) 2013.01.24
[jquery] jquery ui tabs  (0) 2013.01.16
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,
반응형

Go to start of metadata

동적 태그 라이브러리

Grails는 JSP와 GSP에서 사용할 수 있는 다양한 종류의 커스텀 태그를 내장하고 있지만(태그 라이브러리 래퍼런스 를 참고하세요), Grails의 간결한 동적 태그 라이브러리 메커니즘을 이용하면 개발자가 직접 단순 커스텀 태그(simple custom tags), 논리 커스텀 태그(logical custom tags), 반복 커스텀 태그(iterative custom tags)를 만들 수도 있습니다.

Grails 태그는 추가적인 설정이 필요 없고, TLD를 갱신할 필요도 없으며, 서버 재시작 없이 런타임에 자동으로 리로드 된다는 장점을 갖습니다. 이러한 특성 덕에 개발자들은 마치 뷰의 다른 부분들을 개발하는 것 처럼 점진적으로 유용성을 높여가며 태그를 개발할 수 있습니다.

경고

Icon

Grails 태그 라이브러리를 JSP에서 사용하려면 약간의 추가적인 작업이 필요합니다. Grails 태그 라이브러리는 동적이라는 특성으로 인해 JSP 보다는 GSP와 더 잘 연동됩니다. Grails 태그 라이브러리를 JSP에서 사용하는 방법을 알아보려면 마지막 섹션을 참고하세요.

단순 태그(Simple tags)

새 태그를 만들려면 "grails-app/taglib/ApplicationTagLib.groovy" 파일을 열어서 수정하거나, 이름이 "TagLib"로 끝나는 새 클래스를 만들어야 합니다. 단순 태그를 만들려면 클래스에 하나의 인자를 갖는 새로운 클로저 속성을 추가하면 됩니다. 이 인자는 태그의 속성 집합입니다:

def includeJs = { attrs ->
    out << "<script xsrc='scripts/${attrs['script']}.js' />"
}

이 태그를 GSP 페이지에서 호출하려면 "g" 접두사를 붙여서 태그 속성 이름을 적어주면 됩니다:

<g:includeJs script="myscript" />

논리 태그(Logical tags)

논리 태그를 만들려면 두 개의 인자를 갖는 클로저 속성을 추가해야 합니다. 첫 번째 인자는 태그의 속성 집합이고, 두 번째 인자는 태그의 본문(body)이며 인자 자체가 또 다른 클로저 입니다.

def isAdmin = { attrs, body ->
     def user = attrs['user']
     if(user != null && checkUserPrivs(user)) {
           body()
     }
}

위 태그는 사용자가 관리자(administrator)인지 판별한 후, 관리자인 경우에만 태그의 본문을 호출합니다:

<g:isAdmin user="${myUser}">
    // 관리자만 볼 수 있는 제한된 컨텐츠.
</g:isAdmin>

반복 태그(Iterative tags)

반복 태그를 만드는 것 또한 가능합니다:

def repeat = { attrs, body ->
    def i = Integer.valueOf( attrs["times"] )
    def current = 0
    i.times {
           body( ++current ) // 현재 반복 횟수(current)를 Groovy의 기본 인자인 "it"으로 넘김
    }
}

반복 태그를 호출하려면 아래와 같이 하면 됩니다:

<g:repeat times="3">
<p>3회 반복! 현재 반복 횟수 = ${it}</p>
</g:repeat>

태그를 이용하여 마크업 만들기

Grails는 태그를 이용하여 마크업을 만들 수 있도록 도와주는 특별한 메서드를 제공합니다. 마크업을 만드는 것은 태그의 일반적인 활용 사례 중 하나입니다. 마크업을 만들려면 'mkp' 메서드를 호출하면서 화면에 출력하고자 하는 마크업들과 함께 클러저를 전달해주면 됩니다:

def dialog = { attrs, body ->
      mkp {
          div('class':'dialog') {
              body()
          }
      }
}

GSP 태그를 메서드로써 호출하기

GSP 태그들은 GSP 페이지 안의 Groovy 표현식으로 사용될 수도 있습니다. 예를 들어 hasErrors 태그는 다음과 같이 평범한 태그로 쓰일수도 있고:

<g:hasErrors bean="${book}" field="title">
<span class='label error'>There were errors on the book title</span>
</g:hasErrors>

아래처럼 메서드로써 호출될 수도 있습니다:

<span id="title" class="label ${hasErrors(bean:book,field:'title','errors')}">Title</span>

메서드의 마지막 인자는 태그의 본문(body)으로 취급됩니다. 또는 아래와 같이 문자열을 반환하는 클로저를 넘겨도 됩니다:

<%=
hasErrors(bean:book,field:'title') {
'errors'
} %>

JSP에서 Grails 태그 라이브러리 사용하기

JSP에서 Grails 태그 라이브러리를 쓰려면 JSP의 "invokeTag" 태그를 이용하며 Grails의 태그 라이브러리를 호출해주면 됩니다.

<g:invokeTag name="includeJs" script="myscript" />
<g:invokeTag name="isAdmin" user="${myUser}">
    // some restricted content
</g:invokeTag >
<g:invokeTag name="repeat" times="3">
<p>Repeat this 3 times! Current repeat = <c:out value="${it}" /></p>
</g:invokeTag>

만약, Grails 태그를 다른 평범한 JSP 태그처럼 사용하려면 아래 단계를 수행해야 합니다:

1) Grails의 org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag 클래스를 상속받는 자바 클래스를 생성하고 생성자에서 "setName()" 메서드를 호출하여 여러분의 태그 이름을 전달해줍니다:

package com.mycompany.taglib;
public class IncludeJsTag extends JspInvokeGrailsTagLibTag {
   public static final String TAG_NAME = "includeJs";
   public IncludeJsTag() {
       super.setName(TAG_NAME);
   }
}

2) JSP에서는 각각의 태그에 대해 선언적 태그 라이브러리 정의(TLD)가 존재해야 합니다. 따라서 "web-app/WEB-INF/tld/grails.tld" 파일을 수정하여 여러분의 클래스를 지칭하는 적절한 엔트리를 추가해주어야 합니다:

<tag>
        <name>includeJs</name>
        <tag-class>com.mycompany.taglib.IncludeJsTag</tag-class>
        <body-content>JSP</body-content>
        <variable>
            <name-given>it</name-given>
            <variable-class>java.lang.Object</variable-class>
            <declare>true</declare>
            <scope>AT_BEGIN</scope>
        </variable>
        <dynamic-attributes>true</dynamic-attributes>
    </tag>

3) 이제 Grails 태그를 다른 평범한 JSP 태그처럼 호출할 수 있습니다:

<g:includeJs script="myscript" />

출처 : http://docs.codehaus.org/display/grails/korean+dynamic+tag+libraries

반응형
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,
반응형

Tomcat 서버에 특정 ip 만 접근 할 수 있게 설정하기

1. Tomcat 설치 위치에 conf 폴더 내의 context.xml 파일을 메모장 같은 Editor 로 연다 ( 편집하기 전에 미리 백업을 해두자 )
- Windows 경우 Default 설치 경로 : C:\Program Files\Apache Software Foundation\Tomcat 6.0
- Linux 의 경우 : /usr/local/tomcat

2. context.xml 파일의 맨 끝부분에 다음의 내용이 반드시 있는지 확인 한다
- <WatchedResource>WEB-INF/web.xml</WatchedResource>



3. </WatchedResource> 태그 다음 라인에 아래의 내용을 추가 한다. allow 항목에 허용하고 싶은 ip 를 넣는다. ip 가 여러개 일경우 192.168.1.22|192.168.1.33 과 같이 넣고 저장 한다
- <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="IP1|IP2|IP3"/>

4. Tomcat 을 다시 시작 한다
- Windows 경우 : Trayicon 영역에서 tomcat 아이콘을 찾아 마우스 오른쪽 마우스 클릭하여 Stop Service 후 Start Service 하면 된다
- Linux 의 경우 : /etc/init.d/tomcat restart 하면 된다

[ 주의 ]
- Tomcat 의 각종 설정 파일들 안에 한글 주석을 달 경우 주의 해야 한다. 각종 *.xml 파일들이 Tomcat 이 Start 할 때 Parse 되는데 이때 한글 주석을 만나면 Error 가 발생하며, Tomcat Service 는 올라 왔지만, 메인 Servlet 이 Load 실패 하기 때문에 해당 웹 페이지가 열리지 않는다.
어쩔 수 없이 한글 주석을 달아야 한다면, 해당 *.xml 파일의 맨 상단의 encoding='utf-8' 부분을 encoding='eucKR' 로 변경하고, Tomcat 을 재시작하면 된다


반응형

'코드자료실' 카테고리의 다른 글

[secmon] 상태값  (0) 2017.08.28
[grails] 동적 태그 라이브러리  (1) 2014.12.09
블로그 이미지

cocy

조금은 가볍게! 시작은 새롭게!

,