반응형

이번에는 몽고DB에서 데이터 조회를 해볼 것이다.

find는 RDB(MySQL과 같은...)에서의 SELECT 같은 역할을 한다.

find에도 옵션이 상당히 많기 때문에 여기서는 최소한의 기능을 알아볼 예정이다.

일단 find를 사용하기 전에 임시로 아래와 같이 데이타를 등록해놓았다.

 

db.temps.insert({name: '홍길동', age: 20, gender: '남'});
db.temps.insert({name: '최길동', age: 21, gender: '남'});
db.temps.insert({name: '김길동', age: 22, gender: '여'});
db.temps.insert({name: '윤길동', age: 23, gender: '여'});
db.temps.insert({name: '박길동', age: 24, gender: '남'});
db.temps.insert({name: '고길동', age: 25, gender: '남'});
db.temps.insert({name: '모길동', age: 26, gender: '여'});
db.temps.insert({name: '공길동', age: 27, gender: '남'});
db.temps.insert({name: '구길동', age: 28, gender: '남'});
db.temps.insert({name: '정길동', age: 29, gender: '남'});
db.temps.insert({name: '서길동', age: 30, gender: '남'});

 

위와 같이 데이타 삽입을 하고 아주 간단하게 다음과 같이 조회해볼 수 있다.

 

temps 컬렉션의 모든 항목이 표시된다.

MySQL로 예를 들면 'SELECT * FROM temps' 와 같은 명령과 동일하다고 보면 된다.

그리고 위의 경우 데이타가 깔끔하게 보여지지만 필드가 많아질 수록 제대로 정렬이 안되어서 보기 불편할 수가 있다. 그럴 때는 아래와 같이 find() 뒤에 .pretty()를 붙여주면 다음과 같이 데이터를 더 정리된 형태로 볼 수 있다.

 

이와 같이 잘 정렬되어 보여진다.

이제 다음으로는 기본적인 조건 옵션을 붙여보도록 할 것이다.(MySQL의 WHERE절과 같은)

 

도큐먼트 조회시 조건 걸기

이름이 '김길동'인 사람을 조회해보도록 하겠다.

db.temps.find({name: '김길동'});

위와 같이 단순하다. find() 명령안에 { } 중괄호로 원하는 조건을 감싸주기만 하면 된다.

 

만약 조건을 더 붙이고 싶다면 콤마(,)로 구분하여 뒤에 연결시켜주면 된다.

db.temps.find({name: '김길동', age: 22});

예를 들어, 위와 같은 명령이라면 name이 김길동이고 age가 22인 도큐먼트를 가져오게 된다.

 

도큐먼트 조회시 숫자를 비교하는 조건 걸기

조회할 경우 특정 데이타와 완전히 동일한지만 비교할 수도 있지만, 위의 데이타로 예를 들면 20~25세의 도큐먼트만

가져오는 등의 숫자 비교 조건을 걸 수도 있다.

 

MySQL의 경우 'SELECT * FROM temps WHERE age >= 20 AND age <= 25' 이런 형태로 단순하게 부호를 이용해서

비교가 가능하지만 MongoDB에서는 용법이 조금 다르다.

MongoDB에서는 다음과 같이 사용할 수 있다.

 

db.temps.find({age: {$gte: 20, $lte: 25}});

이와 같이 조건이 적용된 것을 확인할 수 있다.

위 명령을 분석해보면 $gte, $lte 라는 것들을 연산자(operator)라고 한다.

기본적으로 필드가 앞에 있고 필드 뒤에 연산자를 중괄호{}로 감싸서 사용하게 된다.

 

$gte는 greater than or equals이란 의미로 '같거나 크면'이라는 조건의 의미를 갖는다.

$lte는 less than or equals이란 의미로 '같거나 작으면'이라는 조건의 의미를 갖는다.

이외에 다양한 연산자가 존재한다.

 

$gt : 주어진 값보다 큰 경우

$lt : 주어진 값보다 작은 경우

$eq : 주어진 값과 일치하는 경우

$ne : 주어진 값과 일치하지 않는 경우

$in : 주어진 배열 안에 속하는 값

$nin : 주어진 배열 안에 속하지 않는 값

 

위는 비교 연산자이고, 그 외에 논리 연산자, 문자열 연산자 등 다양한 연산자가 따로 존재한다. 

그것은 각 연산자 사용시에 다시 알아보도록 하겠다.

 

도큐먼트 조회시 정렬하기

