소프트웨어 개발 방법론

소프트웨어 생명주기 모델

1. 개념

 - 시스템의 요구분석부터 유지보수까지 전 공정을 체계화한 절차

 - 시스템이 개발될 때부터 운용과 유지보수를 거쳐 생애를 마칠 때까지 어떠한 순서를 밟는지에 대한 작업 프로세스를 모델화한 것

 

2. 프로세스 ( 요구사항 분석 → 설계 → 구현 → 테스트 → 유지보수 )

 - 요구사항 분석 : 개발할 소프트웨어의 기능과 제약 조건, 목표 등을 소프트웨어 사용자와 함께 정의하는 단계

  └  기능 요구사항, 비기능 요구사항  

 - 설계 : 시스템 명세 단계에서 정의한 기능을 실제 수행할 수 있도록 수행 방법을 논리적으로 결정하는 단계

  └  시스템 구조 설계, 프로그램 설계, 사용자 인터페이스 설계

 - 구현 : 프로그래밍 언어 선택, 기법, 스타일, 순서 등을 결정하여 실제 프로그램을 작성하는 단계

  └  인터페이스 개발, 자료 구조 개발, 오류 처리

 - 테스트 : 예상과 실제결과의 차이를 검사, 평가 단계

  └  단위 테스트, 통합 테스트, 시스템 테스트, 인수 테스트

 - 유지보수 : 시스템 인수되고 설치된 후 일어나는 모든 활동

  └  예방, 완전, 교정, 적응 유지보수

 

3. 모델 종류

종류 설명
폭포수 모델
(Waterfall Model)

· 개발시 각 단계를 확실히 마무리 지은 후 다음 단계로 넘어감
· 선형 순차적 모형, 고전적 생명주기 모형
· 요구사항 변경 어려움
절차 타당성 검토 → 계획 → 요구사항 분석 → 설계 → 구현 → 테스트 → 유지보수
프로토타이핑 모델
(Prototyping Model)
· 고객이 요구한 주요기능을 프로토타입으로 구현하여, 고객의 피드백을 반영
· 요구사항 분석 용이, 타당성 검증가능
· 프로토타입 폐기에 따른 비용 증가
나선형 모델
(Spiral Model)

· 시스템 개발 시 위험을 최소화하기 위해 점진적으로 완벽한 시스템으로 개발
· 위험분석, 반복개발
·
위험성 감소와 변경에 유연한 대처
·
단계 반복에 따른 관리 어려움  
절차 계획 및 정의 → 위험 분석 → 개발 → 고객평가 
반복적 모델
(Iteration Model)
· 구축대상을 나누어 병렬적으로 개발 후 통합하거나, 반복적으로 개발하여 점증 완성시키는 SDLC 모델
· 병행 개발로 인한 일정 단축 가능
· 병행 개발에 따른 관리 비용 증가

 


 

소프트웨어 개발 방법론

1. 개념

- 소프트웨어 개발 전 과정에 지속적으로 적용할 수 있는 방법, 절차, 기법

- 소프트웨어 개발의 시작부터 시스템을 사용하지 않는 과정까지의 전 과정을 형상화한 방법론

 

2. 종류

종류 설명
구조적 방법론 ·  전체 시스템을 기능에 나누어 개발, 이를 통합하는 분할과 정복 접근 방식의 방법론
·  프로세스 중심의 하향식 방법론
·  나씨 슈나이더만 차트 사용 : 논리의 기술에 중점을 둔 도형식 표현방법
정보공학 방법론 · 정보시스템 개발에 필요한 관리 절차와 작업 기법을 쳬계화
객체 지향 방법론 · '객체'라는 기본 단위로 시스템을 분석 및 설계
컴포넌트 기반 방법론(CBD) · 컴포넌트를 조립해서 하나의 새로운 응용프로그램 작성
· 개발시간 단축 - 생산성 향상, 확장성, 재사용성
애자일 방법론 · 절차보다는 사람 중심, 변화에 유연 신속 적응하면서 효율적인 시스템 개발
제품 개발 방법론 · 특정 제품에 적용하고 싶은 공통된 기능을 정의 개발, 임베디드 S/W작성에 유용

 

3. 애자일 : 절차보다는 사람중심, 변화에 유연 신속 적용, 즉시 피드백을 받아 유동적 개발

- 유형

  XP : 의사소통 개선과 즉각적 피드백으로 소프트웨어 품질 향상을 위한 방법론

     XP 5가지 가치 : 용기, 단순성, 의사소통, 피드백, 존중

     XP 12가지 기본원리

