입출력 함수와 연산자 - 1

함수의 기본 개념, 표준 입출력 함수의 종류와 사용법.
입출력 양식 변환 기호.

  • 학습 목표

    1. C 언어에서의 함수를 이해.
    2. 표준 입출력 함수의 사용.
    3. 입출력 양식 변환 기호 사용..
  • 주요 용어

    • 함수 : 특정한 작업(기능)을 수행하도록 설계된 독립적인 프로그램.
    • 표준 함수 : C 언어 자체적으로 제공하는 함수.
    • 사용자 정의 함수 : 사용자가 정의하여 사용하는 함수.
    • 표준 입출력함수 : 자료의 입출력을 위해 C 언어에서 제공하는 함수.

 


 

표준 입출력 함수

함수 : 특정한 작업(기능)을 수행하도록 설계된 독립적인 프로그램.

 

C언어에서의 함수

  • 표준 함수 : C 언어 자체에서 제공하는 함수.
  • 사용자 정의 함수 : 사용자가 정의하여 사용하는 함수.

 

표준 입출력 함수의 종류

 

표준 출력함수 기능
printf() 화면에 여러 종류의 자료를 출력
putchar() 화면에 1개의 문자를 출력
puts() 화면에 문자열 출력

 

표준 입력함수 기능
scanf() 키보드를 통해 여러 종류의 자료를 입력 받음
getchar() '' 1개의 문자를 입력
gets() '' 문자열 출력

 


 

표준 출력 함수

출력양식 변환 기호

%문자 변환 형식 인자의 자료형
%d 부호 있는 10진 정수 정수형, 문자형
%u 부호 없는 10진 정수 정수형, 문자형
%f 부동소수점형식 실수형
%e, %E 지수 형태 실수형
%c 한 문자 정수형, 문자형
%s 문자열 문자열 포인터
%o 부호 없는 8진수 정수형, 문자형
%x, %X 부호 없는 16진수 정수형, 문자형

 

  #include <stdio.h>
  int main()
  {
    // 양식 변환 기호의 사용 예
    printf("%c\n", 'a');        //  a
    printf("%d\n", -123);       //  -123
    printf("%o\n", 123);        //  173
    printf("%x\n", 123);        //  7b
    printf("%X\n", 123);        //  7B
    printf("%f\n", 123.456789); //  123.456789
    printf("%e\n", 123.456789); //  1.234568e+02
    printf("%s\n", "asdf");     //  asdf

    printf("|%d|\n", 123);        // |123|      -> 숫자의 길이만큼 출력 폭이 자동 지정 됨.
    printf("|%5d|\n", 123);       // |  123|    -> 총 5자리 오른쪽 정렬.
    printf("|%-5d|\n", 123);      // |123  |    -> 총 5자리 왼쪽 정렬.
    printf("|%05d|\n", 123);      // |00123|    -> 총 5자리 공백은 0 오른쪽 정렬.
    printf("|%6.1f|\n", 123.45);  // | 123.5|   -> 소숫점 포함 총 6자리, 소수점 이하 1자리 출력
    printf("|%07.2f|\n", 123.45); // |0123.45|  -> 소숫첨 포함 총 7자리, 소수점 이하 2자리 출력, 공백은 0

    return 0;
  }

 

 

printf()

  • 형식 : printf("출력 양식", 변수1, 변수2, ..);
  • 기능 : 주어 진 출력양식으로 자료를 출력한다.
  • 사용 예
    • printf("This is an example\n");
    • printf("A=%d, B=%c\n", a, b);

 

  #include <stdio.h>

  int main()
  {
    char c = 'A';
    int i = 10, j = 20, k = 30;

    printf("simple print program\n");
    printf("c = %c, c\'s ASCII CODE : %d\n", c, c);
    printf("i = %d, j = %d, k = %d\n", i, j, k);

    return 0;
  }

 

 

putchar()

  • 형식 : putchar();
  • 기능 : 한 문자를 출력.
  • 사용 예
    • putchar('A');

 

  #include <stdio.h>

  int main()
  {
    char c = 'C';

    putchar(c);
    putchar(c + 1);   // 수식이 사용 됨.
    putchar('\n');    //  개항.
    putchar('E');     //  문자형 상수.
    putchar('E' + 2); // 수식 실행.
    putchar('\007');

    return 0;
  }

 

 

puts()

  • 형식 : puts(변수);
  • 기능 : 문자열을 입력 받음.
  • 사용 예
    • char s[50] = "Jeaha";
    • puts(s);

 

#include <stdio.h>

int main()
{
  char s1[] = "Jeaha In ";
  char s2[] = "The C Hell.";

  puts(s1);
  puts(s2); //  \n을 사용하지 않아도 자동으로 줄바꿈이 됨.

  printf("%s", s1);
  printf("%s\n", s2); //  \n을 사용하지 않아서 문자열이 연결되어 출력 됨.
  return 0;
}

 


 

표준 입력 함수

입력 양식 변환 기호

%문자 변환 기능
%d 정수
%ld long
%f 실수형
%lf double 실수형
%c 문자형
%s 문자열

 

scanf()

  • 형식 : scanf("입력 양식", &변수1, &변수2, ..);
  • 기능 : 주어진 양식으로 자료를 입력받아 지정된 변수에 저장.
  • 사용 예
    • scanf("%d", &d);

 

  #include <stdio.h>
  // 권장하지 않은 함수에 대한 경고 무시 요청.
  #pragma warning(disable : 4996)
  int main()
  {
    int i1, i2;
    float j1, j2;

    printf("\n>>> insert integer : ");
    scanf("%d %d", &i1, &i2);

    printf("\n>>> insert float or double : ");
    scanf("%f %f", &j1, &j2);

    printf("\n--------------------------------\n");
    printf("\nint\n\t1 : %d\n\t2 : %d\n", i1, i2);
    printf("\nfloat\n\t1 : %f\n\t2 : %f\n", j1, j2);

    return 0;
  }

 

 

getchar()

  • 형식 : getchar();
  • 기능 : 한 문자를 입력받아 지정된 변수에 저장.
  • 사용 예
    • a=getchar();

 

#include <stdio.h>

int main()
{
  char a;

  printf("\ninsert one char : ");
  a = getchar();
  printf("a = %c\n", a);

  return 0;
}

 

 

gets()

  • 형식 : gets();
  • 기능 : 문자열을 입력 받음.
  • 사용 예
    • char s[50];
    • gets(s);

 

  #include <stdio.h>
  #pragma warning(disable : 4996)
  int main()
  {
    char s[50];
    printf("\ninsert string : ");
    gets(s);

    printf("string inserted by gets() : %s\n", s);

    printf("\ninsert string : ");
    scanf("%s", s); //  공백 문자로 문자를 구분하기 때문에, 공백이 생기면 n개의 문자열로 인식함.
    printf("string inserted by scanf() : %s\n", s);

    return 0;
  }

 

728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 함수와 기억 클래스 - 1  (0) 2020.12.20
[C] 선택 제어문과 반복 제어문  (0) 2020.12.20
[C] 입출력 함수와 연산자 - 2  (0) 2020.12.20
[C] 자료형과 선행 처리기  (0) 2020.12.14
[C] C 언어의 개요  (0) 2020.12.13

자료형과 선행 처리기

상수와 변수의 기본 개념.
변수 등에 사용되는 자료형.
변수 선언과 선행 처리기의 종류, 활용 방법.

  • 학습 목표

    1. 여러 종류의 상수 이해.
    2. C 언어 변수와 변수 선언에 대한 의미.
    3. 변수 선언 시 고려할 사항.
    4. 기본 자료형의 종류와 범위 이해.
    5. 여러 선행처리기의 용도와 사용방법.
  • 주요 용어

    • 상수 (const) : 값이 한번 정해지면 그 값을 변경할 수 없는 수.
    • 변수 (variable) : 프로그램 실행도중 변할 수 있는 값이 저장되는 기억공간을 의미.
    • 자료형 (data type) : 사용하는 자료의 형태.
    • 초기화 : 선언된 변수에 특정 값을 부여하는 것.
    • 선행처리기 : 컴파일 하기 전에 미리 수행되어야 할 처리기.

상수와 변수

자료형

  • 프로그램에서 사용하는 자료의 형태.
  • 상수변수로 구분하여 사용.
  • 프로그램에서 자료(data)를 처리하기 위해 자료의 생성/처장/처리과정이 필요.
  • C 언어.
    • 수많은 명령어와 자료들로 구성.
    • 이들 자료의 정확한 처리와 효율적인 활용 필요.
  • C 언어는 여러가지 종류의 자료형(data type)을 지원.