가져온 데이타들을 소팅할 수 있는 방법을 알아볼 것이다.

위에서 insert한 데이타들을 기준으로 age 필드의 데이타를 내림차순으로 정렬해보려 한다.

db.temps.find().sort({age: -1});

아주 간단하게 정렬이 되었다.

find()뒤에 sort()명령을 붙여줄 수 있고 중괄호 안에 원하는 정렬 기준을 지정해주면 된다.

age: -1는 age 필드를 내림차순으로 정렬한다는 의미이다.

-1은 내림차순이지만 오름차순으로 정렬하고 싶다면 {age: 1}과 같은 형태로 사용하면 된다.

이 때 .sort() 명령 뒤에 .pretty()를 붙여서 더 정리된 형태로 표시할 수도 있다.

 

도큐먼트 조회시 특정 개수만 표시하기, 특정 위치의 데이타 가져오기

데이타 수량이 너무 많거나 페이지네이션 구현 등을 위해 특정 개수만 표시하고 싶을 때가 있다.

이 때는 .limit()이라는 명령을 사용할 수 있다.

 

db.temps.find().limit(1);

이와 같이 가져올 데이타의 상위 1개의 데이타만 가져오게 된다.

페이지네이션 구현을 위해 많이 사용하게 된다. 페이지네이션 구현시에는 특정 개수만 가져오는 것도 필요하지만,

특정 위치의 도큐먼트를 가져오는 것도 필요하다.

이 때는 .skip()이라는 명령을 사용할 수 있다.

 

db.temps.find().skip(2).limit(2);

조회할 데이타의 2개 뒤의 데이타들 중 2개만 가져오는 명령이다.

이를 통해서 페이지네이션을 구현할 수 있다.

 

여기까지 find의 기본적인 내용들을 다루어보았고, 다음에는 여기서 설명하지 않았던 다른 연산자들에 대해서도

알아보려 한다.

반응형
반응형
defaultConfig {
    // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
    applicationId "com.test.abcd"
    minSdkVersion flutter.minSdkVersion
    targetSdkVersion flutter.targetSdkVersion
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName
}

 

위 코드에서 보다시피 각 속성들이 참조로만 지정되어 있다.

Flutter 2.8 전에는 직접 입력되어져 있었으나 2.8 이후부터는 위처럼 참조 형태로 바뀌게 되었다.

 

기본 값은 무엇으로 되어있는지 확인하기 위해 검색을 해보았다.

위와 같이 검색해보았으나, 참조되어있는 부분 빼고는 원 출처가 어디인지 나오지 않았다.

그 이유는 프로젝트 내에 해당 정보가 있지 않고 플러터 SDK 경로안의 gradle 파일을 참조하기 때문이다.

 

해당 파일의 위치는 아래와 같다.

플러터 경로가 C:\flutter라고 가정할 경우 C:\flutter\packages\flutter_tools\gradle\flutter.gradle 파일안에 해당 정보가 있다.

 

파일을 열어보면 위와 같이 선언되어 있는 것을 확인할 수 있다.

굳이 왜 저렇게 했을까 싶다. 플러터 버전을 업그레이드하면서 자기 마음대로 해당 Sdk버전을 변경해버릴 수 있기 때문에, 나의 경우는 위 선언 내용을 그대로 사용하지 않는다.

 

applicationId "com.test.abcd"
minSdkVersion 16
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName

위와 같이 숫자를 직접 대입해서 쓰는 것도 간편하고 나쁘지 않은 방법이라고 본다. (기존의 방법)

하지만 나는 현재 아래처럼 사용하고 있다.

def flutterCompileSdkVersion = localProperties.getProperty('flutter.flutterCompileSdkVersion')
if (flutterCompileSdkVersion == null) {
    flutterCompileSdkVersion = '31'
}

def flutterMinSdkVersion = localProperties.getProperty('flutter.flutterMinSdkVersion')
if (flutterMinSdkVersion == null) {
    flutterMinSdkVersion = '16'
}

def flutterTargetSdkVersion = localProperties.getProperty('flutter.flutterTargetSdkVersion')
if (flutterTargetSdkVersion == null) {
    flutterTargetSdkVersion = '31'
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
    compileSdkVersion flutterCompileSdkVersion.toInteger()

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.test.abcd"
        minSdkVersion flutterMinSdkVersion.toInteger()
        targetSdkVersion flutterTargetSdkVersion.toInteger()
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}

flutterVersionCode, flutterVersionName은 local.properties를 참조하는 형태로 되어있었는데,