기본원리 설명
짝 프로그래밍  개발자 둘이서 짝 코딩
공동 코드 소유  시스템에 있는 코드는 누구든 언제든 수정 가능
지속적인 통합 (CI)  매일 여러번 소프트웨어 통합, 빌드
계획 세우기  고객 요구 비즈니스 가치 정의, 개발자가 필요한 것이 무엇인지, 어떤 부분에서 지연 여부를 알려줌
작은 릴리즈  작은 시스템을 먼저 만들고, 짧은 단위 업데이트
메타포어  공통적인 이름 체계와 시스템 서술서를 통해 의사소통을 원활
간단한 디자인  요구사항에 적합한 가장 단순한 시스템을 설계
테스트 기반 개발 (TDD)  작성하는 프로그램에 대한 테스트 먼저 수행, 테스트를 통과하도록 실제 코드 작성
리팩토링  프로그램 기능을 바꾸지 않으면서, 코드의 중복제거, 단순화
40시간 작업  개발자 실수 방지를 위해 일주일 40시간 이상 일하지 말아야 함
고객 상주  개발자 질문에 즉각 대응을 위해 고객 풀타임 상주
코드표준  효과적인 공동 작업을 위해 코딩 표준 정의


   린(Lean) : 토요타의 린 시스템 품질 기법을 소프트웨어 개발 프로세스에 적용해서 낭비 요소를 제거하여 품질 향상을 위한 방법론

     린 7가지 가치 : 낭비제거, 품질 내재화, 지식창출, 늦은 확정, 빠른 인도, 사람존중, 전체 최적화

  ③ 스크럼(SCRUM) : 매일 정해진 시간, 장소에서 짧은 시간의 개발을 하는 팀을 위한 프로젝트 중심 방법론

     백로그, 스프린트, 스크럼 미팅, 스크럼 마스터, 스프린트 회고, 번 다운 차트

 

 


 

객체 지향 분석 방법론 ( OOA : Object Oriented Analysis )

1. 개념 : 사용자의 요구사항을 분석하여 요구된 문제와 관련된 모든 클래스, 속성과 연산, 관계를 정의

 

2. 종류

- OOSE(Object Oriented Software Engineering) : 유스케이스를 모든 모델의 근간으로 활용되는 방법론, 야콥스

- OMT(Object Modeling Technology) : 그래픽 표기법을 이용하여 소프트웨어 구성요소를 모델링, 럼바우

  └ 분석 절차  : 객체 - 동적 - 기능
  └ 객체 모델링 (Object, Information)  : 객체 다이어그램, 객체들 간의 관계 정의하여 ER 이어그램을 만드는 과정까지의 모델링
  └ 동적 모델링 (Dynamic) : 상태 다이어그램, 시간의 흐름에 따라 객체들의 동적인 행위를 표현
  └ 기능 모델링 (Functional) : 자료흐름도(DFD), 프로세스들의 자료 흐름을 중심으로 처리과정 표현 

- OOD(Object Oriented Design) : 설계 문서화를 강조하여 다이어그램 중심으로 개발, 부치

 

 

 


 

비용산정, 일정관리 모형

비용산정 모형 : 소프트웨어 비용 산정 방식

1. 분류

- 하향식 산정방법 : 경험이 많은 전문가에게 비용산정

  └ 전문가 판단
  └ 델파이 기법  : 전문가의 경험적 지식을 통한 문제 해결 및 미래예측을 위한 기법

- 상향식 산정방법 : 세부적인 요구사항과 기능에 따라 비용산정

  └ 코드라인수(LoC) 모형, Man Month 모형, COCOMO 모형, 푸트남 모형, 기능점수(FP) 모형

 

2. 종류

종류 설명
코드라인수(LoC) 모형 ·  원시 코드 라인수의 낙관치, 중간치, 비관치 측정하여 예측치를 구해 비용산정
Man Month 모형 ·  한 사람이 1개월동안 할 수 있는 일의 양을 기준으로 비용산정
·  (Man Month) = (LoC) / (프로그래머 월간 생산성) 
·  (프로젝트 기간) = (Man Month) / (프로젝트 인력)
COCOMO 모형 ·  보헴이 제안한 모형으로 프로그램 규모에 따라 비용산정
·  조직형(Organic) : 5만 라인 이하
·  반분리형(Semi) : 30만 라인 이하
·  임베디드형(Embedded) : 30만 라인 이상
푸트남 모형 ·  개발주기의 단계별로 요구할 인력의 분포를 가정하는 방식
기능점수(FP) 모형 ·  소프트웨어 기능을 증대시키는 요인별로 가중치를 부여햐여 비용산정

 


 

일정 관리 모델 :  프로젝트가 일정 기한 내에 완료될 수 있도록 관리하는 모델