상수 (constant)

  • 항상 고정된 값을 갖는 자료.
  • 값이 한번 정해지면 프로그램 도중 그 값을 변경할 수 없는 수.
    • 정수형 상수.
      • 10, 8, 16진수
      • 구분 비고
        10진 상수 10, -10, 999 0~9까지의 숫자를 사용. 0으로 시작 불가.
        8진 상수 011, 055 0~7까지 숫자를 사용, 숫자 앞에 0을 붙임.
        16진 상수 0xac, 0X2A 09, AF를 사용, 숫자 앞에 0x나 0X를 붙임.
        unsigned형 상수 12u, 067u, 0XFAU 부호 없는 상수를 표현하며, 숫자 뒤에 u나 U를 붙임.
        long형 상수 12345l, 0XFFL 큰 길이의 정수를 표현, 숫자 뒤에 l이나 L을 붙임.
    • 실수형 상수.
      • 부동소수점 형 상수.
      • double형을 기본 자료형으로 사용.
      • 구분 비고
        소수 형식 12.345, 3.14, .5 소수점을 사용하여 표현.
        자수 형식 12E3(=12000), 5e-2(=0.005) 10진수와 e(E)를 사용하여 표현.
        float형 상수 3.14f, 3.14e-3F 숫자 뒤에 f나 F를 붙임.
        long double형 상수 3.14l, 3.14E-3L 숫자 뒤에 l이나 L을 붙임.
    • 문자형 상수.
      • 단일 인용부호 '' 로 묶여 있는 1개의 영문자나 숫자문자.
      • 내부적으로는 해당문자의 ASCII CODE 값이 사용.
      • escape 문자
        • excape 기능
          \a 경고음 (alert) 출력
          \b 백 스페이스 (back space)
          \f 새 페이지 (foam feed)
          \n 출력 시 줄 바꿈 (new line)
          \r 커서를 행의 시작 위치로 이동 (carriage return)
          \t 수평 탭 (horizontal tab)
          \0 ASCII 코드 값이 0인 문자 (null 문자)
    • 문자열 상수.
      • 이중 인용부호 ""로 묶여 있는 복수개의 영문자나 숫자.
      • 기억공간에 보관될 때는 문자열 끝에 null 문자 \0가 추가.

변수(variable)

  • 변할 수 있는 값.
  • 프로그램 실행 도중 변할 수 있는 값이 저장 되는 기억공간을 의미.
    • i = 10; 은 i는 변수명이고, 10이란 값을 i라는 이름으로 정의된 기억공간에 저장한다는 의미.
  • 이런 변수 속에 들어가는 값은 수시로 변경될 수 있음.
  • 변수는 사용 전에 반드시 선언하여 컴파일러가 기억공간에서 일정 공간을 확보할 수 있도록 해야 함.

변수의 특징

  • 모든 변수는 이름이 있다.
  • 모든 변수는 정해진 자료형이 있다.
  • 모든 변수는 할당된 값을 갖는다.

변수의 정의 규칙

  • 모든 변수는 사용전에 선언되어야 함.
  • 반드시 영문자나 밑줄로 시작해야 함.
  • 중간에 _ 이외의 특수문자를 섞어 사용할 수 없음.
  • 대,소문자 구분 해야함.
  • 예약어는 사용할 수 없음.

변수의 사용 예

  #include <stdio.h>
  void main() {
    int a, b;   //  정수형 변수 a, b 선언.
    a = 100;    //  변수에 값 대입.
    b = 50;
    printf("a=%d, b=%d\n", a, b);
  }

자료형과 변수 선언

  • 변수.
    • 자료를 저장할 기억공간을 확보하고, 이 공간에 이름을 붙인 것.
  • 변수 선언.
    • 확보된 기억공간에 이름을 부여하는 것.
  • 이러한 변수 선언을 위해 자료형이 필요.

자료형의 종류

  • 기본형 (primitive)
    • 정수형 (integer type)
      • int, short, long, unsigned
    • 실수형 (floating-point type)
      • float, double, long double
    • 문자형 (charactor type)
      • char, unsigned char
    • 열거형 (enumerated type)
      • enum
    • 형 없음
      • void
  • 확장형
    • 배열 형 (array type)
    • 함수 형 (function type)
    • 포인터 형 (pointer type)
    • 구조체 형 (structure type)

정수형

  • int, short, long, unsigned
  • 운영체제에 따라 표현 범위가 다름.
정수형 표형 범위 크기
short int -32768 ~ 32767 2 byte
long int -214783648 ~ 214783647 4 byte
int -2147483648 ~ 2147483647 4 byte
unsigned short int 0 ~ 65535 2 byte
unsigned long int 0 ~ 429496795 4 byte
unsigned int 0 ~ 42959667295 4 byte

실수형

  • float (4 byte), double (8 byte), long double (8 byte)

문자형

  • char, unsigned char
  • ASCII 코드를 사용하여 처리.
정수형 표형 범위 크기
char -128 ~ 127 1 byte
unsigned char 0 ~ 255 1byte
  • 문자형 사용의 예
#include <stdio.h>

int main()
{
  printf("Hell The C\n");

  char ch;
  int in;
  ch = in = 'A';

  printf("ch = %d\n", ch); // ASCII 코드 출력
  printf("in = %d\n", in); // ASCII 코드 출력

  return 0;
}

열거형

  • 숫자 대신 단어 사용

  • 형싱 : enum 태그명 {열거자1, 열거자2, ...}

  • 열거형의 사용 예

#include <stdio.h>

int main()
{
  enum day1 { SUN, MON, TUE, WED, THU, FRI, SAT } d1;
  enum day2
  { sun = 2, mon, tue, wed, thu, fri, sat } d2;

  d1 = WED;
  d2 = wed;

  printf("열거형 d1에 저장된 값 %d\n", d1); // 3
  printf("열거형 d2에 저장된 값 %d\n", d2); // 5

  return 0;
}

변수 선언

  • 변수명과 변수가 가질 자료형을 지정하여 변수를 위한 기억공간을 할당하는 것.
  • 형식 : 자료형 변수명;
  • 사용 예
    • 정수 -> int 변수명;
    • 문자열 -> char 변수명 [문자수 + 1];

변수 선언 시 고려 사항

  • 변수에 저장될 값의 크기(범위).

    •   #include <stdio.h>
        void main()
        {
          short int n1, n2;
          n1 = 32767 + 1;
          n2 = -32768 - 1;
      
          printf("n1 = %d\n", n1); //  -32768
          printf("n2 = %d\n", n2); //  32767
          //  자료형 범위가 넘어가면 다른 값이 나옴.
        }
  • 변수 선언 위치.

    • 전역 변수로 선언 -> 프로그램 어디서나 사용 가능.

    • 지역 변수로 선언 -> 함수 내에서만 사용 가능.

    •   #include <stdio.h>
      
        int n = 100; //  전역변수 n 선언
        void func()
        {
          int n = 200; //  지역변수 n 선언
      
          printf("n in func() : %d\n", n); //  200
        }
      
        int main()
        {
          printf("n in main() : %d\n", n); //  100
          func();
          return n;
        }
  • 변수의 초기화.

    •   #include <stdio.h>
        int main()
        {
          int i, sum;
      
          for (i = 1; i < 10; i++)
          {
            sum += i;
          }
          printf("from 1 to 10 : %d\n", sum); //  32811
      
          return n;
        }

선행처리기 (preprocessor)

  • 컴파일에 앞서 프로그램 선두에 선언된 지시자들을 밀리 처리하는 역할 수행.
선행처리기 기능
#include 파일 포함
#define 매크로 정의
#if #else #elif #endif 조건부 컴파일

선행처리기 사용시 주의점

  • 반드시 #으로 시작해야 함.
  • 명령문 끝에는 ;을 붙이지 않음.
  • 한줄에 하나의 명령만 쓴다.
  • 소스 프로그램의 첫 부분에 위치한다.

파일 포함 : include

  • C언어에서 제공하는 헤더파일(*.h)을 자신의 소스파일에 읽어 들여 함께 컴파일 하고자 할 떄 사용.
  • 표준함수인 printf(), scanf()
    • 이 함수들의 원형 (prototype)이 선언되어 있는 표준 입출력 헤더파일인 stdio.h를 include 해야 함.
  • 형식
    • #include <파일명>
    • #include "파일명"
  • 사용 예
    • #include <stdio.h>
    • #include "stdio.h"
    • #include "/tc/lib/math.h"
  • 기능
    • #include 다음에 제시된 파일을 현재 프로그램에 포함시킴.
    • <파일명>은 표준 디렉토리(보통 include)에서 파일을 찾아 포함.
    • "파일명"은 현재 사용 중인 디렉토리나 지정된 디렉토리에서 파일을 찾아 포함하며, 또는 드라이브나 경로를 사용.

매크로 정의 : #define

  • 매크로를 정의할 때 사용.
  • 매크로 macro.
    • 선행처리기 #define을 사용하여 단순 치환되는 자료.
    • 프로그램 작성 시에 명령이나 수식 또는 상수 값이 자주 사용될 때 이들을 대표하는 이름을 붙여 사용하는 대상.
  • 매크로 정의.
    • 매크로 상수 정의.
    • 매크로 함수 정의.

