안경잡이개발자

728x90
반응형

  이번 시간에는 AWS Lambda와 MongoDB를 활용하여 하나의 게시물(Board) API를 완전히 개발해보는 시간을 가져보도록 하겠습니다. 따라서 가장 먼저, 다음과 같이 /board 경로에 GET, POST, PUT, DELETE 메소드의 API를 Gateway로 열어줍니다. 그리고 /board/{proxy+} 경로의 모든 메소드를 사용할 수 있도록 합니다.

 

  /board/{proxy+}로 설정하면, 모든 Path Parameter를 받을 수 있게 됩니다.

 

 

  이후에 소스코드를 작성합니다. 우리가 작성할 게시물 Rest API의 기본적인 명세는 다음과 같습니다.

 

[ 게시물 ]

 

- 게시물 번호

- 게시물 작성자

- 게시물 비밀번호

- 게시물 내용

- 게시물 작성일자

 

  소스코드는 다음과 같습니다.

"use strict";
const mongoose = require('mongoose');
const MONGODB_URI = process.env.MONGODB_URI;

/* Board 오브젝트를 정의합니다. */
const boardSchema = mongoose.Schema({
    id: {
        type: Number,
        required: true
    },
    name: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true
    },
    content: {
        type: String,
        required: true
    },
    date: {
        type: Date,
        required: true
    }
});

/* 하나의 연결 객체를 반복적으로 사용합니다. */
let connection = null;

const connect = () => {
  if (connection && mongoose.connection.readyState === 1) return Promise.resolve(connection);
  return mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true }).then(
    conn => {
      connection = conn;
      return connection;
    }
  );
};