1. 종류 (주,펄,중)

- 주 공정법(CPM)  : 여러 작업의 수행 순서가 얽혀 있는 프로젝트의 일정을 계산하는 기법
  └ 주 공정(임계경로) : 프로젝트의 시작에서 종료까지 가장 긴 시간이 걸리는 경로
- PERT  : 일의 순서를 계획적으로 정리하기 위한 수렴 기법. 비관치, 중간치, 낙관치 이용
- 중요 연쇄 프로젝트 관리(CCPM) : 주 공정 연쇄법으로 자원 제약사항을 고려하여 일정 작성

 


TEST  →  정답은 드래그!

정답 문제
소프트웨어 생명주기
(SDLC)
시스템의 요구분석부터 유지보수까지 전 공정을 체계화한 절차이다.
폭포수 모델 소프트웨어 개발시 각 단계를 확실히 마무리 지은 후에 다음단계로 넘어가는 가장 오래된 생명주기 모델이다.
나선형 모델 시스템 개발 시 위험을 최소화하기 위해 점진적으로 완벽한 시스템으로 개발해 나가는 모델이다.
소프트웨어 개발 방법론 소프트웨어 개발 전 과정에 지속적으로 적용할 수 있는 방법, 절차, 기법이다.
구조적 방법론 전체 시스템을 기능에 따라 나누어 개발하고, 이를 통합하는 분할과 정복 접근 방식을 사용하는 방법론이다.
나씨-슈나이더만 차트 구조적 프로그래밍 표현을 위해 논리의 기술에 중점을 둔 도형식 표현 방법으로 연속, 선택, 반복 등의 제어 논리 구조로 표현한다.
애자일 방법론 절차보다는 사람이 중심이 되어 변화에 유연하고 신속하게 적응하면서 효율적으로 시스템을 개발할 수 있는 신속 적응적 경량 개발 방법론이다.
XP 의사소통 개선과 즉각적 피드백으로 소프트웨어 품질을 높이기 위한 방법론으로 5가지 가치와 12개의 실천항목이 존재한다.
지속적인 통합(CI) 매일 여러 번씩 소프트웨어를 통합하고 빌드해야 한다는 원리이다.
메타포어 XP의 12가지 기본원리 중 하나로 공통적인 이름체계와 시스템 서술서를 통해 고객과 개발자간의 의사소통을 원활하게 한다는 원리이다.
테스트 기반 개발(TDD) 작성해야 하는 프로그램에 대한 테스트를 먼저 수행하고 이 테스트를 통과할 수 있도록 실제 프로그램의 코드를 작성한다는 원리이다
스크럼 애자일 방법론 중 매일 정해진 시간, 장소에서 짧은 시간의 개발을 하는 팀을 위한 프로젝트 관리 중심 방법론이다.
스프린트 스크럼 방법론에서 2~4주의 짧은 개발 기간으로 반복적 수행하는 개발 품질을 향상시키는 프로젝트 수행법이다.
번 다운 차트 스크럼 방법론에서 남아있는 백로그 대비 시간을 그래픽적으로 표현한 차트이다.
리팩토링 프로그램의 기능을 바꾸지 않으면서 중복제거, 단순화 등을 위해 시스템 재구성 한다는 원리이다.
LoC 모형 소프트웨어 각 기능의 원시 코드 라인 수의 낙관치, 중간치, 비관치를 측정하여 예측지를 구하고 이를 이용하여 비용을 산정하는 방식이다.
Man Month 한 사람이 1개월 동안 할 수 있는 일의 양을 기준으로 프로젝트 비용을 산정하는 방식이다.
COCOMO 모형 보헴이 제안한 모형으로 프로그램 규모에 따라 비용을 산정하는 방식으로, 규모에 따라 조직형, 반 분리형, 임베디드형으로 나뉜다.
푸트남 모형 소프트웨어 개발 주기의 단계별로 요구할 인력의 분포를 가정하는 방식으로, 시간에 따른 함수로 표현되는 Rayleigh-Norden 곡선의 노력분포도를 기초로 한다.
델파이 기법 비용산정 모형 중 하향식 산정방법이며, 전문가의 경험적 지식을 통한 문제 해결 및 미래예측을 위한 기법이다.
기능 점수 모형(FP 모형) 요구 기능을 증가시키는 인자별로 가중치를 부여하고, 요인별 가중치를 합산하여 총 기능의 점수를 계산하여 비용을 산정하는 방식이다.
주 공정법 일정관리 모델 중에서 여러 작업의 수행 순서가 얽혀 있는 프로젝트의 일정을 계산하는 기법이며, 모든 자원 제약사항을 배제한 상태로 프로젝트의 시작과 끝을 나타내는 노드와 노드 간을 연결을 통해 공정을 계산하기 위한 액티비티로 표기한다.
PERT 일정관리 모델 중에서 일의 순서를 계획적으로 정리하기 위한 수렴기법으로 비관치, 중간치, 낙관치의 3점 추정방식을 통해 일정을 관리하는 기법이다.
데이터 흐름도(DFD) 데이터가 각 프로세스를 따라 흐르면서 변환되는 모습을 나타낸 그림으로, 시스템 분석과 설계에서 매우 유용하게 사용되는 다이어그램이다.
자료 사전(DD) 자료 요소, 자료 요소들의 집합, 자료의 흐름, 자료저장소의 의미와 그들 간의 관계, 관계 값, 범위, 단위들을 구체적으로 명시하는 사전이다.
릴리즈노트 조직의 최종사용자인 고객과 잘 정리된 릴리즈 정보를 공유하는 문서이다.
헤더 릴리즈 노트 작성 항목 중 문서 이름, 제품 이름, 버전 번호, 릴리즈 날짜, 참고 날짜, 노트 버전 등의 정보이다.
재현 항목 릴리즈 노트 작성 항목 중 버그 발견에 따른 재현 단계 기술이다.
사용자 영향도 릴리즈 노트 작성 항목 중 버전 변경에 따른 최종 사용자 기준의 기능 및 응용 프로그램상의 영향도 기술이다.
노트 릴리즈 노트 작성 항목 중 소프트웨어 및 하드웨어 설치 항목, 제품, 문서를 포함한 업그레이드 항목 메모이다.
면책조항 릴리즈 노트 작성 항목 중 회사 및 표준 제품과 관련된 메시지, 프리웨어 및 불법 복제 방지, 중복 등 참조에 대한 고지 사항이다.

 

 

 

 

 

 

 