매크로 상수 정의

  • 형식
    • #define 매크로명 자료
    • #define 매크로명
  • 사용 예
    • #define PI 3.141592
    • 이는 프로그램 내의 PI는 3.141592로 치환하라는 것.
  • 기능
    • 프로그램에 나오는 매크로 명을 지정한 자료로 치환한 후, 컴파일하거나 (#define), 정의 해제(#undef) 한다.
#include <stdio.h>
#define ADDR "192.168.0.1"
#define TEL "010-1234-5678"

int main()
{
  printf("ADDR : %s\n", ADDR);
  printf("TEL : %s\n", TEL);

  return 0;
}

매크로 함수 정의

  • 형식
    • #define 매크로명 (인수) (수식)
    • #define 매크로명 (인수, 인수) (수식)
  • 사용 예
    • #define AREA(x) (3.14 * (x) * (x) )
    • #define HAP(a, b) ( a + b )
  • 장점
    • 선행처리기에 의해 단순 치환 방식이므로, 전달 인자의 자료형을 명시할 필요가 없음.
    • 어떠한 자료형 변수를 인자로 전달해도 잘 작동함.
    • 한 두 줄의 코드인 경우 함수로 정의하는 것 보다 속도가 빠름.
#include <stdio.h>
#define ADD1(x, y) x + y
#define ADD2(x, y) ((x) + (y))
#define MULTIPLY1(x, y) x *y
#define MULTIPLY2(x, y) ((x) * (y))

int main()
{
  int a1, a2, m1, m2;

  a1 = 10 * ADD1(3, 4);
  a1 = 10 * ADD2(3, 4);

  m1 = MULTIPLY1(1 + 2, 3 + 4);
  m2 = MULTIPLY2(1 + 2, 3 + 4);

  printf("a1 : %d, a2 : %d\n", a1, a2);
  printf("m1 : %d, m2 : %d\n", m1, m2);

  return 0;
}

조건부 컴파일 : #if #else #elif #endif

  • 조건에 따라 프로그램을 컴파일하는 명령.
  • 최적의 코드로 프로그램을 작성할 수 있기 때문에 시스템 성능 향상.
  • #if, #elif 다음에는 컴파일 여부를 결정하는 조건문 필요.
    • 조건문은 선행처리과정에서 진위 여부를 판단할 수 있어야 함.
    • 변수 지정이나 함수 호출 불가.
    • 주로 매크로 값이 사용.
  #include <stdio.h>
  #define CON 0

  int main()
  {
  #if CON
    printf("\n COMPILE IF \n");
  #else
    printf("\n COMPILE ELSE \n");
  #endif
    return 0;
  }
728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 함수와 기억 클래스 - 1  (0) 2020.12.20
[C] 선택 제어문과 반복 제어문  (0) 2020.12.20
[C] 입출력 함수와 연산자 - 2  (0) 2020.12.20
[C] 입출력 함수와 연산자 - 1  (0) 2020.12.15
[C] C 언어의 개요  (0) 2020.12.13

C 언어의 개요

  • 주요 용어

    • compiler : 작성된 프로그램을 기계어로 변환해주는 번역기.
    • source code : 프로그램 안에 있는 명령어.
    • object file(목적파일) : .obj 확장자를 갖는 팡일로 기계어들의 집합으로 이루어진 파일.
    • linker(링커) : 여러 목적파일과 라이브러리 파일을 연결해 주는 도구.
    • reserved word(예약어) : C 언어에 미리 정의되어 있는 단어.

C 언어의 정의, 역사, 특징

C언어의 정의

  • 프로그래밍 언어
    • 사람과 컴파일러(compiler)가 이해할 수 있도록 약속된 형태의 언어.

Compiler

  • 프로그래밍 언어로 작성된 프로그램을 컴퓨터가 이해할 수 있도록 기계어로 번역해 주는 번역기.
    • 어셈블러(assembler) : 기호로 표현된 어셈블리 코드를 기계어로 번역하는 번역기.
    • 인터프리터(interpreter)
      • 소스 프로그램을 한번에 기계어로 변환시키는 컴파일러와는 달리,
        프로그램을 한 단계씩 기계어로 해석하여 실행하는 '언어처리 프로그램'

C언어의 역사

  • Denis Ritchie (1972)
  • Unix 운영체제 구현에 사용할 목적으로 개발.
    • 컴퓨터 기종간 호환성을 가진 고급이면서, 하드웨어를 제어할 수 있는 새로운 언어가 필요함.
  • 어셈블리 언어로 된 UNIX 운영체제가 거의 C 언어로 대체됨.

C 언어의 특징

  • 프로그램 이식성이 높음.
  • 간단한 문법 표현으로 함축적인 프로그램 작성이 가능.
  • 저급언어 특성을 가진 고급언어.

C 프로그램 작성 및 준비

프로그램 개발 단계

일반적인 프로그램 개발

  • 프로그램 목적 정의.
    • 요구 분석과 시스템 분석을 통하여 프로그램이 가져야 할 기능 정의.
  • 프로그램 설계.
    • 분석된 기능을 처리할 수 있도록 프로그램 구조 설계.
  • 소스코드 작성.
    • 작성된 프로그램 설계를 기반으로 에디터를 사용하여 작성.
  • 컴파일 / 링크.
    • 소스코드를 실행 가능한 코드로 변환하고 문법 검사.
  • 프로그램 실행.
    • 프로그램 실행.
  • 테스트와 디버깅.
    • 에러를 검사하고 디버깅.
  • 유지 보수.
    • 사용 중 발생 되는 에러나 추가적인 변경사항을 처리.

C 프로그램을 작성한다면

에디터와 컴파일러가 필요함

  • 에디터 : 소스코드를 작성하여 저장할 수 있도록 도와주는 도구.
  • C 컴파일러 : Turbo C/C++, Dev-C++, Visual C++, GCC, ...

C 프로그램의 완성 과정

코딩 -> 컴파일 -> 링킹

  • 코딩.
    • 주어진 문제에 대한 설계를 바탕으로 소스코드(source code)를 작성하여 소스파일(source file)을 생상하는 과정.
  • 컴파일(compile) 단계.
    • 소스파일이 목적파일(object file)로 변환되는 과정.
  • 링킹(linking) 단계.
    • 목적 파일을 실행파일(execution file)로 변환하는 과정.

\

소스파일의 생성

실행 파일의 생성(링킹 과정)

실제로는 컴파일 후, 링킹 과정을 거쳐 실행 파일이 나옴.
다만 링킹 과정을 거친다는 사실은 인지하고 있어야 함.


C 프로그램의 구성

C 개발을 할 때, 기본적인 틀을 만들어 사용 해야 함.
기본적인 C의 틀을 알아보자.

C 프로그램의 구조

  // 도입부 : 프로그램 전체에 적용되는 사항을 기술.
  /* C 프로그램 구조의 예*/
  #include<stdio.h>
  int add(int x, int y);
  // --------------------------------- //
  //  main()는 가장 먼저 호출되는 함수로서 모든 프로그램에 반드시 존재함.
  void main() {
    // 선언문
    // 치환문
    // 제어문
    // 함수 호출
  }
  // --------------------------------- //
  //  main()에서 호출되는 함수에 대한 정의
  호출될 함수() {
    //
  }
  • C 프로그램은 반드시 하나 이상의 함수를 포함해야 한다.
  • main()가 반드시 존재해야 한다.
  • 함수의 시작과 끝을 알리는 {}를 사용해야 한다.
  • 중괄호 안에는 변수 선언문, 치환문, 연산문, 함수 등의 명령을 기입한다.
  • 선행처리기(proprocessor)를 제외하고 문장의 끝에는 세미콜론을 붙인다.

C 프로그램의 구성 요소

  • 예약어(reserved)
    • 자료형 : char, int, float, short, long, double, unsigned, union, enum, void, ...
    • 기억 : auto, static, extern, register, ...
    • 제어 : ifelse, for, while, dowhile, wditch~case, break, continue, return, ...
    • 기타 : main, sizeof, include, ...
  • 명칭(idnetifier) : 변수, 배열, 함수, ... 등의 이름
    • 규칙
      • 영문자, 숫자의 조합.
      • 명칭의 첫 문자는 영문자나 _ 이어야 함.
      • _이외의 특수문자 사용 X.
      • 문자 사이에 공백 X.
      • 예약어 사용 X.
      • 대소문자는 구별하여 사용.
      • 명칭의 길이는 컴파일러에 다라 차이가 있음. (일반적으로 32자)
  • 상수 : 값이 불변인 자료.
  • 연산자 : =, -, *, /, ++, ...
    • 다른 언어에 비해 연산자가 많음.
  • 설명문 : 프로그램에 대한 주석.
    • /**/, //

에러와 경고

에러

  • C 언어의 문법상 잘못된 경우 에러.
  • C 언어 문법에 맞지 않은 형식의 사용이나, 반드시 필요한 지정이 빠진 경우 발생.
  • 에러 메세지를 확인하여 반드시 수정해야 함.

경고

  • 경미한 실수.
  • 큰 문제는 없지만, 이식성에 문제가 생기거나, C 언어 문법에서 권장하지 않은 방법으로 소스를 작성했을때 경고.
  • 무시해도 상관 없음.
728x90
반응형

'Language > C' 카테고리의 다른 글

[C] 함수와 기억 클래스 - 1  (0) 2020.12.20
[C] 선택 제어문과 반복 제어문  (0) 2020.12.20
[C] 입출력 함수와 연산자 - 2  (0) 2020.12.20
[C] 입출력 함수와 연산자 - 1  (0) 2020.12.15
[C] 자료형과 선행 처리기  (0) 2020.12.14

웹 서버

  • 학습 개요
    웹 서버의 동작 원리를 알아보고 리눅스 환경에서 웹 서버 구성을 위하여 널리 사용죄는 APM을 학습.
    Apache 웹 서버, PHP 처리기, MySQL을 각각 설치하고 Apache의 설정 방법을 알아봄.

  • 학습 목표

    1. 웹 서버의 동작 방법과 HTTP 프로토콜 설명 가능.
    2. Apache 웹 서버, PHP 처리기, MySQL 설치 가능.
    3. Apache 웹 서버의 주요 설정 항목을 설명 가능.
    4. APM을 이용하여 웹 서비스 제공 가능.

웹서버

  • 클라이언트의 HTTP 요청을 처리하여 웹 페이지의 내용을 클라이언트에게 제공하는 서버 프로그램.
    • 웹 페이지를 요청하고 보여주는 웹 브라우져는 클라이언트.
    • 서버와 클라이언트는 네트워크를 통해 연결 되므로, 웹 서버와 웹 브라우져 사이에 통신을 위한 프로토콜이 필요함.
  • 많이 사용되는 웹 서버 - Apache, ISS Nginx 등.
    • W3Techs에서 조사된 시장 점유율.
      • Apache 48.4%, Nginx 35.6%, IIS 10.7%

HTTP (HyperText Trasfer Protocol)

  • 웹 환경에서 서버와 클라이언트 간에 정보를 주고 받기 위한 프로토콜.
  • 요청(request)와 응답(response) 프로토콜.
    • 클라이언트가 서버에 특정 자원에 대한 요청(GET, POST 등)을 보냄.
    • 클라이언트의 요청에 대해 서버가 응답.
      • 응답코드 (200 OK, 404 Not Found 등)와 함께 요청한 자원을 전달.
  • 대부분 TCP를 사용하며, 포트(port)번호는 일반적으로 80번을 사용함.

APM (Apache, PHP, MySQL)

  • Apache HTTP 서버, PHP 스크립트 처리기, MySQL DB 관리시스템을 지칭
    • 동적으로 웹 페이지를 만들고, 웹 페이지 생성에 필요한 데이터를 관리할 수 있는 프로그램이 필요함
  • 모두 공개 소프트웨어로 웹 사이트 구축을 위한 비용절감의 방법으로 많이 사용.
  • 리눅스 시스템에서 많이 사용됨. LAMP(Linux, Apache, MySQL, PHP)이라고도 함.

APM을 이용하는 웹 서버의 동작 과정

  • 클라이언트가 웹 문서를 Apache 웹 서버에 요청.
  • 웹 문서 내에 있는 PHP 스크립트가 PHP 모듈 등에 의해 처리되어 HTML 문서가 생성되어 클라이언트에게 응답.
  • PHP 스크립트 처리 과정 중 MySQL DB에 접근하여, query를 수행.

PHP (HyperText Processor) 스크립트 처리기

  • PHP는 동적으로 웹 페이지를 생성할 수 있는 스크립트 언어.
  • 서버에서 실행되며 HTML 파일에 포함하여 사용함.
  • PHP 대신 다른 스크립트 언어인 Perl이나 Python을 이용하여 APM 구축 가능.

MySQL DBMS

  • DBMS로 C/C++, C#, Java, PHP 등의 언어에서 사용할 수 있도록 API를 제공.
  • PHP에서 MySQL을 사용하려면 'php-mysql' 패키지를 설치해야 함.

APM 설치

  • 대부분의 리눅스 배포판이 APM을 포함하고 있음.
  • 다음 명령으로 설치 여부 확인 가능.
    • yum list installed | grep httpd
    • yum list installed | grep mysql
    • yum list installed | grep php
  • httpd는 Apache HTTP 서버 프로그램 이름으로 http deamon을 의미.
  • 설치 순서
    1. 최신 파일을 이용한 설치 명령.
      • yum -y install httpd
    2. Apache update 명령.
      • yum -y update httpd
    3. Apache 설치 후 MySQL 설치 명령.
      • yum -y install mysql mysql-server
    4. MySQL 설치 후, PHP 설치.
      • yum -y install php
      • yum -y install php-mysql
  • 데스트톱 메뉴의 패키지 관리도구(시스템 > 관리 > 소프트웨어 추가/제거)에서도 설치 가능.

Apache, PHP 설치 확인 방법

  • 방화벽 설정(tcp 80 port)와 httpd 실행 여부 확인.
  • Apche
    • 브라우져에서 http://localhost 접속.
  • PHP
    • /var/www/html/test.php
    •   <?php
          phpinfo();
        ?>
    • 브라우져에서 http://localhost/test.php 접속.

Apache 설정

  • Apache 설정 파일은 /etx/httpd/conf/httpd.conf
    • 전역의 기본 설정을 가지며 1000 라인이 넘음.
    • /etc/httpd/conf.d 디렉토리도 기타 설정 파일이 위치함.
  • 설정을 변경한 후에는 Apache 서버를 다시 시작해야 적용됨.
    • service httpd restart
  • 현재 런레벨에서 서비스 활성화 방법.
    • 부팅 시 자동으로 서비스를 시작하게 하는 방법.
    • chkconfig httpd on
  • 요청과 응답
    • /var/www/html/ 디렉토리에 index.html 파일 생성.
    • http://localhot/index.html 요청하여 확인.

Apache 설정 파일에서 지시어 목록 참고

  • 참고
  • 이후의 내용은 httpd.conf 파일에서 사용되는 지시어를 설명함.

ServerTokens

  • 서버의 응답 헤더 설정
value ex
Prod Server: Apache
Major Server: Apache/2
Minor Server: Apache/2.0
Min Server: Apache/2.0.41
OS Server: Apache/2.0.41 (Unix)
Full Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2

ServerRoot

  • Apache 서버가 설치된 디렉토리.
    • 서버가 설정 파일이나 로그 파일을 보관하는 디렉토리.
    • 설정 파일에서 파일을 참조할 때의 기준 디렉토리.
  • 일반적으로 기본값 /etc/httpd

Timeout

  • 클라이언트로부터 수신을 기다리는 최대 대기 시간을 초 단위로 설정.
  • 설정값이 60인 경우.
    • 서버는 60초 이내에 클라이언트로 부터 TCP 패킷을 모두 받거나,
      클라이언트에 데이터를 보낸 후 60초 이내에 클라이언트로부터 확인(ACK) 패킷을 받아야 함.

PidFile

  • 주 서버 프로세스로 httpd의 PID가 기록되는 파일을 설정함.
  • run/httpd.pid로 설정된 경우
    • 서버가 실행 중이라면, 해당 파일에 httpd의 PID로 31038이 저장되어 있음.

KeepAlive

  • 클라이언트가 한 번 연결로 서버와 여러 번의 요청과 응답을 주고받을 수 있도록 지속적인 연결을 허용할지 여부를 On 또는 Off 로 설정.
    • HTTP/1.0 까지는 한 쌍의 요청과 응답이 끝나면 TCP 연결이 끊어짐.
    • HTTP/1.1 ~ 이후에는 KeepAlive를 On으로 설정하면 클라이언트가 한 번의 연결로 서버에 여러 번 요청후 응답 받을 수 있음.

MaxKeepAliveRequests

  • KeepAlive가 On으로 설정된 경우, 클라이언트가 지속적인 연결을 유지하며 보낼 수 있는 최대 요청의 수를 설정.
  • 서버의 성능을 극대화 시키기 위해서 큰 값으로 설정함.
  • 기본값은 100, 0으로 설정하면 제한 없이 요청 받음.

KeepAliveTimeout

  • 연결을 끊지 않고 다음 요청을 대기하는 최대 시간
    • KeepAlive가 On으로 설정된 경우, 연결을 유지하면서 클라이언트의 다음 요청을 기다리는 최대 대기 시간을 초 단위로 설정.
    • 15로 설정하면 15초 동안 클라이언트로부터 요청을 기다림.
    • 큰 값으로 설정하는 경우에는 서버 성능에 문제가 발생될 수 있음.

StartServers

  • 초기에 생성하는 자식 서버 프로세스의 수를 설정.
  • 8로 설정된 경우, PidFile에서 PID가 같은 httpd가 8개의 자식 프로세스를 초기에 생성함.

MinSpareServers & MaxSpareServers

  • 유휴 자식 서버 프로세스 수의 최솟값, 최댓값 설정
    • 유휴 자식 프로세스 수가 부족하거나 초과시, 자식 서버 프로세스를 생성하거나 종료시키는 기준이 됨.
  • 최솟값이 5, 최댓값이 20으로 설정된 서버
    • 유휴 자식 서버 프로세스가 5라면, 5개를 유지하기 위해 클라이언트의 요청이 있을 때 자식 서버 프로세스를 계속 생헝.
    • 유휴 자식 서버 프로세스가 20이라면, 20개를 유지하기 위해 클라이언트의 요청이 끝날 때 자식 서버 프로세스를 계속 삭제.

MaxClients

  • 동시에 접속 가능한 클라이언트 수의 최댓값.

MaxRequestsPerChild

  • 1개 자식 서버 프로세스가 종료 전까지 처리할 수 있는 최대 요청 수.
  • 설정 값이 4000인 경우.
    • 자식 서버 프로세스가 처리한 요청 수가 4000을 초과하면 해당 자식 서버 프로세스를 종료함.
    • 설정 값이 0인 경우는 요청 수에 제한이 없음을 의미.

Listen

  • 서버가 사용할 TCP 포트 번호 설정.
    • 일반적으로 80
    • port 또는 ip:port를 지정함.
    • ex )
      • 모든 네트워크 인터페이스로부터 오는 80번 포트에 대한 요청을 받아들이며 다른 포트를 추가지정 가능.
      •   Listen 80
          Listen 8080
      • 특정 IP만 허용하는 방법
          Listen x.x.x.x:80

