2018년 9월 27일 목요일

mysql 계층형 메뉴 정렬 하는 쿼리


계층형 메뉴 정렬 하는 쿼리

CREATE DATABASE test default CHARACTER SET UTF8;

use test;

DROP table IF EXISTS menu;
CREATE TABLE menu (
  no int PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  parent int NULL,
  depth int NOT NULL,
  sequence int,
  reg_date DATETIME,
  modify_date DATETIME
)ENGINE=INNODB;
DESCRIBE  menu;

DROP TABLE menu;

INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date) VALUES("메뉴1" ,0 ,1, 1, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴1-1" ,1 ,2, 1, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴1-2" ,1 ,2, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴1-1-1" ,2 ,3, 1, now(), now());

INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴2" ,0 ,1, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴2-1" ,5 ,2, 1, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴2-2" ,5 ,2, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴2-1-1" ,6 ,3, 1, now(), now());

INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴1-1-2" ,2 ,3, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴2-1-2" ,6 ,3, 2, now(), now());
INSERT INTO menu(name, parent, depth , sequence, reg_date, modify_date)  VALUES("메뉴2-1-3" ,6 ,3, 3, now(), now());
SELECT * FROM menu;

/* 계층형 mysql 쿼리 정렬 함수 */
DROP FUNCTION IF EXISTS hierarchy_connect_by_parent_eq_prior_no;
DELIMITER $$
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_no(value INT) RETURNS INTEGER
NOT DETERMINISTIC
READS SQL DATA
  BEGIN
    DECLARE _parent INT;
    DECLARE _rank INT;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;

    SET _parent = @id;
    SET _rank = 0;

    IF @id IS NULL THEN
      RETURN NULL;
    END IF;

    LOOP
      SET @innerrank = 0;
      SELECT p.no
          INTO   @id
      FROM   (
             SELECT   no, @innerrank := @innerrank+1 AS ran
             FROM     menu
             WHERE    COALESCE(parent, 0) = _parent
             ORDER BY sequence
             ) p
      WHERE   p.ran > _rank LIMIT 0, 1;
      IF @id IS NOT NULL OR _parent = @start_with THEN
        SET @level = @level + 1;
        RETURN @id;
      END IF;
      SET @level := @level - 1;
      SET @innerrank = 0;
      SELECT COALESCE(p.parent, 0), p.ran
          INTO   _parent, _rank
      FROM   (
             SELECT no, parent, @innerrank := @innerrank+1 AS ran
             FROM    menu
             WHERE   COALESCE(parent, 0) = (
                                           SELECT COALESCE(parent, 0) FROM menu WHERE no = _parent
                                           )
             ORDER BY sequence
             ) p
      WHERE p.no = _parent;
    END LOOP;
  END;
$$
DELIMITER ;

/* 계층형 메뉴 정렬*/
SELECT  CONCAT(REPEAT('    ', depth  - 1), CAST(ou.no AS CHAR)) AS no, parent, depth, CONCAT(REPEAT('    ', depth  - 1), CAST(ou.name AS CHAR)) AS name, sequence, level FROM (
                 SELECT mn.name , mn.no, depth , parent, sequence, level FROM (
                                                               SELECT hierarchy_connect_by_parent_eq_prior_no(no) AS no,
                                                                      @level AS level
                                                               FROM (
                                                                    SELECT @start_with := 0, @id := @start_with, @level := 0
                                                                    ) vars, menu
                                                               WHERE @id IS NOT NULL
                                                               ) m
                                                                 JOIN menu mn ON mn.no = m.no
                 ) ou;

/* 계층형 mysql 쿼리 정렬 함수 - 특정 번호 */
DROP FUNCTION IF EXISTS hierarchy_connect_by_parent_eq_prior_id;
DELIMITER $$
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INTEGER
NOT DETERMINISTIC
READS SQL DATA
  BEGIN
    DECLARE _no INT;
    DECLARE _parent INT;
    DECLARE _next INT;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET @no = NULL;

    SET _parent = @no;
    SET _no = -1;

    IF @no IS NULL THEN
      RETURN NULL;
    END IF;

    LOOP
      SELECT  MIN(no)
          INTO    @no
      FROM    menu
      WHERE   parent = _parent
        AND no > _no;
      IF @no IS NOT NULL OR _parent = @start_with THEN
        SET @depth = @depth + 1;
        RETURN @no;
      END IF;
      SET @depth := @depth - 1;
      SELECT  no, parent
          INTO    _no, _parent
      FROM    menu
      WHERE   no = _parent;
    END LOOP;
  END;
$$
DELIMITER ;

/* 조건에 따라 메뉴 출력 */
SELECT mn.name , mn.no, depth , parent, sequence
FROM    (
        SELECT no, @depth  AS vars_depth FROM menu WHERE no= '원하는메뉴번호'
        UNION ALL
        SELECT  hierarchy_connect_by_parent_eq_prior_id(no) AS no, @depth  AS vars_depth
        FROM    (
                SELECT  @start_with := '원하는메뉴번호',
                        @no := @start_with,
                        @depth  := 0
                ) vars, menu
        WHERE   @no IS NOT NULL
        ) fn
          JOIN    menu mn
            ON      mn.no = fn.no;
참고사이트
Share:

2018년 9월 26일 수요일

자기소개서 작성

필수항목

  • 내 전문 분야에 대해 흥미를 갖게 된 계기
  • 내 전문 분야와 관련된 과거의 경험(팀프로젝트,공모전,스터디 등)
  • 회사업무와 관련된 과거 경험(팀프로젝트, 공모전, 아르바이트 등)
  • 현재의 자신에 대한 설명(성격, 능력등)
  • 내 분야의 전문가로서 자신이 할 수 있는, 하고 싶은 일