※ 해당 글은 수제비 2022 도서 참고하였습니다.

 

수제비- IT 커뮤니티 (정보처리기사... : 네이버 카페

수제비-수험생 입장에서 제대로 쓴 비법서(정보처리기사, 정보처리기능사, 빅데이터 분석기사 등 시리즈)

cafe.naver.com

 

<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/emn178/chartjs-plugin-labels/src/chartjs-plugin-labels.js"></script>

chartjs-plugin-labels을 사용하기 위한 설정

 

 

위와 같은 차트의 라벨에 세 자릿수마다 콤마를 찍고 싶었다.

 

https://chartjs-plugin-datalabels.netlify.app/guide/formatting.html

 

Formatting | chartjs-plugin-datalabels

Formatting Data Transformation Data values are converted to string ('' + value). If value is an object, the following rules apply first: value = value.label if defined and not null else value = value.r if defined and not null else value = 'key[0]: value[ke

chartjs-plugin-datalabels.netlify.app

공식문서와 구글 검색에서는 formatter를 사용하라고 한다.(필자가 못 찾는 걸 수도...)

type : 'pie' 설정이라 그런지. formatter는 먹히지 않았다.

 

2일의 뻘짓. .

// 기존코드
... // 생략
plugins: {
    labels: {
        render: 'value', .. // 생략
        }
    }
}

우연히 눈에 들어온 render = 'value'

// 변경코드
... // 생략
plugins: {
    labels: {
        render: function(data) {
        	console.log(data);
        	return data.value.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
        }, .. // 생략
    }
}

공식문서를 응용하여 함수를 만들어 파라미터를 콘솔로 찍어보니 dataset 객체가 마구 찍히고 있었다.

속는 셈 치고 위와 같이 코딩을 해보니 라벨에 콤마가 잘 찍혔다.

 

 

속이 뻥 뚫리는 기분이다. 🤣

엑셀 다운로드시 날짜 형식의 데이터가 포함되어 있었다.

뷰에서는 YYYY-MM-DD hh:mm (2022-10-20 08:41)으로 잘 보여졌는데, 같은 데이터를 엑셀 다운로드 한 결과 yyyy-mm-dd h:mm (2022-10-20 8:41) 형식으로 보여지고 있었다.

구글링은 해보던 중 mso-number-format를 알게 되었고, mso-number-format형식 중 날짜형식 포맷 방법을 찾아 보았다.

mso-number-format:"mm\/dd\/yy" Date7
mso-number-format:"mmmm\ d\,\ yyyy" Date9
mso-number-format:"m\/d\/yy\ h:mm\ AM\/PM" D -T AMPM
mso-number-format:"Short Date" 01/03/1998
mso-number-format:"Medium Date" 01-mar-98
mso-number-format:"d-mmm-yyyy" 01-mar-1998
mso-number-format:"Short Time" 5:16
mso-number-format:"Medium Time" 5:16 am
mso-number-format:"Long Time" 5:16:21:00