compileSdkVersion, minSdkVersion, targetSdkVersion 또한 그렇게 참조하는 형태로 바꿔버리는 것이다.

sdk.dir=C:\\Users\\Master\\AppData\\Local\\Android\\sdk
flutter.sdk=C:\\flutter
flutter.buildMode=debug
flutter.versionName=1.0.0
flutter.versionCode=1
flutter.flutterCompileSdkVersion=31
flutter.flutterMinSdkVersion=16
flutter.flutterTargetSdkVersion=31

그리고 local.properties 파일을 위와 같이 수정해주면 좀 더 깔끔한 형태로 sdk 버전을 관리할 수 있게 된다.

 

반응형
반응형

 

이더리움 주소와 개인 키(Private Key)의 조합을 계정(account)이라고 한다.

이더리움 계정은 이더리움 잔고를 보유하고 트랜잭션을 전송할 수 있다.

 

이더리움에는 아래와 같이 2가지 유형의 계정이 존재한다.

 

​외부 소유 계정(Externally Owned Accounts)

공개 이더리움 주소와 개인키 조합을 의미하는데 쉽게 말해 지갑 주소라고 보면 된다.

이것을 이용하여 다른 계정과 이더리움을 송수신하고 스마트 컨트랙트에 트랜잭션을 보낼 수 있다.

메타마스크, 카이카스에서 만든 계정이 EOA라고 보면 된다.

 

컨트랙트 계정(Contract Accounts)

컨트랙트 계정은 외부 소유 계정과 다르게 개인키가 존재하지 않고, 스마트 컨트랙트를 블록체인에 배포할 때 생성된다.

컨트랙트 계정 대신 컨트랙트로만 표시하기도 한다.

이 컨트랙트 계정은 다른 계정과 이더를 송수신하는 기능을 하며, 이것은 EOA와 동일하다.

또 이 컨트랙트 계정에는 코드를 담고 있는데 흔히 스마트 컨트랙트라고 한다.

EOA나 다른 컨트랙트의 호출을 받아서 트랜잭션을 발생시키며, 스스로 동작하지는 않는다.

스마트 컨트랙트에 접근하기 위한 주소가 곧 컨트랙트 계정을 의미한다.

 

반응형
반응형

AWS SSH를 접속하기 위해 보통 Putty라는 SSH 접속 프로그램을 사용하게 되는데,

AWS에서 SSH 접속을 위해 제공해주는 키 페어 파일은 확장명이 pem파일인데 Putty에서는 ppk 파일을 요구한다.

즉, pem파일을 ppk파일로 변환하는 과정을 거쳐야 한다.

 

변환하기 위해서는 puttygen.exe 파일을 다운로드 받고 실행한다.