LoadModule

  • 웹 서버의 기능을 확장시키는 DSO(Dynamic Shared Object)모듈을 설정
    • Apache 웹 서버의 특징 -> 모듈화.
    • 모듈을 추가로 로드함으로 새로운 기능 추가 가능.
  • 설정 값 형식
    • 모듈 이름을 먼저 쓰고, 그 다음 해당하는 파일명을 씀.
  • 여러 모듈을 로드하려면 다음과 같이 각각의 줄로 설정.
    •   LoadModule a_module a_module_dir
        LoadModule b_module b_module_dir
        LoadModule c_module c_module_dir

User와 Group

  • Apache 서버의 실행에 사용되는 사용자와 그룹.
    • 서버 프로세스의 사용자와 그룹을 지정함.
  • 서버는 초기에 root 계정으로 실행되나, 일단 실행 된 후에는 낮은 권한의 계정으로 실행되어야 함.
    • 기본적으로 사용자와 그룹 이름은 apache.
    • 서버 프로세스가 root 권한으로 실행되면, 악의적인 클라이언트에 의한 요청이 root 권한으로 실행되어 보안문제가 발생함.
    • User와 Group을 root로 지정하면 안됨.

ServerAdmin

  • 웹 서버 관리자의 이메일 주소를 설정.
    • 서버에 문제가 생겼을 때, 클라이언트로 보내지는 오류 메세지에 포함되는 메일 주소.