하지만, 내가 원하는 포맷 방식은 나오지 않았다.

반나절을 고민.... 또 고민.

결론적으론 날짜서식을 문자열서식으로 포맷해주었더니 원하는 방식으로 잘 출력된다!!

mso-number-format:"\@" Text

mso-number-format 은 style에 지정해주면 된다!!

<td style='mso-number-format: \"@\";'>2022-10-20 08:46</td>

 

 

정보 마스킹 처리

 

- 실무에서 회원 이름을 마스킹 할 일이 생겼다. ( EX : 이름 → 이*, 이름이 → 이*이, 이름이다  이**다) 

 

SELECT
    IFNULL(
        CASE WHEN CHAR_LENGTH(name) > 2
             THEN CONCAT(SUBSTRING(name, 1, 1),LPAD('*', CHAR_LENGTH(name) - 2, '*'), SUBSTRING(NAME, CHAR_LENGTH(name), CHAR_LENGTH(name)))
             ELSE CONCAT(SUBSTRING(name, 1, 1),LPAD('*', CHAR_LENGTH(name) - 1, '*'))
        END, ''") AS mask_name
FROM 테이블명;

데이터의 길이가 가변적이기 때문에 CASE 문을 사용하여 변환.

CONCAT으로 문자열 합치기.

SUBSTRING으로 문자열 자르기.

LPAD를 사용하여 왼쪽으로 *으로 밀어주기!

 

위와 같은 방식으로 SUBSTRING의 시작위치와 종료위치를 변경하면 휴대폰 번호도 마스킹 가능하다!

 

게시판형 웹사이트를 구현하다 보면 검색 시작일 ~ 검색 종료일을 검색할 때 datePicker로 많이 사용한다.

지난번 프로젝트 때 다 만들어 놓았던 util 함수였는데, 내부망이라서 코드를 다 날려버렸다.

새로 시작한 프로젝트에서도 비슷한 유형의 검색을 하게 되어 추후 사용할지도 몰라 업로드한다.🤣

 

/* utils.js */

let utlls = {
    /**
     * 기준일자 default 셋팅
     * @param fromId
     * @param toId
     */
    searchDateSet : function (fromId = '#do_date', toId = '#do_date1') {
        let nowDate = new Date();
        let setMonth = (nowDate.getMonth()+1).toString();
        let setDay = nowDate.getDay().toString();
        let setDate = nowDate.getFullYear() + (setMonth < 10 ? '0' + setMonth : setMonth) + (setDay < 10 ? '0' + setDay : setDay);  // yyyymmdd
        if(fromId.indexOf('cpn_date') > Number(-1)) {
            setDate = nowDate.getFullYear() + '/' + (setMonth < 10 ? '0' + setMonth : setMonth);    // yyyy/mm
        }
        $(fromId).val(setDate);
        $(toId).val(setDate);
    },

    /**
     * 기준일자 데이트피커 포맷
     * @param fromId : 기준시작일
     * @param toId   : 기준종료일
     */
    datePickerFormat : function (fromId = '#do_date', toId = '#do_date1') {
       if(fromId.indexOf('cpn_date') > Number(-1)){
           $(fromId).datepicker({
               dateFormat: 'yy/mm'
           });
           $(toId).datepicker({
               dateFormat: 'yy/mm'
           });
       } else {
           $(fromId).datepicker({
               dateFormat: 'yymmdd'
           });
           $(toId).datepicker({
               dateFormat: 'yymmdd'
           });
       }
    },

    /**
     * 기준일자 value 체크
     * @param fromId
     * @param toId
     * @param obj
     */
    searchDateValidation : function (fromId = '#do_date', toId = '#do_date1', obj) {
        let fromDate = $(fromId).val();
        let toDate = $(toId).val();

        if(fromDate.replace("/", "") && toDate.replace("/", "") && fromDate > toDate) {
            if(obj.id.indexOf("1") == -1) { // 기준시작일
                alert('기준시작일은 기준종료일보다 빠를 수 없습니다.');
                $(fromId).val(toDate);
            }else {
                alert('기준종료일은 기준시작일보다 늦을 수 없습니다.');
                $(toId).val(fromDate);
            }
        }
    }
}

utils.js를 따로 작성해 주었다. 게시판 형일 경우 비슷하게 날짜를 포맷하는 경우가 많아. 그 경우 파라미터에 default id를 지정해 준다. 포맷 형식이 다른 id는 if문을 사용. * default id값에 #을 포함하여 넣는건 추천하지 않는다. 초보인지라.. 더 좋은 방법이 생각나면 코드 수정을 할 예정....... 피트백도 좋습니다.

 

<script type="text/javascript" src="utils.js"></script>
<script type="text/javascript">
    $(function() {
        utlls.datePickerFormat('#cpn_date', '#cpn_date1');
        utlls.searchDateSet('#cpn_date', '#cpn_date1');
    });
</script>        
<body>
	<input type="text"  id="cpn_date"  readonly name="cpn_date" onchange="utlls.searchDateValidation('#cpn_date', '#cpn_date1', this);"> -
	<input type="text"  id="cpn_date1" readonly name="cpn_date1" onchange="utlls.searchDateValidation('#cpn_date', '#cpn_date1', this);">
</body>

html 코드는 간략하게 작성하였다.

샘플 이미지

 

restApi를 사용하다보면 전송할 데이터가 JSON 안에 배열을 넣어야 하는 데이터일 때가 종종 있다.

그래서 글을 한번 작성해 보려 한다.

 

let id = 'testId';
let key = 'testKey';

let testArr1 = [{"number":2,"color":'red'}];
let testArr2 = new Array();
let pushJson = {
  "number":3,
  "color":'blue'
};
testArr2.push(pushJson);

let params = {
  "id":id,
  "key":key,
  "arr1":testArr1,	// "arr1":[{"number":2,"color":'red'}] 가능
  "arr2":testArr2
};

console.log(params);

JSON 안에 배열 추가

json data 생성시 value값으로 배열을 넣어주기만 하면 된다.

배열 안에 JSON  추가

배열에 생성해논 JSON data를  push() 함수를 사용하여 추가해주었다.

 

params의 모양을 그려보면 아래와 같다.

{
  id: 'testId',
  key: 'testKey',
  arr1: [
    {
      number:2,
      color:'red'
    }
  ],
  arr2: [
    {
      number: 3,
      color: 'blue'
    }
  ]
}

 

console 이미지

 

현재 진행중인 프로젝트에서 파일경로를 취합할 일이 생겼다.

검색을 해보니, cmd로 단축어를 사용해서 검색하는 방법이 있었다.

추후, 또 사용할 일이 생길 수 있으니 남겨 놓으려 한다. (캡쳐를 남기려 했지만, 내부망으로 막혀있는 구조라... 글로만 씀 ㅠㅠ)

 

윈도우키 + R을 누르면 윈도우 실행창이 실행된다.

그곳에 'cmd' 확인

 

필요한 파일 리스트가 있는 디렉토리로 이동한다. 

드라이브 이동 - 드라이브명: (ex C:)

디렉토리 이동 - cd 디렉토리명

전 디렉토리 이동 - cd ..

디렉토리 파일 확인 - dir

 

파일명 목록

단축어 : dir /b

 

텍스트 파일에 파일명 목록내용 넣기

dir/b > 파일명.txt

 

경로 + 파일명 목록

단축어 : dir /s/b

원하는 확장자만 검색하고 싶을땐 dir /s/b *.확장자명 (ex : dir /s/b *.txt)

 

텍스트 파일에 경로+파일명 목록내용 넣기

dir /s/b > 파일명.txt

 

'IT > 이것저것' 카테고리의 다른 글

[Server] 서버의 구조 이해  (0) 2021.06.11

 

이미지를 올리기 전 미리보기를 구현해보자!

 

전체 코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>

    <div id="previewDiv"></div>
    <input type="file" id="imgInput" onchange="readURL(this)">

    <script>
        function readURL(obj) {

            let reader = new FileReader();
            if(!obj.files.length) {
                return;
            }
            reader.readAsDataURL(obj.files[0]);
            reader.onload = function (e) {
                let img = $('<img />');
                $(img).attr('src', e.target.result);
                $('#previewDiv').append(img);
            }
        }
</script>
</body>
</html>

 

우선 제이쿼리를 사용하기 위해 링크를 걸어준다.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

 

body에 div를 선언하고, input 태그에 onchange 이벤트가 발생할 때 스크립트에 만들어 논 함수를 실행한다.

파라미터엔 this를 넣어준다.

this = 해당 태그의 객체

<div id="previewDiv"></div>
<input type="file" id="imgInput" onchange="readURL(this)">

 

파일에 이미지를 업로드하고 클릭을 하게 되면 readURL함수가 실행되고 매개변수로 객체를 받게 된다.

FileReader를 불러오고, 매개변수로 넘어온 값의 길이가 0일 경우 return

readAsDataURL() 함수를 통해 File에서 읽는다.

readAsDataURL() 읽어 온 후 onload가 실행되는데 이때 img태그를 생성하여, img태그에 src를 url로 넣어준 후 div에 img를 추가해준다.

function readURL(obj) {
            let reader = new FileReader();
            if(!obj.files.length) {
                return;
            }
            reader.readAsDataURL(obj.files[0]);
            reader.onload = function (e) {
                let img = $('<img />');
                $(img).attr('src', e.target.result);
                $('#previewDiv').append(img);
            }
        }

스프링에서 controller로 이동시 veiw에서 url로 파라미터를 전달할 수 있는데, 대표적 형태가 2가지 형태가 있다.

1유형 : http://www.test.com/board?seq=1
2유형 : http://www.test.com/board/1

 

@PathVariable 과 @RequestParam어노테이션은 url파라미터로 전달받은 value를 메서드의 파라미터로 받을 수 있게 해주는 어노테이션이다.

 

 

@RequestParam사용법

1유형 : http://www.test.com/board?seq=2
@GetMapping("/board")
public String save(@RequestParam("seq") int seq){
    .....
}

위와 같을 경우 int seq로 들어온 값은 1이 된다.

 

파라미터의 value로 null이 들어오는 것을 방지하기 위해선 아래와 같이 required 설정을 false로 한다. (defualt : true)

String형으로 데이터 타입을 변환한 이유는 seq가 ""이 들어올 경우 NumberFormatException이 발생하게 된다.

@GetMapping("/board")
public String save(@RequestParam(value = "seq", required = false) String seq){
    .....
}

 

 

@PathVariable 사용법

2유형 : http://www.test.com/board/1
@GetMapping("/board/{seq}")
public String save(@PathVariable int seq){
    .....
}

 

위와 같을 경우 int seq로 들어온 값은 1이 된다.

주의할 점은 URL에 특수문자나 구분기호 " , , ` , . " 등을 사용하면 인식을 못한다.

@GetMapping("/board/{seq}")
public String save(@PathVariable("seq") int num){
    .....
}

변수명을 바꿔서 사용하고 싶은 경우 @PathVariable('템플릿 변수명') url로 들어온 템플릿 변수명과 맵핑을 시켜주면 된다.

 

@RequestParam와 @PathVariable 복합 사용법

http://www.test.com/user/user?name=test
@PostMapping("/user/{category}")
public String save(@PathVariable("category") String category, @RequestParam(value = "name", required = false) String name){
    ....
}

위와 같이 코드를 실행하게 되면 category = user, name = test가 된다.

회원가입이나 value 체크를 할 때 정규식을 많이 사용하게 된다.

자주 사용할만한 함수를 모아서 한곳에 모아두면 편리해진다!

 

value 체크를 위한 js코드 ( join-util.js )


var joins = {
    /**
     * 공백체크
     * @param str
     * @returns {boolean}
     */
    nullCheck : function (str){
        if((!str)){
            return true;
        }
        return false;
    },
    /**
     * 아이디체크
     * @param str
     * @return {boolean}
     */
    idCheck : function (str){
        var check = /^[A-Za-z0-9+].{3,25}$/;
        if((!str) || (!check.test(str))){
            return true;
        }
        return false;
    },
    /**
     * 길이체크 : 2글자 이상 ~ 10글자 이하
     * @param str
     * @returns {boolean}
     */
    lenCheck : function (str){
        var check = /^[가-힣]{2,10}$/;
        if((!str) || (!check.test(str))){
            return true;
        }
        return false;
    },
    lenCheck2 : function (str){
        if((!str) || (str.length < 2)){
            return true;
        }
        return false;
    },
    /**
     * 숫자 확인
     * @param num
     * @return {boolean}
     */
    numberCheck : function (str){
        console.log(str);
        var check = /[0-9]/g;
        if((!str) || (!check.test(str))){
            return true;
        }
        return false;
    },

    /**
     * 이메일 형식 확인
     * @param str
     * @return {boolean}
     */
    emailCheck : function (str){
        var check = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]+$/;;
        if((!str) || (!check.test(str))){
            return true;
        }
        return false;
    },

    /** 패스워드는 6 ~ 20자 이내 영문 대,소문자, 숫자, 특수문자 혼합 입력
     * 패스워드 형식 확인 : 영문/숫자/특수문자 조합 10자 이상
     * @param str
     * @return {boolean}
     */
    passwordCheck : function (str){
        var check = /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{6,20}$/;
        if((!str) || (!check.test(str))){
            return true;
        }
        return false;
    },
    /**
     * 패스워드 재확인
     * @param str
     * @param str2
     * @return {boolean}
     */
    pwConfirmCheck : function (str, str2){
        if((!str2) || (str != str2)){
            return true;
        }
        return false;
    },
    /**
     * 전화번호 하이픈처리
     * @param obj
     */
    phoneKeyup : function (obj) {
        $(obj).val($(obj).val().replace(/[^0-9]/g, "").replace(/(^02|^0505|^1[0-9]{3}|^0[0-9]{2})([0-9]+)?([0-9]{4})$/, "$1-$2-$3").replace("--", "-"));
    },

    /**
     * 전화번호 확인 : hipen 포함
     * @param str
     * @returns {*}
     */
    phoneCheck : function (str){
        var check = /^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})$/;
        if((!str) || (!check.test(str))){
            return true;
        }
        return false;
    },

    /**
     * 전화번호 하이픈 제거 : DB 저장시
     * @param str
     * @return {*}
     */
    hyphenClear : function (str){
        return str.replaceAll("-", "");
    },


}

 