모든 항목을 다 넣는 것이 Best
경험이 적거나 마이너스 요인이 될 가능성이 높은 경우에는 빼는 것이 좋다
1번과 5번은 필수!!

추가하면 좋은 사항
  • 개발 외 조직생활 경험
  • 동아리 경험
  • 지원하는 회사에 대한 제품에 대한 내용
  • 나의 현재 실력에 대한 내용
  • 나의 포부

자기소개서

  • 예시가 있는 근거로 주장을 해야한다.
  • 스토리를 넣는게 좋다.
  • 짧게 쓰는게 좋다.
  • 소제목을 넣어야하고 소제목만 봐도 의미를 알아야 한다.
  • 자소서를 봤을때 어떤사람인지 알수있게 쓰는게 좋다.
  • 지원하는 직무와 잘 맞아야 한다.
  • 자소서에 쓴 나와 실제의 나와 일치해야 한다.
다른사람과 비교해서 나의 장점을 부각해서 적어야한다.

기업별 자기소개서 특징

  • 대기업 채용 : 원하는 인재상이 정확히 정해져 있다. 인재상에 부합하는 인재상 중에서 가장 능력
    있는 사람을 뽑고 싶어함.
  • 중견기업 : 충성도가 1순위, 스펙을 많이 보는 경향, 일을 빠르게 많이 수행할 수 있는 능력
  • 스타트업 : 기업의 비전의 뜻을 같이, 알아서 잘크는, 자기주도적인 인재

검토

직무 70%, 직무 외 내용 30%

인사 담당자가 궁금해 하는것은 어떻게가 아니라 왜?이다(기술,퇴사등등)
Share:

Spring 프로젝트에서 ckEditor를 이용해서 이미지 업로드 구현

1. 기본 셋팅

  1. 사이트
  2. 설치
    • 다운로드 사이트에 접속해서 Full Package 를 다운받는다.
    • 압축을 해제한다.
    • 압축해제한 폴더를 webapp 폴더에 resources폴더를 만들고 복사한다.
  3. 리소스 폴더 매핑
    • ckeditor폴더의 리소스를 매핑하는 부분을 설정한다.
  4. <mvc:resources mapping="/resources/**" location="/resources/" />
    
  5. 기본 에디터 셋팅
    <!DOCTYPE html>
    <html lang="ko">
    <head>
     <script src="/resources/ckeditor/ckeditor.js"></script>
        <script>
        window.onload = function(){
           ck = CKEDITOR.replace("editor");
        };
        </script>
    </head>
    <body>
        <form>
            <textarea name="editor1" id="editor1" rows="10" cols="80">
                This is my textarea to be replaced with CKEditor.
            </textarea>
        </form>
    </body>
    </html>
    

2. 이미지 기본 업로드

  1. ckEditor config 설정을 변경한다.
  2. <script src="/resources/components/ckeditor/ckeditor.js"></script>
    <script>
        var editorConfig = {
            filebrowserUploadUrl : "/ckEditor/imgUpload", //이미지 업로드
        };
    
        CKEDITOR.on('dialogDefinition', function( ev ){
            var dialogName = ev.data.name;
            var dialogDefinition = ev.data.definition;
    
            switch (dialogName) {
                case 'image': //Image Properties dialog
                //dialogDefinition.removeContents('info');
                dialogDefinition.removeContents('Link');
                dialogDefinition.removeContents('advanced');
                break;
            }
        });
     window.onload = function(){
          ck = CKEDITOR.replace("editor", editorConfig);
     };
    </script>
    
  3. 리소스 폴더 매핑
    파일 저장을 아래와 같이 설정 했을 경우
  4. //파일 기본경로
    String defaultPath = request.getSession().getServletContext().getRealPath("/");
    //파일 기본경로, 상세경로
    String filePath = defaultPath + "resources" + File.separator + "ckEditorImg" + File.separator;
    
    파일을 저장한 위치와 요청한 url을 매칭시키는 설정을 추가한다.
    <mvc:resources mapping="/ckEditorImg/**" location="/resources/ckEditorImg/" />
    
  5. 서버에서 아래의 형식에 맞게 JSON으로 응답한다.

3. 드래그 이미지 업로드

  1. add-on 설치
    upload image 애드온은 '드래그앤드롭'을 가능하게 해주고, 나머지는 종속되는 프로그램
    프로그램을 다운받아서 ckeditor/plugins 디렉토리에 넣는다
  2. ckEditor config 설정을 변경
    <script src="/resources/components/ckeditor/ckeditor.js"></script>
    <script>
        var editorConfig = {
             filebrowserUploadUrl : "/ckEditor/imgUpload?type=image", //이미지만 업로드
             extraPlugins : 'uploadimage'
        };
     
     
        CKEDITOR.on('dialogDefinition', function( ev ){
            var dialogName = ev.data.name;
            var dialogDefinition = ev.data.definition;
     
            switch (dialogName) {
                case 'image': //Image Properties dialog
                //dialogDefinition.removeContents('info');
                dialogDefinition.removeContents('Link');
                dialogDefinition.removeContents('advanced');
                break;
            }
        });
     
        window.onload = function(){
             ck = CKEDITOR.replace("editor", editorConfig);
        };
    </script>
    
Share:

2018년 9월 19일 수요일

NHN 엔터테이먼트 안정적인 서비스 운영 - 설계에서 모니터링 까지


NHN에서 주관한 세미나에 참석했다
서비스를 운영하면서 설계하는 여러가지 방법과 운영하면서 신경써야 할 부분에대해 들을 수 있었다.
발표자료는 슬라이드쉐어에서 볼 수 있다.
세미나 정보도 올라오는 페이스북도 있다


Share:

2018년 9월 18일 화요일