module.exports.handler = (event, context, callback) => {
  let operation = event.httpMethod;
  let Board = mongoose.model('board', boardSchema);
  let proxy, password;
  switch (operation) {
    case 'GET':
      /* 
        경로: /board
        설명: 전체 게시글 정보를 불러옵니다.
      */
      if(event.pathParameters === null) {
        let query = {};
        if(event.queryStringParameters.name) {
          query.name = {$regex:event.queryStringParameters.name, $options: 'i'};
        }
        if(event.queryStringParameters.content) {
          query.content = {$regex:event.queryStringParameters.content, $option: 'i'};
        }
        // name과 content를 이용하여 검색한 결과를 내림차순으로 반환합니다.
        connect().then(() =>
        Board.find(query)
        .select("-password")
        .sort({id: -1})
        .exec(function(error, boards) {
            if(error) {
              context.done(null, { 'statusCode': 500, 'body': JSON.stringify(error) });
            }
            else {
              context.done(null, { 'statusCode': 200, 'body': JSON.stringify(boards) });
            }
        }));
      }
      /* 
        경로: /board/:id
        설명: 특정 게시글 정보를 불러옵니다.
      */
      else {
        proxy = event.pathParameters.proxy;
        connect().then(() =>
        Board.findOne({id:proxy})
        .select("-password")
        .exec(function(err, board) {
            if(err) {
              context.done(null, { 'statusCode': 500, 'body': JSON.stringify(err) });
            }
            else if(!board) {
              context.done(null, { 'statusCode': 500, 'body': JSON.stringify("Board not found.") });
            }
            else {
              context.done(null, { 'statusCode': 200, 'body': JSON.stringify(board) });
            }
        }));
      }
      break;
    case 'POST':
      /* 
        경로: /board
        파라미터: {"name":"작성자","content":"내용","password":"비밀번호"}
        설명: 특정 게시글을 작성합니다.
      */
      let lastId = 0;
      // 가장 최근에 작성된 게시물 번호를 가져옵니다.
      connect().then(() =>
      Board.findOne({})
        .sort({id: -1})
        .exec(function(err, board) {
          if(err) {
            context.done(null, { 'statusCode': 500, 'body': err });
          } else {
            lastId = board ? board.id : 0;
            const { name, content, password } = JSON.parse(event.body);
            const newBoard = new Board({ name, content, password });
            newBoard.date = new Date();
            newBoard.id = lastId + 1;
            // 새로운 글을 등록합니다.
            newBoard.save(function(err, board) {
              if(err) {
                context.done(null, { 'statusCode': 500, 'body': JSON.stringify(err) });
              } else {
                context.done(null, { 'statusCode': 200, 'body': JSON.stringify(lastId + 1) });
              }
            });
          }
        })
      );
      break;
    case 'PUT':
      /* 
        경로: /board/:id
        헤더: password:"현재 비밀번호"
        파라미터: {"name":"작성자","content":"내용","password":"비밀번호"}
        설명: 특정 게시글을 수정합니다.
      */
      proxy = event.pathParameters.proxy;
      password = event.headers.password;
      // 사용자가 입력한 번호의 게시물을 찾습니다.
      connect().then(() =>
      Board.findOne({id:proxy})
      .exec(function(err, board) {
          if(err) {
              context.done(null, { 'statusCode': 500, 'body': JSON.stringify(err) });
          }
          else if(!board) {
              context.done(null, { 'statusCode': 500, 'body': JSON.stringify("Board not found.") });
          }
          else {
              if(board.password != password) {
                context.done(null, { 'statusCode': 500, 'body': JSON.stringify("Password is incorrect.") });
              } else {
                  const { name, content, password } = JSON.parse(event.body);
                  // 사용자가 입력한 name, content, password에 맞게 정보를 변경합니다.
                  Board.findOneAndUpdate({id:proxy}, { name, content, password })
                  .exec(function(err, board) {
                      if(err) {
                        context.done(null, { 'statusCode': 500, 'body': JSON.stringify(err) });
                      }
                      else {
                        context.done(null, { 'statusCode': 200, 'body': JSON.stringify('success') });
                      }
                  });
              }
          }
      }));
      break;
    case 'DELETE':
      /* 
        경로: /board/:id
        헤더: password:"현재 비밀번호"
        설명: 특정 게시글을 삭제합니다.
      */
      proxy = event.pathParameters.proxy;
      password = event.headers.password;
      connect().then(() =>
      Board.findOne({id:proxy})
      .exec(function(err, board) {
          if(err) {
              context.done(null, { 'statusCode': 500, 'body': JSON.stringify(err) });
          }
          else if(!board) {
              context.done(null, { 'statusCode': 500, 'body': JSON.stringify("Board not found.") });
          }
          else {
              if(board.password != password) {
                context.done(null, { 'statusCode': 500, 'body': JSON.stringify("Password is incorrect.") });
              } else {
                // 사용자가 입력한 번호에 해당하는 게시물을 삭제합니다.
                Board.findOneAndRemove({id:proxy})
                .exec(function(err, board) {
                    if(err) {
                      context.done(null, { 'statusCode': 500, 'body': JSON.stringify(err) });
                    }
                    else {
                        context.done(null, { 'statusCode': 200, 'body': JSON.stringify('success') });
                    }
                });
              }
          }
      }));
      break;
    default:
      callback(new Error(`Unrecognized operation "${operation}"`));
  }
};

 

  테스트 결과는 다음과 같습니다.

 

1. 게시글 리스트 보기


경로: /board 
설명: 전체 게시글 정보를 불러옵니다. 

 

 

 

2. 게시물 정보 확인하기


경로: /board/:id 

설명: 특정 게시글 정보를 불러옵니다. 

 

 

3. 게시물 등록하기


경로: /board 
파라미터: {"name":"작성자","content":"내용","password":"비밀번호"} 
설명: 특정 게시글을 작성합니다. 

 

 

4. 게시물 수정하기

 

경로: /board/:id
헤더: password:"현재 비밀번호" 
파라미터: {"name":"작성자","content":"내용","password":"비밀번호"} 
설명: 특정 게시글을 수정합니다. 

 

 

5. 게시물 삭제하기


경로: /board/:id 
헤더: password:"현재 비밀번호" 
설명: 특정 게시글을 삭제합니다. 

 

728x90
반응형

728x90
반응형

  이번 시간에는 간단히 AWS Lambda와 MongoDB를 연동하는 방법에 대해서 알아보도록 하겠습니다. 우리는 추후에 결과적으로 간단한 형태의 게시판 게시글 API를 만들어볼 것입니다. AWS Lambda와 MongoDB 모두 구축이 매우 간단하고, 편리하기 때문에 이 두 서비스를 한꺼번에 이용하는 경우가 많습니다.

 

  따라서 바로  Atlas 회사의 MongoDB를 구축해보도록 하겠습니다. MongoDB는 다음의 포스팅에서 제가 간단히 소개한 바 있습니다. https://ndb796.tistory.com/302

 