DocumentRoot

  • 웹 서버가 웹 콘텐츠를 저장하는 루트 디렉토리.
    • 사용자 요청에 의해 웹 서버가 웹 페이지를 찾을 때의 루트 디렉토리
  • 기본 설정 값은 /var/www/html
    • http://localhost/test.html에 대한 웹 페이지 요청은 서버 컴퓨터에서 /var/www/html/test.html 파일에 대한 요청임.

UserDir

  • 클라이언트 요청에서 ~ userid가 있는 경우의 처리 여부를 설정.
    • 루트 사용자 이외의 다른 사용자가 자신의 계정으로 홈페이지를 만들 때의 기본 디렉토리를 설정.
  • 설정 값이 public_html 인 경우.
  • 설정 값이 disabeld로 설정된 경우.
    • 사용자 계정의 홈 디렉토리로 변환하지 않음.
  • public_html로 설정하였으나 해당 사용자의 웹 페이지가 열리지 않는다면, 사용자 디렉토리의 mod를 확인 해야 함.
    • 홈 디렉토리인 ~ userid는 711, ~ userid/public_html음 755여야 함.
    • 설정이 잘몬 될 경우 403 에러가 남.

DirectoryIndex

  • 클라이언트가 디렉토리를 요청한 경우, 기본으로 사용할 웹 페이지의 파일 이름을 설정.
    • 일반적으로 index.html을 설정.
  • http://localhost/docs/를 요청한 경우.
    • /var/www/html/docs/index.html 파일이 있으면 이것을 보냄.
    • 없다면 디렉토리 목록을 보여줌.

ErrorLog

  • 웹 서버의 에러 로그가 기록될 파일을 설정
  • 설정 값이 logs/error_log인 경우, ServerRoot의 설정 값에 더해져서 /etc/httpd/logs/error_log 파일에 에러 로그가 기록 됨.
    • /var/log/httpd/access_log 파일에는 엑세스 정보가 기록 됨.

AddLanguage

  • 웹 서버를 통해 서비스되는 웹 문서의 지원 언어를 설정
    • 웹 서버가 다국어 페이지를 제공하는 경우.
  • 한국어를 추가하는 경우 ko .ko를 설정 값으로 추가하면 됨.
    • 언어와 파일 확장자를 표시.
  • 언어를 추가할 때마다 다음과 같이 새로운 줄로 설정.
  AddLanguage ca .ca
  AddLanguage cs .cz .cs
  AddLanguage ko .ko

AddDefaultCharset

  • 웹 서버에서 제공하는 응답 문서의 Content-Type이 text/plain 또는 text/html인 경우 기본 문자 집합을 설정.
    • 설정 값이 UTF-8인 경우, 응답 헤더에 Content-Type:text/html;charset=UTF-8 과 같은 것이 만들어 짐.
  • 기본 문자 집합을 설정하지 않으려면 설정 값을 Off로 지정.

APM을 이용한 웹 서비스

PHP 설정

  • /etc/httpd/conf.d/php.conf
    • APM과 관련한 PHP 스크립트 처리기의 설정 파일
    • php.conf의 설정들은 Apache 서버의 설정에 추가되는 것들로, httpd.conf에서 사용하는 설정명을 따름.
    • PHP 자체의 기본 설정 파일로 /etc/php.ini가 존재함.

MySQL 설정

  • /etc/my.cnf
    • MySQL 설정 파일
      • datadir=... : 데이터 디렉토리 설정
      • socket=... : 사용할 소켓 파일 설정
      • user=... : 사용할 계정 설정
  • /usr/share/mysql
    • 시스템 규모에 따른 다양한 설정 파일 제공됨.
  • 추가 설정
    • mysql_secure_installation 을 실행하여 다음 설정 진행.
    • root 계정의 비밀번호 설정.
    • 익명 사용자 허용 여부, root 계정의 원격 로그인 허용.
    • test Data의 제거 여부.
728x90
반응형

원격관리

  • 학습 개요
    telnet, ftp, rcp 등 원격 관리를 위한 전통적 방법을 알아보고 문제점을 파악해 보자.
    암호화를 이용하는 SSH 서비스에 관해 알아보고, OpenSSH 퍀지의 설치 여부와 방화벽 설정 및 서비스 실행 여부를 확인해 보자.
    ssh, sftp, scp 등 다양한 SSH 클라이언트 프로그램의 사용법을 알아보자.

  • 학습 목표

    1. telnet, ftp, rcp의 보안 취약점을 설명 가능.
    2. OpenSSH 패키지 설치.
    3. 방화벽 설정과 서비스 설정, SSH 서버 운영 가능.
    4. ssh, sftp, scp 클라이언트 프로그램 사용 가능.

전통적인 방법

전통적 원격 접속 방법

  • telnet, rlogin, rsh, ftp, rcp 등.
  • 전통적인 방법들은 암호화가 되지 않은 데이터를 주고 받음.
    • 도청이나 위변조 등 보안에 취약함.
  • 현재 거의 쓰지 않음.

telnet

  • 원격 컴퓨터에 telnet 프로토콜로 접속하는 프로그램
    • 사용자 계정, 비밀번호를 이용하여 원격으로 로그인 함.
  • telnet [-l user] host || telnet user@host
    • -l 생략 할 경우 호스트로부터 사용자 계정을 요구 받음.
    • -l 옵션 대신 @을 이용, 사용자 계정을 제시할 수도 있음.
  • 사용이 끝나면 logout 또는 exit을 이용하여 로그아웃.

ftp

  • 원격에서 터미널로 접속하여 파일을 업로드하거나 다운로드 할 수 있는 파일 전송 프로토콜 또는 프로그램

rcp

  • 원격의 컴퓨터와 서로 파일을 복사하는 프로그램
    • cp 명령과 유사
  • rcp [-r] source_file target_file
    • source_file을 target_file로 복사함.
    • ex) rcp a.txt jeaha@aws.ip:.
    • target_file이 디렉토리라면 해당 디렉토리에 source_file을 복사함.
    • -r 옵션을 사용하면 source_file이 디렉토리이며,
      그 안의 모든 서브 디렉토리도 함께 target_file 디렉토리로 복사함.
    • 원격 파일의 경우 [user@]host[:remote_file]의 형태.
  • rcp는 ftp와 달리 일회성으로 파일을 전송함.

Secure Shell (SSH)

  • telnet, ftp, rcp 등의 서버와 클라이언트 간 연결을 통해 주고 받는 모든 명령과 결과 및 계정 정보 등이 암호화 되지 않는 문제가 있음.
  • SSH는 원격 로그인이나 원격 데이터 통신에 사용되는 프로토콜로 패킷을 암호화하여 전홍
    • 전통적인 원격 관리 방법들의 문제점을 해결함.
  • 서버 / 클라이언트 구조로 동작하며, 보통 TCP 포트 22를 사용하여 서로 통신함.
    • 보안을 위해 우선 전자서명을 이용하여 서버와 클라이언트 간 연결을 인증하고, 그 후 서버와 클라이언트 간에 주고받는 메세지를 모두 암호화 함.
  • SSH를 사용하기 위해 필요한 프로그램
    • Server : sshd가 deamon 형태의 프로세스로 동작 중이어야 함.
    • Client : 사용 목적에 따라 ssh, sftp, scp 등이 필요.

OpenSSH 패키지

  • SSH 프로토콜을 사용하는 패키지로 공개 소스 프로그램.
    • 암호화된 안전한 통신을 제공하는 네트워크 연결 도구의 집합.
      • server : sshd
      • client : scp, sftp, ssh
  • 현재 대부분의 리눅스 배포판에 OpenSSH가 포함되어 있음.
    • 설치 확인 : yum list installed | grep openssh
    • 서버 설치 : yum -y install openssh openssh-server
    • 클라 설치 : yum -y install openssh-clients
    • 업데이트 : yum -y update openssh
  • 전역 설정 파일은 /etc/ssh/ 디렉토리에 저장됨.
  • 개별 사용자 설정 파일은 ~/.ssh/ 디렉토리에 저장됨.

SSH 서버의 실행

  • SSH를 이용하기 위해서는 sshd 데몬이 실행 중이어야 함.
    • 실행 : service sshd start
    • 중지 : service sshd stop
    • 상태 : service sshd status
  • 부팅 시 자옫으로 데몬을 시작시킬 수 있음(활성화).
    • 런레벨 별 서비스의 활성화 여부 확인은 chkconfig --list sshd.
    • 부팅 시 자동 실행 방법은 chkconfig sshd on.