view에 가져와 사용을 해보자!

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <script src="/js/jquery-2.2.4.min.js"></script>
    <script src="/js/common/join-util.js"></script>
    <script src="/js/bootstrap.min.js"></script>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
    <link href="/css/bootstrap.min.css" rel="stylesheet">


    <title>Title</title>
    <script type="text/javascript">
        function onChangeConfirm(obj, join, text) {
            if($(obj).val().trim().length > 0){
                if(join($(obj).val().trim())) {
                    $(obj).siblings().text(text);
                    confirmFail(obj);
                    return true;
                }else{
                    confirmSuccess(obj);
                    return false;
                }
            }else if($(obj).val().trim().length === 0){
                $(obj).removeClass('is-invalid');
                $(obj).removeClass('is-valid');
                $(obj).siblings().text("");
            }
        }

        function confirmFail(obj){
            $(obj).addClass('is-invalid');
            $(obj).siblings().addClass('invalid-feedback');
            $(obj).focus();
        }

        function confirmSuccess(obj){
            $(obj).removeClass('is-invalid');
            $(obj).addClass('is-valid');
        }
    </script>
</head>
<body>
<div class="form-group">
    <label for="userId" class="col-sm-2 control-label">아이디</label>
    <div class="col-sm-10">
        <input type="text" class="form-control" name="userId" id="userId" placeholder="아이디" data-minlength="4" required
               onchange="onChangeConfirm(this, joins.emailCheck, '이메일형식으로 입력해 주세요.')">
        <div class="float-right"></div>
    </div>