Atlas 무료 MongoDB 사용 방법

공부 목적으로 MongoDB를 이용하시는 분들은 Atlas 회사의 MongoDB 서비스를 가장 많이 사용합니다. 이번 포스팅에서는 Atlas 회사의 무료 MongoDB를 사용하는 방법에 대해서 소개하도록 하겠습니다. ▶ Atlas Mon..

ndb796.tistory.com

  위 과정은 매우 금방 따라하실 수 있을 거고, 최종적으로 만들어진 MongoDB의 접속 문자열(String)을 메모장에 기록해 놓은 뒤에 다음의 과정을 따라오시면 됩니다.

 

  더불어 Atlas에서는 공식 AWS Lambda와 Atals MongoDB를 연동하는 예제를 제공하고 있으므로 이를 참고하시면 좋습니다. https://docs.atlas.mongodb.com/best-practices-connecting-to-aws-lambda/

 

Best Practices Connecting from AWS Lambda — MongoDB Atlas

Best Practices Connecting from AWS Lambda MongoDB recommends the following best practices to optimize connection times between AWS Lambda and Atlas: Define the MongoDB client connection to the MongoDB server outside the AWS Lambda handler function. This ma

docs.atlas.mongodb.com

 

  가장 먼저 AWS Lambda의 환경 변수(Environment Variables)로 MONGODB_URI을 설정합니다. 이 때 <password> 부분에 자신의 MongoDB 비밀번호를 넣어주셔야 합니다.

 


이제 Lambda 소스코드를 작성합니다.

 

"use strict";

const mongoose = require('mongoose');
const MONGODB_URI = process.env.MONGODB_URI;

module.exports.handler = (event, context, callback) => {
  console.log('event: ', event);
  
  /* Database 설정 및 변수 초기화 */
  mongoose.Promise = global.Promise;
  mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true });
  const db = mongoose.connection;
  db.once('open', function () {
      console.log('Database Connected.');
  });
};

 

  이후에 코드를 [Save]하고 [Test] 버튼을 눌러서 아무렇게나 테스트 설정을 하여 테스트를 해보시면, 아래 쪽에 Cannot find module 'mongoose'라는 메시지가 나오게 됩니다. 이는 Mongoose 라이브러리가 AWS Lambda에 기본적으로 포함되어 있지 않기 때문에 발생하는 문제입니다.

 

 

  따라서 우리가 AWS Lambda에 특정한 라이브러리를 추가하여 사용하고 싶다면, 직접 Node.js 라이브러리를 압축하여 AWS Lambda에 올려야 합니다. 따라서 특정한 폴더에서 npm install mongoose로 MongoDB 라이브러리를 설치합니다.

 


  그리고 nodejs라는 이름의 폴더를 만들고, 그 안에 node_modules 폴더를 둡니다. 그리고 library라는 이름의 폴더를 하나 더 만들어서 nodejs 폴더를 그 안에 둡니다. AWS Lambda에 업로드 하게 되는 압축 파일의 루트 폴더는 nodejs라는 이름을 가진다고 약속되어 있어요. 

 

 

  이후에 library 폴더를 압축합니다. 이후에 그 압축 파일을 AWS Lambda의 Layer에 올립니다. 이 때 Runtime이 자신의 AWS Lambda의 Runtime과 일치하는지 확인할 수 있도록 합니다. (Node.js 8.10 버전인 경우 Layer Runtime도 8.10을 선택합니다.)

 

 

  이제 다시 AWS Lambda로 돌아가서, 우리의 Lambda 함수를 클릭한 뒤에 [Add a layer]를 눌러 레이어를 추가합니다.

 

 

  결과적으로 다음과 같이 업로드한 라이브러리를 선택해서 [Add] 버튼을 누르시면 됩니다.

 

 

  이제 이 상태에서 다시 AWS Lambda를 [Save]하고 [Test]하면 이제 Mongoose를 사용할 수 있게 되는 것을 알 수 있습니다.

 

 

  다만 이 때 위와 같이 정상적으로 DB 접근이 되지 않아서, 'Database Connected.' 라는 로그(Log)가 출력되지 않으면, Atlas에서 DB White List 설정을 확인하실 필요가 있습니다. 혹은 MongoDB 비밀번호가 제대로 입력이 되어 있는지 확인하실 필요가 있습니다.

 

  기본적으로 AWS Lambda의 IP를 Atlas의 White List에 등록해야 사용할 수 있습니다. 하지만 AWS Lambda는 유동 IP 정책을 따르고 있어서, 일일히 모든 IP를 White List에 등록할 수 없습니다. 그래서 흔히 VPC를 이용하여 고정 IP를 할당할 수 있습니다.  다만 이렇게 하면 어렵고, 비용도 많이 발생할 수 있어요. 따라서 그냥 실습 과정에서는 MongoDB에서 모든 IP를 허용할 수 있도록 할 수 있습니다. 따라서 Atlas의 MongoDB에서 [CONNECT]를 눌러 연결 정보를 확인합니다.

 

 

  이후에 다음과 같이 [IP Whitelist tab]을 누릅니다.

 

 

  이후에 다음과 같이 모든 IP 주소에서 접속할 수 있는 Entry를 추가하시면 됩니다.

 

 

  이제 다음과 같이 정상적으로 AWS Lambda를 실행하면, 3초 가량의 시간이 흐른 뒤에 'Database Connected.'라는 메시지가 출력됩니다. 다만 DB 연결과 관련하여 많은 시간이 소요되며, Error Message를 뱉을 수 있습니다.

 

 

  그래서 실제로 코딩을 할 때에는 다음과 같은 방식으로 코드 맨 아래에서 context.done() 함수를 통해 결과를 돌려주며 함수를 마치도록 해야 합니다.

 