서비스 설정 도구

  • 데스크탑 메뉴에서 '시스템 관리 > 관리 > 서비스' 실행.
  • '서비스 설정'창을 연 후 sshd를 찾아서 활성화 및 활성 상태를 확인하고 변경 가능.

방화벽 설정

  • 방화벽을 사용 중이라면, 설정을 확인한 후 사용하려는 서비스의 해당 포트와 프로토콜을 열어둬야 함.
    • 원격의 사용자가 어떤 서비스를 사용할 수 있는지를 제어할 수 있음
    • 방화벽 설정 파일은 /etc/sysconfig/iptables
  • 데스크탑 메뉴에서 '시스템 > 관리 > 방화벽'
    • 방화벽 설정 창에서 [신뢰하는 서비스] 선택, 해당 서비스를 선택, 적용.
    • [비활성화]는 방화벽을 사용하지 않는다는 뜻.

가상 머신의 SSH 서버에 접속하기

  • 호스트 PC 또는 외부 가상 머신에 설치된 sshd 또는 httpd에 접속.
    • 호스트 PC는 네트워크 인터페이스를 가지고 있음.
    • 가상 머신은 별도의 가상 네트워크 인터페이스를 가짐.
    • 가상 머신의 IP 주소는 기본적으로 10.0.2.15로 할당 됨.
  • 방법
    • 가상 머신의 리눅스에서 방화벽 설정 확인.
    • 가상 머신 리눅스에서 서버 프로세스 실행 여부 확인.
  • Port Forwarding 설정
    • 호스트 PC의 IP 주소와 Port 로 접속할 때,
      가상 머신의 IP 주소와 Port로 연결.

SSH 클라이언트 - 원격 접속

  • ssh는 SSH 서버에 원격으로 접속하기 위한 클라이언트 프로그램
    • 사용자 계정과 비밀번호를 이용하여 로그인하고, 이후에는 컴퓨터에 직접 로그인한 것과 동일하게 이용할 수 있음.
    • telnet, rlogin, rsh 등을 대체
  • [-l user] host || ssh user@host
    • ssh -l jeaha 192.168.0.10과 같이 실행.
    • ssh에서는 telnet과 같이 리눅스 명령어의 사용이 가능함.
    • exit, logout 명령으로 로그아웃.
  • 클라이언트 컴퓨터에서는 ~/.ssh/know_hosts 파일에
    원격으로 접속했던 호스트의 호스트 명, 암호의 종류, 원격 호스트 공개 키를 저장.
  • 윈도우에서는 공개 소프트웨어인 Putty 또는 Xshell을 클라이언트 프로그램으로 이용해서 접속 가능.

SSH 클라이언트 - 원격 파일 전송 : sftp

  • sftp는 서버에 원격 접속하여 파일을 업로드 하거나 다운로드 할 수 있는 클라이언트 프로그램.
    • 암호화된 연결릉 제외하면 사용 방법은 ftp와 같음.
  • sftp [user@]host
    • sftp jeaha@192.168.0.20
    • 원격 호스트 접속에 성공하면 지정된 사용자 계정의 호스트를 이용할 수 있음.
      • 업로드 : put localfile
      • 다운로드 : get remotefile
  • sftp 명령
CMD DESC
help sftp에서 사용할 수 있는 명령 조회
ls 원격 작업 디렉토리 조회
cd path 원격 작업 디렉토리 변경
mkdir path 원격 디렉토리 생성
chmod mode path 파일 path에 대한 권한을 mode로 변경
get 파일을 원격 서버에서 로컬 클라이언트로 받음
put 파일을 로컬 에서 원격으로 보냄
mget 여러 파일을 원격으로 부터 로컬로 받음. 파일 이름에 wildcard 가능
mput 여러 파일을 로컬에서 원격으로 보냄. wildcard 가능.
bye, exit, quit 종료

SSH 클라이언트 - 원격 파일 복사 : scp

  • 원격의 컴퓨터와 서로 파일을 복사하는 명령
  • scp [-r] source_file target_file
    • 소스(또는 타겟) 파일이 원격에 존재하는 경우
  • sftp로도 scp 기능을 수행할 수 있음.
    • 대화식이 아닌 일회성으로 파일을 전송하는 것이 가능.
728x90
반응형

유지보수나 기능 개선프로젝트를 진행하면서 분기 처리 부분에서 가독성이 떨어지는 코드를 많이 보게 되었다.
종종 이런 코드는 가독성이 떨어지는건 물론이고 코드 작성자 본인도 가독성 문제로 오류를 만들어 내는 로직도 있었다.

 


연산자 우선 순위

좋은 분기분을 만들기 전에 언어별 연산자 우선순위를 알아야 한다.
결합 방법에 대해서는 언어별, 버전별 기준으로 정확하지 않으니 참고만 하면 된다.
언어별 연산자 우선순위는 사칙 연산에서 곱셈/나눗셈이 덧셈/뺄셈보다 먼저 이뤄지는 것처럼 이해하면 된다.

 


java 연산자 우선순위

우선순위 연산 기호 결합 방향
1 [], . >>>>
2 x++, x-- <<<<
3 ++x, --x,_x, -x, ~, !, (type) <<<<
4 *, /, % >>>>
5 +, - >>>>
6 <<, >>, >>> >>>>
7 <, >, <=, >=, instanceof >>>>
8 ==, != >>>>
9 & >>>>
10 ^ >>>>
11   >>>>
12 && >>>>
13    
14 ? a : b <<<<
15 =, +=, -=, *=, /=, %=, &=, ^=, !=, <<=, >>=, >>>= <<<<

 

javascript 연산자 우선순위

자바스크립트 연산자 우선순위(비트 연산자 제외)
순위 기능 연산자
1 괄호 ()          
2 증감/논리 연산자 not ++ -- !      
3 산술 연산자 곱셈 * / %      
4 산술 연산자 덧셈 + -        
5 비교 연산자 대소 < <= > >=    
6 비교 연산자 같음 == === != !==    
7 논리 연산자 and &&          
8 논리 연산자 or ||          
9 대입 연산자 = += -= *= /= %=

 

python 연산자 우선순위

우선순위 연산자 설명
1 (값...), [값...], {키: 값...}, {값...} 튜플, 리스트, 딕셔너리, 세트 생성
2 x[인덱스], x[인덱스:인덱스], x(인수...), x.속성 리스트(튜플) 첨자, 슬라이싱, 함수 호출, 속성 참조
3 await x await 표현식
4 ** 거듭제곱
5 +x, -x, ~x 단항 덧셈(양의 부호), 단항 뺄셈(음의 부호), 비트 NOT
6 *, @, /, //, % 곱셈, 행렬 곱셈, 나눗셈, 버림 나눗셈, 나머지
7 +, - 덧셈, 뺄셈
8 <<, >> 비트 시프트
9 & 비트 AND
10 ^ 비트 XOR
11    
12 in, not in, is, is not, <, <=, >, >=, !=, == 포함 연산자, 객체 비교 연산자, 비교 연산자
13 not x 논리 NOT
14 and 논리 AND
15 or 논리 OR
16 if else 조건부 표현식
17 lambda 람다 표현식

 


단축 평가 (Short-circuit Evaluation)

단축 평가는 and(&&) 연산자와 or(||) 연산자의 원리를 이해하면 쉽다.

    if( condition1 && condition2 && condition3 && condition3 )

위와 같이 && 연산자로 여러 boolean 값의 상황이 있을 때, && 연산자는 하나의 조건이라도 false면 결과가 false 이기 때문에,
condition1이 false라면 굳이 뒤에 있는 2, 3, 4를 확인하지 않는다.

    if( condition1 || condition2 || condition3 || condition3 )

마찬 가지로 || 연산자로 여러 boolean 값의 상황이 있을 때는 condition1이 true면 그다음 조건은 검사하지 않는다.
이런 단축 평가의 개념으로 boolean 값이 간단하게 나오는 상황을 앞 쪽에 적용하면 빠르게 처리할 수 있다.

 


가독성 높은 분기 처리 방법

중첩 if

일반적으로 개발할 시 긍정적(유효한) 상황을 염두하고 개발을 하는데,
지속적으로 유효성을 체크하는 로직이 들어갈 경우 if 문이 계층구조처럼 구성이 만들어지기도 함.

    Object getUserInfo() {
      Session session = getSession();
      if( session != null ) {
        User user = session.getAttribute("loginUser");
        if( user != null ) {
          String id = user.getId();
          if( id != null ) {
            // 처리할 로직
          }
        }
      }
    }

 

중첩 if - 개선

역으로 부정적(유효하지 않는) 상황을 염두하고 분기 처리를 하면, 가독성과 구조적으로 좋은 코드가 나옴.
실제 처리할 로직이 시작하기 전에 유효하지 않는 상황으로 분기되면 해당 메소드나 함수를 return이나 예외 처리로 벗어나는 것을 보호절 숙어 라고 함.

    Object getUserInfo() {
      Session session = getSession();
      if( session == null ) return;

      User user = session.getAttribute("loginUser");
      if( user == null ) return;

      String id = user.getId();
      if( id == null ) return;

      // 처리할 로직
    }

 

 


loop 내에서의 분기 처리

    String line;
    while( line = reader.readline() ) {
      if( line.startsWith('#') || line.isEmpty() )
        continue;

      //  처리할 로직
    }

 

 