</div>
<div class="form-group">
    <label for="userName" class="col-sm-2 control-label">이름</label>
    <div class="col-sm-10">
        <input type="text" class="form-control" name="userName" id="userName" placeholder="이름" data-minlength="2" required
               onchange="onChangeConfirm(this, joins.lenCheck, '이름은 두글자 이상 입력해 주세요.' )">
        <div></div>
    </div>
</div>
</body>
</html>

 

 

 

코드를 분석해 보자면..

<script src="/js/jquery-2.2.4.min.js"></script>

extarnal 방식 으로 JS파일을 불러온다.

 

 

<input type="text" class="form-control" name="userId" id="userId" placeholder="아이디" data-minlength="4" required
       onchange="onChangeConfirm(this, joins.emailCheck, '이메일형식으로 입력해 주세요.')">
<div class="float-right"></div>

input 태그에서 onchage이벤트 발생시 onchageConfirm 함수가 실행되고, 함수의 파라미터로 this(태그 자체), util안의 함수, 문자열을 받게 된다.

 

 

function onChangeConfirm(obj, join, text) {
    if($(obj).val().trim().length > 0){
        if(join($(obj).val().trim())) {
            $(obj).siblings().text(text);
            confirmFail(obj);
            return true;
        }else{
            confirmSuccess(obj);
            return false;
        }
    }else if($(obj).val().trim().length === 0){
        $(obj).removeClass('is-invalid');
        $(obj).removeClass('is-valid');
        $(obj).siblings().text("");
    }
}

 

onchageConfirm()

- $(obj).val() : this의 value

- join : util안의 함수(emailCheck) == 파라미터로 받았기 때문에 콜백 함수가 된다.

/**
 * 이메일 형식 확인
 * @param str
 * @return {boolean}
 */
emailCheck : function (str){
    var check = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]+$/;;
    if((!str) || (!check.test(str))){
        return true;
    }
    return false;
}

if문 안에 함수의 파라미터로 $(obj).val()를 넣어주면 함수의 실행에 따라 boolean값을 반환 받게 된다.

 

true를 반환 받을 시

$(obj).siblings() : this의 형제요소 == <div class="float-right"></div> 의 text에 파라미터로 받은 문자열을 넣어주면, 조건 실행시 text가 보여지게 된다.

 

실행화면

 

+ Recent posts