"use strict";
const mongoose = require('mongoose');
const MONGODB_URI = process.env.MONGODB_URI; // or Atlas connection string
module.exports.handler = (event, context, callback) => {
  console.log('event: ', event);
  /* Database 설정 및 변수 초기화 */
  mongoose.Promise = global.Promise;
  mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true });
  const db = mongoose.connection;
  db.once('open', function () {
      console.log('Database Connected.');
  });
  context.done(null, { 'statusCode': 200 });
};

 

  이제 결과적으로 200번 응답 코드가 출력되는 것을 알 수 있습니다. 다만 'Database Connected.'라는 로그 메시지는 출력되지 않고, 바로 종료되는 것을 알 수 있습니다. 이제 이러한 구조에서 실제로 DB로부터 데이터를 조회하는 등의 작업을 수행하면, 그 때 정상적으로 동작하게 됩니다. 이상으로 이번 시간에는 AWS Lambda와 MongoDB의 연동 방법에 대한 개괄적인 내용을 다루어 보았습니다.

 

 

728x90
반응형

728x90
반응형

  프로세스 익스플로러(Process Explorer)를 이용하면 어떠한 프로그램이 특정한 폴더나 디바이스에 접근하고 있는지 확인할 수 있습니다. 예를 들어 현재 웹 캠(Web Cam)의 불빛이 들어와서 사용 중이라는 신호가 잡히고 있다고 가정합시다. 이 때 실제로 웹 캠 기능을 이용하고 있지 않다면, 누군가 카메라를 이용해 내 모습을 촬영 중이지 않을까 하는 걱정을 하실 수 있습니다. 이 때, 웹 캠 디바이스에 어떤 프로세스가 접근하고 있는지 확인하는 방법이 있습니다.

 

  프로세스 익스플로러를 이용하면 어떠한 프로세스가 돌아가고 있는지에 대한 자세한 정보를 확인할 수 있습니다.

 

  프로세스 익스플로러 다운로드: https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer

 

 

  프로세스 익스플로러를 다운로드 하면, 다음과 같이 실행 파일을 확인할 수 있습니다.

 

 

※ 프로세스의 속성 확인 ※

 

  프로세스의 속성을 확인할 때는 특정 프로세스를 우클릭하여 [Properties...] 버튼을 누르면 됩니다.

 

 

  특히 [Performance] 탭에서는 해당 프로세스의 구체적인 성능 정보를 확인할 수 있습니다. 해당 프로세스가 몇 번째 우선순위를 가지고 동작하고 있는지, 그리고 가상 메모리 공간은 얼마나 차지하고 있는지 등을 확인할 수 있습니다.

 

 