가독성을 위한 if

좌변에 유동적인 값이나 표현을 넣고, 우변에 상수와 같은 고정 값을 넣어야 가독성이 좋아짐.

    if( 10 <= length )

    //  아래가 더 보기 편함.
    if( length >= 10 )

 

 


if/else 블록의 순서

  • 가능하다면 if 조건 안에는 긍정 조건을 넣어야 가독성이 좋음.
  • 단, if/else 처리 로직 중 간단한 로직을 먼저 if 절에 넣는 것이 가독성이 좋음.
  • 단, 보호절 숙어가 우선순위가 높음. 부정의 조건을 넣어서 계층 구조를 만들지 않을 수 있다면 이게 더 낫다는 의미.
  •   if( hasAuth ) {
        // 간단하고 긍정적인 내용
      } else {
        // 상대적으로 복잡하고 긴 내용
      }

 


삼항 연산자

  • 간단한 구문일 경우 : 삼항 연산자.
  • 복잡한 구문일 경우 : if/else.

삼항 연산자는 코드 한 줄로 가독성을 챙길 수 있으며, 한 줄로 처리하기 복잡할 경우에는 if/else를 사용하는 게 낫다.

  • 삼항 연산자가 이득인 경우
  • let timeType = hour < 12 ? 'am' : 'pm';
  • if/else가 이득인 경우
  •   let timeKor, timeEng;
      if( hour < 12 ) { 
          timeKor = '오전';
        timeEng = 'am';
      } else { 
          timeKor = '오후';
        timeEng = 'pm';
      }

 


복잡한 분기 추출

재사용되거나, 분기 절 내의 복잡한 내용을 메소드로 표현하게 되면 더 나은 가독성을 얻을 수 있다.

  • 기존
  •     if( user.id == post.registerId ) {
            // 사용자가 게시물의 작성자 이다.
        } else {
            // 사용자가 게시물의 작성자가 아니다.
        }
  • 개선
  •     boolean isEditable = isOwner( user, post );
        if( isEditable ) {
            // 사용자가 게시물의 작성자 이다.
        } else {
            // 사용자가 게시물의 작성자가 아니다.
        }
        boolean isOwner( User user, Post post ) { return user.id == post.registerId; }

 


드모르간 법칙

괄호 중첩이 적을수록 가독성이 좋다.

  • 기존
  • if( !(hasfile && !isPrivate) ) return false;
  • 개선
  • if( !hasFile || isPrivate ) return false;

 


복잡한 논리 가독성 향상

한 라인으로 논리를 표현하지 않고, 가독성을 위해 적절한 여러 라인으로 분리하여 보호절과 유사하게 한다.

  • 기존
  •   public class Range {
        private int bgn;
        private int end;
        // this의 bgn이나 end가 other의 bgn이나 end에 속하는지 확인
        private boolean isOverlapsWith( Range other ) {
          return ( this.bgn >= other.bgn && this.bgn < other.end )
              || ( this.end > other.bgn && this.end <= other.end )
              || ( this.bgn <= other.bgn && this.end >= other.end );
        } 
      }
  • 개선
  •   public class Range {
        private int bgn;
        private int end;
        // this의 bgn이나 end가 other의 bgn이나 end에 속하는지 확인
        private boolean isOverlapsWith( Range other ) {
          // this가 시작하기 전에 끝난다.
          if( other.end <= this.bgn ) return false;
          // this가 끝난 후에 시작한다.
          if( other.bgn >= this.end ) return false;
          // 겹친다.
          return true;
        }
      }

 


switch 문의 사용

if-else 문은 각 조건문을 iterate 하며 로직을 결정한다. N개의 if-else 구문이 있다면 N번의 조건 여부를 판단한다.
switch 문은 입력받은 케이스로 로직이 바로 넘어가게 된다.
일반적으로 4개 이상의 조건일 때 if-else 보다 switch 문을 사용하는 것이 성능에 좋다고 한다.

시간 복잡도

다음은 if-else와 switch의 시간 복잡도이다.

  • if-else : O(N)
  • switch : O(logN)
  int num = 5;
  int ret;

  if (num == 0)      ret = num;
  else if (num == 1) ret = num;
  else if (num == 3) ret = num;
  else if (num == 5) ret = num;
  else if (num == 7) ret = num;
  else               ret = num;

  System.out.println(ret);
  int num = 5;
  int ret;

  switch (num) {
    case 0: ret = num; break;
    case 1: ret = num; break;
    case 3: ret = num; break;
    case 5: ret = num; break;
    case 7: ret = num; break;
    default: ret = num; break;
  }
  System.out.println(ret);

 

 


참고자료 :

728x90
반응형

jstl 내장함수

JSTL functions은 JSTL에서 제공하는 각종 함수를 사용해서 문자열이나, 컬렉션들을 처리함.
fn태그는 단독으로 사용할 수 없고 EL 표현식 내에서 사용해야함.
like ${fn:length(...)}

jsp 페이지 시작점에 다음 태그로 선언 해줘야 사용 할 수 있음.

  <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

 


 

boolean contains(String sting, String substring)

string이 substring을 포함하면 return true.

boolean containsIgnoreCase(String string, String substring)

대소문자에 관계없이, string이 substring을 포함하면 return true.

 

  ${fn:contains("helloworld", "world")} // true

  ${fn:containsIgnoreCase("hello world!", "WoRLd")} // true

 


 

boolean startsWith(String string, String prefix)

string이 prefix로 시작하면 return true.

boolean endsWith(String string, String substring)

string이 suffix로 끝나면 return true.

 

  ${fn:startsWith("hello world!", "ld!")} // false

  ${fn:endsWith("hello world!", "ld!")} // true

 


 

String escapeXml(String string)

string에서 XML, HTML의 < >& ' " 문자들을 각각 < > & ' "로 치환하여 리턴.

 

  <c:out value="${fn:escapeXml('<>')}"/> // &lt;&gt;

 


 

int indexOf(String string, String substring)

string에서 substring이 처음으로 나타나는 인덱스 리턴.

 

  ${fn:indexOf("abcdefg", "f")} // 5

 


 

String[] split(String string, String separator)

string 내의 문자열을 separator에 따라 잘라내서 잘려진 문자열들을 배열로 리턴.

String join(String[] strings, String separator)

배열 요소들을 separator를 구분자로 하여 모두 연결해서 리턴.

 

// 예시를 위한 배열 생성
<c:set var="texts" value="${fn:split('Hi My name is waldo', ' ')}"/>
<c:out value="${fn:join(texts, '-')}"/> // Hi-My-name-is-waldo

 


 

int length(Object item)

item이 배열이나 컬렉션이면 요소의 개수를, 문자열이면 문자의 개수를 리턴.

 

<c:set var="texts" value="${fn:split('Hi My name is waldo', ' ')}"/>

${fn:length(texts)} // 5

${fn:length("123456")} // 6

 


 

String replace(String string, String before, String after)

string 내에 있는 before 문자열을 after 문자열로 모두 바꿔서 리턴.

 

${fn:replace("hi hello", "hello", "hi")} // hi hi

// replace 함수는 HTML에서 공백과 줄바꿈을 표현할 때 사용할 수 있다.
${fn:replace("hell            o          o       ~", " ", "&nbsp;")} // hell            o          o       ~