(https://www.puttygen.com/ 에서 다운로드 가능하다.)

위와 같이 프로그램이 실행되었으며, 위의 Load 버튼을 클릭한다.

먼저 pem 파일을 불러와야 하므로 확장자를 All Files(*.*) 로 변경해준 뒤 키 페어 파일(.pem)을 불러온다.

성공적으로 불러왔다는 메세지가 뜬다.

'Save private key' 버튼을 클릭한다.

위의 경고창에서는 '예' 버튼을 클릭한다. 

그리고 원하는 파일명의 ppk 파일로 저장하기만 하면 된다.

최종적으로 ppk 파일이 생성되며 해당 파일을 Putty에 지정하여 사용하면 된다.

 

참고로 Putty에서 ppk 파일 설정하는 영역은 아래와 같다.

Connection->SSH->Auth의 Private key file for authentication 부분을 생성한 키페어 파일로 설정해주고

접속하면 정상적으로 접속될 것이다.

반응형
반응형

 

플러터로 앱 개발하던 도중 잘만 실행 되다가 어느 순간 갑자기 아래와 같은 오류를 발견하였다.

 

위와 같이 devtools-2.9.2\build 폴더를 찾을 수 없다는 오류였으며,

저렇게 오류가 발생하여도 실행하는데는 문제가 없었지만 무언가 찝찝했다.

 

실제로 저 경로에 들어가보아도 devtools-2.9.2 폴더 안에 build 폴더는 존재하지 않았다.

무언가의 영향을 받아서 build를 생성하지 못한 것 같다.

 

먼저 위 경로 중 pub.dartlang.org 폴더까지 들어가보면 아래와 같이 많은 버전의 devtools가 깔려있다.

(devtools-2.9.2 폴더는 어짜피 안되니까 삭제해버렸다.)

 

해결방법은 단순하게 사용할 버전을 바꾸어주면 된다.

 

dart pub global activate devtools -v 2.8.0

 

위 명령어를 실행하게 되면 기존 활성화되어 있던 devtools-2.9.2 버전에서 devtools-2.8.0 버전으로 활성화 버전이 변경된다.

2.8.0 버전 안에는 정상적으로 build폴더도 존재하고 문제가 없으므로 위의 문제는 간단히 해결된다.

이렇게 하지 않고 devtools-2.9.2 버전을 재설치하는 방법도 있겠으나,

일단 급하게 해결이 우선이었고 버전을 바꾼다하여도 문제될 것은 없었기 때문에 위와 같은 방법으로 해결하였다.

반응형
반응형

이번에는 몽고DB에서 데이타를 삭제하는 방법을 알아볼 것이다.

remove는 단일 혹은 다수 삭제가 모두 가능하고 deleteOne은 단일 삭제만 deleteMany는 다수 삭제만

가능하다. MongoDB 3.2버전부터 remove 대신 deleteOne, deleteMany로 대체되었다.

 

1. 삭제(remove)

MySQL에서 'DELETE FROM' 과 매칭되는 명령이다.

insert 혹은 update명령과 비슷한 형태로 사용하게 되는데 단순히 삭제할 조건만 넣어주면 된다.

먼저 위와 같이 데이터를 넣어놓고, 이름이 "최길동"인 사용자를 삭제해보도록 하겠다.

db.users.remove({name: "최길동"});

실행 결과

정상적으로 삭제되었으며, 조건에 따라 단일 삭제가 될 수도 있고 다수 삭제가 될 수도 있다.

예를 들어, 나이가 27살 이상인 사용자를 삭제하고 싶을 경우 다음 명령을 사용한다.

db.users.remove({age: {$gte: 27}});

($gte 연산자는 'greater than or equal'의 약자로 '같거나 크면'의 의미를 갖는다.

 여러 연산자에 대해서는 다음 포스팅에서 다뤄볼 예정이다.)

이와 같이 3개가 삭제되었다는 메세지가 나오며, 조회해보니 정상적으로 삭제된 것을 확인할 수 있다.

remove()의 사용법을 알아보았다. 하지만 몽고3.2 이후에는 deleteOne, deleteMany로 대체되었으니,

remove의 사용은 자제하는 것이 좋다.

 

2. 단일 삭제(deleteOne)

지난번 포스팅에서 설명했던 insertOne, insertMany, updateOne, updateMany와 같은 형태로 용법이 비슷하고,

바로 위에 설명한 remove() 용법이 단일, 다수 삭제 기능으로 분리된 것 뿐이기에 간단하게 설명하고 넘어갈 것이다.

 

db.users.deleteOne({name: "최길동"});

'최길동'이라는 사용자 도큐먼트를 삭제하는 명령이다.

(최길동이라는 사용자가 두명이면 가장 처음의 '최길동' 사용자 도큐먼트만 삭제된다.)

 

db.users.deleteOne({});

처음 도큐먼트 한개를 삭제하는 명령이다.

 

db.users.deleteOne({age: {$gte: 27}});

age 필드가 27 이상의 도큐먼트 중 처음 도큐먼트 한개를 삭제하는 명령이다.

 

3. 다수 삭제(deleteMany)

조건에 해당하는 데이타를 모두 삭제할 때 사용한다.

 

db.users.deleteMany({name: "최길동"});

'최길동'이라는 사용자 도큐먼트를 모두 삭제한다.

 

db.users.deleteMany({});

users 컬렉션의 모든 도큐먼트를 삭제하는 명령이다.

 

db.users.deleteMany({age: {$gte: 27}});

age 필드가 27 이상의 도큐먼트를 모두 삭제한다.

 

 

반응형
반응형

제목에 나열되어 있는 워터풀, 애자일, 린은 프로젝트 방법론이다.

프로젝트 방법론이란 어떠한 프로젝트를 어떤 순서로 어떤 방식으로 개발할지를 정의한 것이라 보면된다.

각각 어떤 차이가 있는지 알아보도록 하겠다.

 

폭포수(Waterfall)

폭포수(Waterfall) 방법론은 아주 오래전부터 쓰여오던 방식이다.

기획->디자인->개발->테스트(검증)->런칭 이렇게 순서대로 다섯가지의 과정을 거치게 된다.

반드시 위의 순서대로 프로젝트가 진행되어야 한다.

어떤 서비스를 개발할 때 해당 서비스에 대한 기획이 모두 완료되면, 디자인팀에서 해당 기획에 대한 디자인을 진행하고, 디자인이 모두 완료되면 개발팀에서 해당 기획과 디자인을 가지고 개발을 진행하게 된다.

최종적으로 테스트하여 문제가 없다면 서비스를 런칭한다.

이 작업의 장점은 어떤 파트에서든 순조롭게 진행된다면 가장 이상적인 방법론이 된다.

또 현재 단계의 진행이 끝나야 다음 단계를 진행할 수 있는 특성 때문에 진행 상황을 파악하기가 더 수월하다는 것이다.

반대로 개발까지 진행을 했는데 기획이 변경된다던지, 디자인이 변경된다던지 한다면,

변경할 부분이 많아지기 때문에 다른 방법론에 비해 유연하게 대처하기 어렵다는 단점이 있다.

대기업에서는 아직도 많이 쓰이는 프로젝트 방법론이지만, 현실적으로 모든 파트가 순조롭게 진행되는 경우가 드물기 

때문에 이런 순차적인 개발 과정은 비효율적으로 보여진다.

 

애자일(Agile)

애자일 방법론은 워터풀의 비효율적인 부분을 개선하기 위해 등장하였다.

워터풀처럼 순차적인 과정을 거치지만, 그 과정을 짧게 거치게 된다.

'기획->디자인->개발->테스트'의 과정을 빠르게 거치며 프로토타입부터 살붙이기 형태로 개발해나가는 방식이다.

아무래도 폭포수 방법론에 비해 개발 주기가 짧기 때문에 기획이나 디자인이 변경되어도 그 부담이 훨씬 적어지게 된다.

잘못될 수 있는 부분을 미리 잡아가는 부분이 폭포수 방법론에 비해 엄청난 장점이 될 수 있다.

A,B,C 기능이 포함된 앱을 개발한다고 가정할 때, 애자일 방법론을 개발하게 되면,

A 기능에 대한 기획->디자인->개발->테스트가 이루어지고,

B 기능에 대한 기획->디자인->개발->테스트가 이루어지는 형태로 개발 진행이 된다.

즉, 어떤 문제가 발견됐을 때 비교적 덩치가 작은 상태에서 수정하기 때문에 문제 해결 시간이 줄어들 수 밖에 없다.

또한, 결과물을 일부 기능들이 완료될 때마다 프로토타입 형태로 보고 피드백을 할 수 있으므로 보다 더 효율적인 프로세스 진행이 된다고 볼 수 있다.

점점 변화가 빨라지는 세상에 살고 있기 때문에 애자일 방법론이 더 빛을 보는게 아닌가 싶다.

 

린(Lean)

린 방법론을 설명하기 위해서는 '린 제조'를 먼저 알아야 한다. 린 제조는 도요타가 사용한 제조 방식인데,

불필요한 설비나 인력을 줄여서 낭비를 줄이는 방식이다. 즉, 린 방법론은 어떤 낭비될 수 있는 부분을 제거하여

고객에게 더 빠르게 프로덕트를 제공할 수 있는 방법론이다.

프로덕트 기획을 하고 개발을 진행하는데 만약 고객이 원치 않는 불필요한 기획이 있다면 어떨까?

이를 개발하는 시간은 모두 낭비되는 시간이라 봐야 한다. 또 개발하고나서도 검증 과정에 시간을 또 쏟아야 하므로

불필요한 프로세스 시간이 더 늘어나게 된다. 린 방법론은 바로 이 부분을 캐치하여 불필요한 작업을 제거하는 것이다.

스타트업에서 린 방법론을 차용한 것을 린스타트업이라고 부른다.(실리콘밸리의 기업가 에릭리스가 개발하였다.)

초기 스타트업에서 폭포수 방법론을 도입하게 되면 프로덕트 도출 기간이 길어지게 되고, 출시 이후에

문제가 발생할 경우 시장 리스크가 너무 커지고 대응 또한 어렵게 된다.

린 스타트업의 기본은 개발 -> 측정 -> 배움 세가지 과정을 거치게 되는데, 실제로 빠르게 프로토타입을 개발하여,

고객과 접촉하여 문제를 발견하면 빠르게 변경하여 적합한 비즈니스를 빨리 찾아내는데 목적이 있다.

여기까지 보면 린과 애자일은 빠른 변화에 대응할 수 있다는 부분에서 공통점을 지닌다.

실제 경험에서 차이점이 있다면 린 모델의 경우 런칭 후 사용자 피드백을 통해 빠른 변화를 도모한다는 것이고,

(프로토타입 개발->런칭->피드백 과정의 반복)

애자일 모델의 경우 사용자에게 런칭하기 이전까지의 개발 사이클을 빠르게 돌리는 것이라고 볼 수 있다.

(프로토타입 개발 과정이 빠르게 반복되고, 살붙이기가 모두 완료되면 런칭 후 피드백)

 


위 세가지 모델에 대해 정리해보았는데 폭포수 모델과 다른 모델과의 차이는 뚜렷한 편이지만,

애자일과 린의 경계는 그리 뚜렷하지 않은 것 같다.

어쨌든 린과 애자일이 변화에 빠르게 대응할 수 있고 리스크를 줄이기 위한 효율적인 모델이라는 것에 대해 동의하며,

앞으로 진행하는 프로젝트에 대해서도 이 두가지 모델을 애용할 것 같다.

반응형

'스타트업' 카테고리의 다른 글

스타트업 팀빌딩할 때 CTO가 꼭 필요한 이유  (0) 2021.12.10
반응형

이번에는 몽고DB에서 데이타를 수정하는 방법을 알아본다.

update 또한 insert와 마찬가지로 함수 형태가 크게 세개로 구성된다.

update 명령은 단일 도큐먼트 혹은 다수의 도큐먼트를 수정할 수 있고 updateOne은 단일 도큐먼트만,

updateMany는 다수의 도큐먼트만 수정 가능하다.

MongoDB 3.2버전 이후부터는 update() 함수 대신 updateOne()과 updateMany() 함수를 사용하기를 권장한다.

 

1. 수정(update)

데이타를 수정할 때 사용하는 명령이며, MSQL의 update와 매칭되는 명령이다.

insert 명령과 마찬가지로 JSON 형태로 데이터를 수정할 수 있다.

 

위와 같은 데이터가 있다고 가정해보자.

name이 '홍길동'인 age의 값 20을 23으로 변경하고자 하면 아래와 같이 명령을 실행할 수 있다.

db.users.update({name: '홍길동'}, {$set:{age: 23}});

 

위와 같이 정상적으로 입력된 것을 확인할 수 있다.

데이터를 조회해보니 age값이 20에서 23으로 변경되었다.

MongoDB에서 update명령을 사용하여 특정 필드의 값을 변경할 때는 $set 연산자를 사용하여야 한다.

만약 사용하지 않는다면 어떻게 될까?

 

$set 연산자를 제거하고 나이를 25살로 변경하여 입력해보았더니 위와 같은 결과가 나왔다.

$set 연산자를 사용하지 않을 경우 입력한 데이터 자체를 통째로 덮어버리게 된다.

즉, 기존에 존재하던 name 필드까지 사라져버리는 것이다.

그렇기에 update 명령 사용시에는 반드시 주의해야 한다. $set 사용하는 것을 실수해서 

다른 필드를 날려버리는 경우가 종종 발생할 수 있다.

 

update 명령은 단일 도큐먼트도 수정 가능하지만 다수의 도큐먼트도 수정 가능하다.

다수의 도큐먼트 수정시에는 multi 옵션을 사용하여 수정할 수 있다.

먼저 테스트를 위해 위와 같이 데이터를 준비하였다.

위 두 데이터 전체의 나이를 25로 변경해보도록 하겠다.

db.users.update({}, {$set: {age: 25}}, {multi: true});

앞의 조건 {}은 전체 필드를 수정하겠다는 의미이다.

조회해보면 다음과 같은 결과가 나온다.

age 필드가 모두 정상적으로 25로 변경되었다.

만약 multi 옵션을 사용하지 않는다면 기본적으로 단일 도큐먼트 수정이 되기 때문에 가장 처음 데이터만 변경이 된다.

 

2. 단일 데이터 수정(updateOne)

update와 사용법은 동일하다. 단지, 단일 도큐먼트만 수정될 뿐이다.

db.users.updateOne({name: '홍길동'}, {$set: {age: 25}});

이와 같이 명령을 실행하면 name 필드가 '홍길동'인 age 값을 25로 변경한다.

완전히 동일하다.

 

3. 다수 데이터 수정(updateMany)

update의 multi 옵션을 자동으로 사용해준 명령이라고 보면 된다.

위의 두개 도큐먼트에 대한 age를 모두 27로 변경해보겠다.

db.users.updateMany({}, {$set: {age: 27}});

multi 옵션 없이 조건에 해당하는 모든 필드가 알아서 수정이 된다.

updateOne과 updateMany은 update 명령에 비해 좀 더 명시적으로 업데이트되었다고 보면 될 것 같다.

 

반응형
반응형

 

몽고DB에서 데이터 삽입하는 방법에 대해 알아보도록 할 것이다.

데이터를 삽입하는 방식에는 크게 세가지가 있다.

insert 명령, insertOne명령, insertMany명령인데, insert의 경우 단일 도큐먼트 혹은 다수 도큐먼트 모두 삽입이

가능하며, insertOne의 경우 단일 도큐먼트만, insertMany는 다수 도큐먼트만 삽입할 수 있다.

 

1. 삽입(insert)

DB에 데이터를 삽입할 때 사용하는 명령어이다. MySQL의 insert와 매칭되는 명령인데,

MySQL의 경우 각 필드에 데이터를 입력시켜주는 반면 몽고DB에서는 데이터를 도큐먼트 단위로 입력시켜주게 되며,

도큐먼트는 JSON 형태의 데이터로 구성된다.

 

users 컬렉션에 아래와 같이 데이터를 입력시켜볼 수 있다.

db.users.insert({

    name: '홍길동',

    age: 20,

});

위와 같이 입력이 완료되었고, find() 명령을 통해 입력된 데이타를 확인할 수 있다.

db.users.find();

위는 users 컬렉션에 있는 모든 도큐먼트를 조회한 결과이다.

insert() 명령으로 넣은 JSON 데이타가 그대로 들어가있다.

그런데 _id라는 필드는 입력하지 않았는데 자동으로 생겨버렸다.

이 필드는 MySQL에서 Primary key와 같은 역할을 하는 필드라고 보면 된다.

중복을 허용하지 않는 고유의 값이며, 기본적으로 인덱스가 걸려있기 때문에 해당 필드로 조회시 검색 성능은 보장된다. 

 

insert를 이용하여 다수의 데이타를 한번 삽입해보도록 하겠다.

다수의 데이타 삽입시에는 배열을 사용한다.

db.users.insert([
{
    name: '최길동',
    age: 21,
},
{
    name: '박길동',
    age: 22,
},
]);

위와 같이 대괄호 []를 통해 다수의 데이터를 삽입할 수 있다.

정상적으로 다수의 데이타가 입력된 것을 확인할 수 있다.

 

2. 단일 데이터 삽입(insertOne)

insertOne은 단일 도큐먼트를 삽입하는 명령이다.

몽고 3.2버전 이후에 추가된 명령이며, insert를 대체하기 위해 만들어졌다고 한다.

insert()명령과 사용법은 동일하며, 배열 형태로 다수의 데이터를 삽입하는 것은 insertMany명령을 이용해야 한다.

db.users.insertOne({
    name: '홍길동',
    age: 20,
});

아래와 같이 조회하면 정상적으로 데이타가 삽입된 것을 확인할 수 있다.

 

3. 다수 데이터 삽입(insertMany)

insertMany은 다수의 도큐먼트를 한번에 삽입하는 명령이다.

insertOne과 같이 몽고 3.2버전 이후에 추가된 명령이다.

다수 데이터 삽입이므로 배열 형태로 삽입하며 아래와 같이 명령을 사용할 수 있다.

db.users.insertMany([
{
    name: '최길동',
    age: 21,
},
{
    name: '박길동',
    age: 22,
}

]);

정상적으로 삽입이 완료되었다.

 

몽고3.2버전 이후에는 insertOne(), insertMany() 명령을 사용을 권장하므로, insert() 명령 사용은 자제하는 것이 좋을 것으로 보인다.

반응형
반응형

ICT 분야의 스타트업을 팀빌딩할 때 빠질 수 없는 팀원이 개발자 팀원이다.

물론 기획자, 디자이너, 마케터 등 다른 파트의 팀원 또한 매우 중요한 역할을 담당하지만,

서비스를 개발하기에 앞서 초기에 비용이 가장 많이 투입되는 부분이 개발쪽이기에 부담이 큰 파트라는 부분은

어느정도 동의할 것이다.

 

여기서 내가 얘기하고자 하는 것은 단순한 개발자 팀원 뽑는 것보다 더 중요한 것은 CTO의 영입이라는 것이다.

심지어 개발 팀원을 두지 않고 외주 개발로만 진행한다하더라도 CTO를 영입하는 것을 권장한다.

단, 팀의 대표가 개발에 대한 역량이 없고, 개발에 대한 커뮤니케이션 능력이 없다는 가정이다.

 

여기서 CTO라는 것은 원론적인 의미의 CTO라기보다는 어느정도 중간 관리자 수준 급(개발자 컨트롤이 가능한)의 개발자를 의미하는 것으로 보면 될 것 같다.

초기 스타트업의 경우 당연히 각 분야 인재를 영입하는게 쉽지 않지만, 개발자 자체도 영입하는게 쉽지 않아서

그냥 개발자라면 무턱대고 뽑거나, 뽑는 것을 포기하고 바로 외주 업체를 찾아나선 후 개발을 시작하는 경우가 많다.

이것이 무조건 잘못됐다고 하는 것은 아니며 리스크가 있을 수 있는 부분을 설명하고자 한다.

 

이유는 여러가지가 있지만 여기서 살펴볼 이유는 '구현된 제품의 수준'이다.

어떤 고도화된 서비스 개발을 경험해보지 않은 개발자의 경우 아무리 초기 제품으로 MVP 모델을 만든다하더라도 이를 확장 모델로 고도화시키기가 매우 어렵게 만들곤 한다.

조금 더 쉽게 예를 들면, MVP 모델을 완성한 후 런칭을 하였는데 사용자가 급격히 늘어나며 데이타베이스에 데이타가 쌓이게 되면서 앱 속도가 점점 느려지고, 사용하기 어려울 정도가 되버리는 경우가 발생할 수 있다.(하나의 예이다.)

이 때 간단한 수정으로 해결될 수도 있지만 상황에 따라 설계의 문제라면, 다시 엎고 새로 만들어야 하는 경우까지 발생하게 된다.

 

나는 주변 스타트업에서 이런 상황을 직접 보기도 했고, 간접적으로 들은 것까지 포함하면 꽤나 흔한 상황이라 느꼈다.

이런 일이 발생하는 이유는 개발자가 이를 고려하지 않거나(혹은 역량 문제로 고려하지 못하거나),

외주에 의뢰하는 경우라면 이러한 디테일한 부분까지는 언급하지 않기 때문이다.

개발자의 역량이 높을 수록 당장의 구현에 급급하지 않고 앞으로를 고려한 설계를 신경쓰게 된다.

(귀차니즘의 문제로 그렇지 않은 경우도 있기는 하다.)

반대로 개발 역량이 낮을 수록 당장 구현에 급급할 뿐, 설계에 대한 노하우가 부족하므로 위와 같은 문제를

초래하게 된다. 

 

외주업체의 경우 당연히 외주 업체마다 case by case인 부분인데, 의뢰하는 경우 외주업체 입장에서는

단발성 프로젝트로 치부되는 경향이 있기 때문에, 고도화된 설계보다 프로젝트를 빨리 마무리하는데 중점을 두게 된다.

그래서 초기 스타트업이 외주 업체에 맡겨 개발한 초도 제품을 고도화시킬 때 쯤에는 새롭게 팀빌딩한 멤버들과 함께

처음부터 온전한 설계를 통해 새로 만드는 경우가 꽤 흔하다.

 

초기 스타트업은 개발 단가에도 민감할 수밖에 없는데, 무조건 싸게 진행하려는 것도 문제가 될 수 있다.

외주 업체는 특히 진행 비용에 맞추어 개발하는 경향이 있기 때문에 개발 단가는 제품 퀄리티에 영향을 크게 미친다.

만약 CTO에 버금가는 인력이 있었다면 단가 문제를 떠나서 외주를 주던, 개발자 팀원을 뽑던 위와 같이 발생할 수 있는 문제를 최소한으로 줄일 수 있었을 것이다.

 

물론 개발하려는 제품에 따라, 혹은 개발하는 개발자에 따라 위와 같은 문제가 없을 수 있고 의외로 순조로울 수도 있다.

하지만 많은 스타트업에서 이런 문제가 발생하고, 또 스타트업이 아니더라도 일반 기업에서 위시캣, 프리모아 등과 같은 개발 중개 사이트를 통해 진행하는 경우에도 개발에 대한 트러블이 꽤나 많이 발생하므로 위 내용을 어느정도 주의하는 것은 좋을 것 같다.

반응형

+ Recent posts