※ 특정 프로세스 강제 종료하기 ※

 

  특정 프로세스를 강제 종료하려면, 우클릭 이후에 [Kill Process] 버튼을 누르면 됩니다.

 

 

※ 특정한 장치를 사용 중인 프로세스 찾기 ※

 

  특정한 장치를 사용 중인 프로세스를 찾을 때는 먼저 [장치 관리자]를 실행합니다. 저는 다음과 같이 웹 캠(Web Cam)의 속성을 확인해 보았습니다. 이 때 [자세히] - [실제 장치 개체 이름] 탭으로 들어가면, 해당 장치의 구체적인 이름을 얻을 수 있습니다.

 

 

  이제 [Find] 탭에서 [Find Handle or DLL...] 버튼을 누릅니다.

 

 

  이후에 관련 장치를 사용 중인 프로세스를 검색하기 위해, 저는 다음과 같이 검색을 해보았습니다. 그랬더니 웹 캠을 현재 사용 중인 프로세스는 찾지 못했습니다.

 

 

728x90
반응형

728x90
반응형

  공부 목적으로 MongoDB를 이용하시는 분들은 Atlas 회사의 MongoDB 서비스를 가장 많이 사용합니다. 이번 포스팅에서는 Atlas 회사의 무료 MongoDB를 사용하는 방법에 대해서 소개하도록 하겠습니다.

 

  ▶ Atlas MongoDB 사이트: https://www.mongodb.com/cloud/atlas

 

  사이트에 접속하면 다음과 같이 회원가입을 하여 시작하라는 메시지가 등장합니다.

 

 

  무료로 회원가입을 한 이후에 바로 MongoDB 서비스를 이용할 수 있습니다.

 

 

  가입을 하자마자 바로 하나의 데이터베이스를 생성하라고 나옵니다. 그냥 기본 설정 그대로 만들어 주시면 됩니다. 아마 기본적인 클라우드 제공 서비스로는 AWS가 선택되어 있을 겁니다.

 

 

  나머지 설정 또한 기본 설정으로 진행하면 무료로 서비스에 가입할 수 있습니다.

 

 

  클러스터를 생성한 이후에 약간의 시간이 지나면 다음과 같이 초기화가 완료됩니다.

 

 

  이후에 다음과 같이 [CONNECT] 버튼을 눌러서 DB 접속 User 계정을 만들 수 있습니다.

 

 

  다음과 같이 접속을 위한 계정명과 비밀번호를 설정합니다.

 

 

  이후에 실제로 MongoDB에 접속하기 위한 방법을 명시합니다.

 

 

  다음과 같이 Application에서 접속할 수 있도록 [Connect Your Application] 버튼을 누릅니다.

 

 

  결과적으로 다음과 같이 개발 환경에 따른 접속 문자열을 얻을 수 있습니다.

 

 

  또한 지금 이 상태로는 DB에 접속할 수 없습니다. 다시 뒤로 가서 마지막으로 방화벽 설정을 해주세요. 기본적으로 MongoDB에 접속할 수 있는 IP를 직접 입력하는 식으로 연결할 수 있습니다.

 

 

  이제 아까 복사한 접속 문자열(String)을 이용하여 접속할 수 있습니다.

728x90
반응형

728x90
반응형

  크롬(Chrome) 브라우저로 지메일(Gmail)을 이용하시는 분들은 Streak이라는 확장 프로그램을 이용해 내가 보낸 메일을 상대방이 읽었는지 추적할 수 있습니다.

 

Streak 공식 사이트: https://www.streak.com/

 

  저는 이미 Streak을 설치한 상태입니다. 설치가 아직 안 된 분들은 설치 버튼을 눌러서 설치를 진행하시면 됩니다.

 

 

  설치가 된 이후에 크롬 브라우저로 Gmail에 접속하시면 다음과 같이 알림 창이 나오실 거예요. 이처럼 처음 접속할 때는 Streak을 이용하도록 설정하시면 됩니다. 로그인을 하시면 바로 Streak을 이용할 수 있게 됩니다.

 

 

  이제 Streak과 Gmail이 연동되었습니다. 이제 [보낸 편지함]에 [모든 추적된 메일]이라는 항목이 추가되었습니다.

 

 

  이제 Gmail을 이용해 보내는 메일은 자동으로 추적됩니다.

 

 

  결과적으로 메일을 보낸 이후에 [모든 추적된 메일] 탭으로 이동하시면, 다음과 같이 보낸 메일에 대한 추적 여부를 확인할 수 있습니다. 대표적인 정보로는 상대방이 몇 번 읽었는지 알 수 있습니다.

 

 

  실제로, 해당 메일을 상대방이 읽었을 때에는 다음과 같이 언제 상대방이 읽었는지 등에 대한 정보가 출력되는 것을 확인할 수 있습니다.

 