<% pageContext.setAttribute("enter","\n"); %>
${fn:replace(info.text, enter, '<br/>') // 엔터처리

<% pageContext.setAttribute("enter","\n"); %>
${fn:replace(fn:replace(fn:escapeXml(info.content_txt), enter, '<br/>') , ' ', '&nbsp;')} // 엔터와 공백 처리

 


 

String substring(String string, int begin, int end)

string에서 begin 인덱스에서 시작해서 end 인덱스에 끝나는 부분의 문자열을 리턴.

String substringAfter(String string, String substring)

string에서 substring이 나타나는 이후의 부분에 있는 문자열을 리턴.

String substringBefore(String string, String substring)

string에서 substring이 나타나기 이전의 부분에 있는 문자열을 리턴.

 

${fn:substring(text, 3, 19)} // My name is waldo

${fn:substringAfter(text, "Hi ")} // My name is waldo

${fn:substringBefore(text, "waldo")} // Hi My name is

 


 

String toLowerCase(String string)

string을 모두 소문자로 치환.

String toUpperCase(String string)

string을 모두 대문자로 치환.

 

<c:set var="text" value="Hi My name is waldo"/>

${fn:toLowerCase(text)} // hi my name is waldo

${fn:toUpperCase(text)} // HI MY NAME IS WALDO

 


 

String trim(String string)

string 앞뒤의 공백을 모두 제거.

 

<c:set var="text" value="          blank spcae          "/>
${fn:length(text)}  // 31

<c:set var="text" value="${fn:trim(text)}"/>
${fn:length(text)}  // 11
728x90
반응형

windows 10 NVM 과 nodejs 설치하기

nvm은 Node Version Manager의 약자로, node.js 버전이 다른 개발환경을 필요로 할경우 해당 버전의 설치를 지원하여 사용할 버전을 선택할 수 있도록 도와줌.

OS 환경

  • Windows 10

NVM 설치

PS C:\Users\jeaha> nvm version
1.1.7

nodejs 설치

  • nvm이 설치 되었다면, 필요로 하는 nodejs 의 버전을 확인한다.
    • nodejs & npm 버전 확인
  • 설치할 버전을 확인 했다면 cmd에서 다음 명령으로 설치하면 된다.
nvm install v{버전}
  • 여기까지 하면 nodejs를 사용할 준비가 되었지만, 어떤 버전을 사용할지 설정하지 않은 상태이다.
  • nvm use {버젼} 명령으로 사용 버전을 지정 해 줘야 한다.
  • 설정한 node/npm 버전 확인
PS C:\Users\jeaha> nvm use 14.15.1
Now using node v14.15.1 (64-bit)

PS C:\Users\jeaha> nvm ls

  * 14.15.1 (Currently using 64-bit executable)

PS C:\Users\jeaha> node -v
v14.15.1

PS C:\Users\jeaha> npm -v
6.14.8
728x90
반응형

'Language > JavaScript' 카테고리의 다른 글

[JS] 페이지 리로드  (0) 2021.06.07
[JavaScript] url을 a 태그로 변환하기  (0) 2021.01.06
[JS] 날짜 비교  (0) 2020.11.11
[Modern JS] 동기 처리를 위한 Async Await  (0) 2020.06.14
[Modern JS] Promise  (0) 2020.06.14

SiteMesh와 Tiles

이직 하고 프로젝트를 인계 받다 보니 SiteMesh라는 것을 사용하고 있었다.
도대체 이게 뭐신고 하니 apache tiles 와 같은 화면 구성을 위한 템플릿 프레임워크였다.

현재는 소멸 된 오픈 소스 프로젝트로(이마짚...) 2015년 이후로는 업데이트가 없다는 설명에 tiles와 무슨 차이가 있는건지 찾아보았다.

혹시 라도 SiteMesh 사용법을 찾는 사람이라면 여기서 뒤로가기를 누르시라...

 


 

Google Trends

SiteMesh가 과연 얼마나 자주 사용 되는 것인가가 궁금해서 Google Trends에 비교 검색 해 보았다.

지난 5년간 압도적으로 Tiles 검색이 더 많았다...

지역별 비교 분석을 보면 한국과 중국에서 많이 검색을 했단다...

"공공 SI 에서 많은 메뉴들을 간단한 설정으로 표출 하고 싶어서" 가 아닐까 싶다.

 


 

SiteMesh와 Tiles의 차이점

 

SiteMesh와 Tiles의 가장 큰 차이점은 패턴이다.
Tiles의 경우에는 Composite View 패턴을, SiteMesh의 경우에는 Decorator 패턴을 사용하고 있다.

아래 비교 내용는 해당 링크에서 가져왔다. http://tiles.apache.org/framework/tutorial/pattern.html

Composite View vs. Decorator

Tiles is a composite view framework: it allows to reuse page pieces across the application. But another approach to achieve the same result is using the Decorator pattern. For example, Sitemesh is based on the Decorator pattern.

Instead of creating a template and organizing the pieces together, the Decorator pattern (in this case) takes a simple HTML page, transforms it adding the missing pieces (in our example, adding header, footer and menu) and finally renders it.

Here you can find a comparison table between the two patterns.

Aspect Composite View Decorator
Reusability The different parts of the page (template and pieces) can be reused across the whole application. Each decorator can be reused, but the decoration itself can be applied to one page at a time.
Ease of configuration Each page must be defined explicitly. The decorator can be applied even to the entire application.
Runtime configuration The pages can be configured and organized at runtime Since one page is decorated at a time, this feature is not present.
Performances Low overhead for composition. The page to be decorated has to be parsed.



재사용성

Composite View Pattern의 Tiles의 경우에는 페이지의 모든 부분을 모두 재사용 가능하다.
반면, Decorator Pattern을 사용하는 SiteMesh는 각각의 데코레이터를 재사용 할수는 있지만, 데코레이션 자체는 한 페이지씩 적용할 수 있다고 한다.
데코레이터가 무엇인지 모르겠지만, 모든 부분을 재사용할 수 있는 Composite View Pattern이 Decorator Pattern 보다 나아보인다.

설정

각 페이지를 일일히 다 정의 해야하는 Tiles 보다는 SiteMesh가 더 쉽다고 한다.
근데 Tiles도 일일히까지는 설정 안해도 됬던 것으로 기억하는데,,

실행중 수정 여부

Composite View Pattern은 런타임중 각 페이지의 설정을 변경할 수 있고, Decorator Pattern 은 최초 한번에 적용 되기 때문에 런타임준 수정할 수 있는 기능은 제공하지 않는다.

성능

Composite View Pattern에 비해 매번 페이지를 파싱해야 하는 Decorator Pattern은 성능면에서는 당연히 떨어질 것이라 생각한다.

 


 

결론

이렇게 보니, Tiles가 trend인 이유도, 공공 SI에서 SiteMesh를 사용하는 이유도 이해가 간다.
간단한 프로그램에 복잡하지 않지만 페이지의 양이 많은 공공 지자체 SI라면 SiteMesh를 사용하는 합리적인 이유인것 같긴 하다만, 그래도 Tiles가 더 편한 것 같다는 생각은 변하지 않는다.
SiteMesh가 2015년 이후로 업데이트가 없었고, Tiles는 2016 이후로 retired 했다고 한다. (?)
그리고 비슷한 대안으로 Thymeleaf, Freemarker, mustach.java등이 있다고 한다. 그리고 Thymeleaf가 Tiles 만큼 사용율도 높다...

기술 트렌드... 참 사람 어쩌라는 건지 모르겠다.

728x90
반응형

Java 에서 Map 안의 요소 반복문으로 꺼내기.

package dev.jeaha.practice;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapIterationPractice {

  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();

    map.put("k00", "v00");
    map.put("k01", "v01");
    map.put("k02", "v02");
    map.put("k03", "v03");
    map.put("k04", "v04");
    map.put("k05", "v05");
    map.put("k06", "v06");
    map.put("k07", "v07");
    map.put("k08", "v08");
    map.put("k09", "v09");
    map.put("k10", "v10");

    System.out.println(">>>> SOLUTION 01-1 <<<<");
    /**
     * Generic 미사용.
     * Java 버젼이 낮을 경우 사용할 수 있는 방법.
     */
    Iterator entries = map.entrySet().iterator();
    while( entries.hasNext() ) {
      Map.Entry entry = (Map.Entry) entries.next();
      String key = (String) entry.getKey();
      String val = (String) entry.getValue();
      System.out.println( String.format("key : %s, value : %s", key, val ) );
    }


    System.out.println("\n\n>>>> SOLUTION 01-2 <<<<");
    /**
     * Generic, Entry 사용
     */
    Iterator<Map.Entry<String, String>> entriex = map.entrySet().iterator();
    while( entriex.hasNext() ) {
      Map.Entry<String, String> entry = entriex.next();
      System.out.println( String.format("key : %s, value : %s", entry.getKey(), entry.getValue() ) );
    }

    System.out.println("\n\n>>>> SOLUTION 01-3 <<<<");
    /**
     * Generic 사용, Entry 미사용
     */
    Iterator<String> keys = map.keySet().iterator();
    while( keys.hasNext() ) {
      String key = keys.next();
      System.out.println( String.format("key : %s, value : %s", key, map.get(key)) );
    }

    System.out.println("\n\n>>>> SOLUTION 02 <<<<");
    /**
     * Entry에 for-each loop 사용.
     * 가장 일반적이고 많은 경우에 사용됨.
     * 반복문 안에서 key 값과 value 값이 전부 필요할 때 사용.
     * Java 1.5 이상부터 사용 가능. NullPointerException 발생 가능.
     */
    for( Map.Entry<String, String> entry : map.entrySet() ) {
      System.out.println( String.format("key : %s, value : %s", entry.getKey(), entry.getValue() ) );
    }

    System.out.println("\n\n>>>> SOLUTION 03 <<<<");
    /**
     * entry 대신에 key 값이나 value 값만 필요할 때 사용.
     * entrySet을 사용할 때보다 약 10% 빠르다고 함.
     */
    for( String key : map.keySet() ) {
      System.out.println( String.format("key : %s", key ) );
    }
    for( String value : map.values() ) {
      System.out.println( String.format("value : %s", value ) );
    }

    System.out.println("\n\n>>>> SOLUTION 04 <<<<");
    /**
     * 코드상으로는 깔끔해 보이지만 비효율 적이고 성능면에서 좋지 않은 방법.
     * key 값을 이용해서 value 를 찾는 과정에서 시간 소모가 많음.
     * SOLUTION 02에 비해 20~200% 성능 저하 유발.
     */
    for( String key : map.keySet() ) {
      System.out.println( String.format("key : %s, value : %s", key, map.get(key) ) );
    }

    System.out.println("\n\n>>>> SOLUTION 05 <<<<");
    /**
     * stream을 사용한 forEach.
     */
    map.entrySet()
    .stream()
    .forEach(System.out::println);

    System.out.println("\n\n>>>> SOLUTION 06 <<<<");
    /**
     * forEach 및 Lambda를 사용한 반복.
     * forEach() 내에서 람다 표현식 사용.
     */
    map.forEach( (key, val) -> {
      System.out.println( String.format("key : %s, value : %s", key, val ) );
    });
  }
}
728x90
반응형

'Language > Java' 카테고리의 다른 글

[Java] 문자열이 날짜 형식인지 확인하기  (0) 2021.10.18
[Java] 성능을 고려한 try-catch 문  (0) 2020.12.16
[JAVA] 구 버젼 설치  (0) 2020.11.02
[Java] ArrayList Sort  (0) 2020.05.22

+ Recent posts