728x90
반응형

728x90
반응형

  갑자기 여러분이 서울에 있다고 해봅시다. 오늘 오후 6시까지 부산에 있는 어떤 기관으로 증빙 서류를 반드시 제출해야 하는데, 지금이 오전 10시다! 그럴 땐 어떻게 해야 할까요?

 

  저는 지금까지 등기 우편만 보내보았는데요. 지금 당장 보내야 할 때는 퀵 서비스라는 것을 이용할 수 있습니다. 저는 이런 게 있다고 들어보기만 했습니다. 실제로 이용해 본 적은 이번이 처음이에요. 그래서 정보를 공유하고자 글을 남깁니다. 어떤 업체를 이용하라고 추천하지는 않을게요. 그냥 구글에 퀵 서비스 업체를 검색하면 많이 나옵니다.

 

 

  예를 들어 제가 강남역 근처에 있고, 부산에 있는 곳으로 우편을 보내야 한다면. 강남역 근처에 있는 퀵 서비스 업체에 연락을 하시면 됩니다. 혹은 몇몇 퀵 서비스 업체는 이미 전국 단위로 퍼져 있고, 콜 센터가 따로 있기 때문에 그냥 전화하면 알아서 가까운 기사님과 연결해줍니다. 따라서 그냥 바로 전화한 뒤에 요건만 말하시면 됩니다.

 

  그리고 일반적으로 서울에서 완전 지방권으로 물건을 보내는 경우에도, 대략 5만원 안으로 해결된다는 특징이 있습니다.

728x90
반응형

728x90
반응형

  네이버 메일은 기본적으로 수신 여부를 알려줍니다. 물론 G-Mail의 Streak처럼 매우 정밀하게 언제 몇 번 읽었는지 등은 알려주지 않지만, 수신 여부만 알면 될 때 유용하게 사용할 수 있습니다.

 

  바로 메일을 작성한 뒤에 [보내기] 버튼을 눌러서 메일을 보내보겠습니다.

 

 

  보낸 이후에는 [보낸 메일함] 옆에 있는 [수신확인] 버튼을 눌러 자신이 보낸 메일에 대한 [수신확인]을 할 수 있습니다.

 

 

  그러면 바로 오른쪽에 [읽지 않음] 혹은 언제 일었는지 나오게 됩니다.

 

 

(+ 참고 사항 )

 

  참고로 그냥 [보낸 메일함]에 있는 [읽음] 표시는 자기 자신이 읽었는지에 대한 여부입니다. 우리가 보낸 메일의 상대방이 읽었는지 확인하기 위해서는 [수신확인]에서 확인하셔야 해요!

 

 

728x90
반응형

728x90
반응형

  운영체제: 컴퓨터 리소스를 효율적으로 관리할 수 있도록 도와주는 시스템 소프트웨어입니다. 좋은 운영체제란 신뢰성이 높고, 사용이 편하며, 빠르게 처리될 수 있어야 합니다. 운영체제의 대표적인 종류로는 윈도우, 리눅스(Linux), Mac OS 등이 있습니다. 운영체제는 크게 4가지 목차로 구성됩니다.

 

[ 목차 ]

 

  1) 프로세스 관리: 실행 중인 프로그램들을 효율적으로 관리

 

- 스케줄링

- 문맥 교환(Context Switch)

- 스레드(Thread)

- 프로세스 동기화

- 상호배제와 임계영역

- 세마포어

 

  2) 메모리 관리: 주기억장치의 쓰임을 효율적으로 관리

 

  3) I/O 관리: 입출력 장치를 효율적으로 관리

 

  4) File 관리: 컴퓨터의 파일을 효율적으로 관리

 

  일반적으로 시험이나 면접에서는 프로세스 관리에 대해서 물어보는 경우가 제일 많습니다.

728x90
반응형