Ruby 메서드

루비 메서드

메서드 정의

메서드는 def 키워드로 정의하며 이름의 마지막에는 !, ?, = 를 사용할 수 있다. 각각의 키워드는 다음과 같이 사용된다.

  1. True, False를 반환하는 메서드의 경우 ?를 사용하기도 한다.
  2. 수신자의 값을 바꿔버리는 메서드의 경우 !를 사용한다. 이러한 메서드는 뱅 메서드라고 불린다.
  3. 대입문의 좌측에 올 수 있는 메서드이름 마지막에 = 기호를 사용한다.

가변 인자 리스트

개수가 정해지지 않은 가변 매개변수를 전달하거나 하나의 매개변수로 여러개의 매개변수를 처리한다면 메서드 인자의 마지막에 가변매개변수 앞에 *기호를 사용하면 된다.

1
2
3
4
5
6
7
def method_1(arg_1, *rest)
"arg_1 = #{arg_1}, rest = #{rest.inspect}"
end

pp method_1("one") # => "arg_1 = one, rest = []"
pp method_1("one", "two") # => "arg_1 = one, rest = [\"two\"]"
pp method_1("one", "two", 1) # => "arg_1 = one, rest = [\"two\", 1]"

첫 번째 매개변수는 일반적인 매개변수로 지정되고 두 번쨰 매개변수에 *기호가 붙어있기 때문에 남은 매개변수 모두를 Array객체에 저장하여 매개변수에 대입한다.

이러한 가변 매개변수는 메서드에서 직접 사용하지는 않지만 상위 클래스에서 같은 이름을 가지고 있는 메서드를 호출하고자 하는 경우에 사용되기도 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Parent
def do_something(*)
pp "parent class"
end
end

class Child < Parent
def do_something(*)
super
end
end

a = Child.new
a.do_something # => "parent class"

메서드와 블록

메서드를 호출할때 블록을 결합시켜 호출을 할 수 있다. 이러 방식으로 결합된 메서드는 내부에서 yield를 사용하여 호출이 가능하다.

1
2
3
4
def some(arg_1)
yield(arg_1 + 1)
end
some(1) { |value| pp "value : #{value}" } # => 2

이러한 방식으로도 사용이 가능하지만 매개변수 앞에 & 기호를 붙여주면 Proc 객체로 변환되어 이 객체를 마지막 매개변수에 대입하여 사용할 수 있다.

1
2
3
4
def proc(arg_1, &proc)
proc.call(arg_1)
end
proc(1) { |v| pp v * 10 } # => 10

루비 메서드 결과 반환

루비 메서드는 일반적으로 결과를 반환한다. 무조건 반환하는 것은 아니다. 하지만 결과를 반환하는 메서드에서 결과값은 일반적으로 마지막으로 실행된 표현식의 결과값이다.
대부분 return 문을 작성하지 않아도 되지만 메서드 실행 중간 빠져나가야 한다면 return 문을 사용하는 경우도 있다.

1
2
3
4
5
6
7
8
def re
100.times do |i|
value = i * i
return i, value if value > 1000
end
end
v = re
pp v # => [32, 1024]

루비에서는 두개 이상의 결과를 return 하게 되면 배열 형태로 결과값을 반환하게 된다. 이런식으로 반환된 Array 값은 병렬 대입문으로 값을 이용 할 수 있다.

1
2
3
4
5
6
7
8
9
def re
100.times do |i|
value = i * i
return i, value if value > 1000
end
end
index, value = re
pp index # => 32
pp value # => 1024

Ruby 정규표현식

정규표현식
그동안 공부를 하면서 서버에서 정규 표현식을 사용하는 일이 얼마나 있을까? 라는 의문과 필요하면 그때그때 찾아보면서 해도 상관없겠다 라는 마음으로 미루고 미룬 것 중 하나가 정규표현식이였다.
간단한 코딩 테스트 문제에서도 등장했던 정규표현식인데 항상 마주하면 생각만큼 쉽지 않고 복잡한 정규표현식…
왜 정규표현식이 서버 코드에서 사용하는 일이 많지 않을 것이라고 생각했는지 의문이 들 정도로 회사 프로젝트에서 정규표현식의 필요성이 느껴졌다. 가장 많이 사용하는 곳은 Rspec을 활용한 테스트 케이스 코드 그리고 파일을 읽고 쓰는 과정에서 항상 등장하는 정규표현식..

그래서 기본적인 정규표현식의 형태에 대해 알아보고자 정규표현식을 학습해보고자 한다. 모든 언어에서 정규표현식을 지원하지만 주로 사용하는 언어가 루비와 자바스크립트인 만큼 그리고 회사 백엔드 코드는 루비로 이루어져있기 때문에? 루비 기준으로 루비에서는 어떤 방식으로 정규표현식이 이루어 지는지 알아보았다.

정규표현식이란?
정규표현식이란 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다.

정규 표현식을 사용해야 하는 이유는 여러가지가 있겠지만 직접 직면한 문제에서 느낀점은 수많은 데이터 혹은 문자들에서 원하는 패턴의 문자열을 매칭하고 치환하는 작업을 할때 정규표현식을 모른다면?
일일히 원하는 결과를 위한 메서드를 만들어야 할 것이다. 하지만 정규표현식을 통한 연산을 통해 원하는 값을 얻고 변환하며 결과를 가지고 조건문에서 사용이 가능해진다면
하나하나 메서드를 만들 필요도 없고 생산성이 좋아진다. 물론 이런 작업을 위해 그래도 난 메서드를 만들어 보겠다는 사람이 굳이 존재할까 싶지만 정규표현식을 활용하여 많은 작업과 처리가 이루어 질 수 있기 때문에 기본적인 정규표현식에대해 학습해보고자 한다.

자세히 보기

Ruby 파일 읽기,쓰기

루비에서 파일 읽기, 쓰기

루비에서는 파일 및 디텍토리 입출력을 위하여 File, Dir클래스를 제공하고 있다.

###File
File 클래스는 다양한 메서드를 통해 파일을 읽고 쓰고 할 수 있으며 다양한 방식으로 활용이 가능하다.
회사 프로젝트에서 File 클래스를 주로 사용하게 되었던 부분은 이미지 파일을 읽고 AWS S3에 업로드 할 때 혹은 어드민에서 엑셀 데이터를 활용, 생성하기 위해 주로 사용하였다.

File 클래스에 대한 다양한 기능은 문서를 통해 학습하고 필요한 기능을 사용하면 되겠다.

File Class Docs
https://ruby-doc.org/core-2.5.0/File.html

포스트에서는 사용했던 메서드와 간단한 사용방법에 대해 기록하고자 한다.

  1. 파일 읽기.
    가장 중요한 읽기이다. 파일을 읽기 위해서는 File.open, File.new 이라는 메서드를 사용한다. 사용방법은 간단하며 다음과 같이 실행한다.
1
2
File.open(filename, option)
File.new(filename, option)

new 메서드와 open 메서드의 동작 결과는 동일하게 흘러간다. 하지만 open 메서드를 사용하면 코드 블록을 통한 작업이 가능해진다.

option 값으로 설정할 수 있는 값은 다음과 같다.

옵션 설명
r 읽기 전용 모드로 파일을 연다.
r+ 읽기,쓰기 모드로 파일을 연다.
w 쓰기 전용 모드로 파일을 연다. 단 파일이 존재한다면 덮어쓴다. 그리고 파일이 없다면 새로 생성한다.
w+ 읽기, 쓰기 모드로 파일을 연다. 단 파일이 존재한다면 덮어쓴다. 그리고 파일이 없다면 새로 생성한다.
a 쓰기 전용으로 연다. 파일이 존재한다면 파일의 끝을 가르키며 없으면 생성한다.
a+ 읽기 쓰기 모드로 연다. 파일이 존재한다면 끝을 가르키고 없다면 생성한다.

  1. 폴더 읽기
    폴더를 읽기 위해서는 Dir class를 활용한다.
1
Dir.new(path)

방식은 파일 클래스와 동일하다. 주로 디렉토리를 읽고 파일을 생성하거나 내부의 파일들을 활용하기 위해 사용되는 것 같다.

디렉토리 내부의 특정 파일을 열기위해 사용하게 되었는데 만약 어떤 경로의 내부에 있는 파일 모두 혹은 특정 파일들만 찾기 위해서는 다음과 같이 사용한다.

1
2
3
4
5
# 이미지 파일만 가져오도록 한다. 확장자는 png파일만
Dir.glob("./tmp/hexo_blog/*.png") do |path|
File.open(path)
...
end

cdn 링크를 통한 이미지 파일을 실행하기 위해서 두가지 클래스들을 활용하며 느낀점은 파일 읽고 쓰기 간단하다고 생각했지만 막상 자주 사용하지 않다보니 다소 어려움이 있었다.

가장 어려웠던 cdn 링크 이미지 파일 열기…

고민하고 구글링을 통해 찾아낸 방법…이다.

1
2
3
4
5
6
7
8
image_path = "https://ifh.cc/g/jmG8MF.jpg"
filename = image_path.split(/[\/]/)[-1].split('?')[0] # 파일 이름만 잘라낸다.
stream = URI.open(image_path) # URI 클래스를 통해 url을 열어준다. 결과값은 strem형식으로 출력이 된다.
File.open("./tmp/#{filename}", 'w+b') do |file| # 해당 경로에 파일이 당연히 없으니 w+ 옵션으로 생성하게 될것이다.
stream.respond_to?(:read) ? IO.copy_stream(stream, file) : file.write(stream) # 스트림형식의 파일을 읽던지 생성하게 끔 하여 파일을 실행한다.
img = URI.open(file)
...
end

이런 방식으로 이미지를 실행하고 생성하며 업로드 등의 작업을 수행할 수 있다.

연휴 전 마지막 평일이라 그런가… 정리 퀄리티가 평소에도 막장이였는데.. 오늘은 더 심한것 같다.. 그래도 이번주 야근하면서 얻어낸? 결과 중 한가지를 기록하고자 마음먹고 기록을 하게 되었다는 것에 의미를 부여하자…
다음 포스트는 루비에서 엑셀 쓰기,읽기 관련하여 기록 예약… 요거 참 골때리고 간단하지만 복잡미묘한 그런 작업…

웹스톰, 루비마인 단축키 정리(기록중)

웹스톰 루비마인 단축키 정리 (기록)

도구창 열기 :⌘0~9

  • 가장자주 쓰게 되는 번호는 프로젝트 폴더 창으로 넘어가는 1번 그리고 커밋 탭인 0번 정도였다.

터미널 열기 : ⎇ F12

설정 탭 열기 : ,

프로젝트 관련 모든 검색 : ⇧⇧

파일 내용 검색 : ⌘ ⇧ F

최근 파일 조회 : ⌘ E

라인 번호로 이동 : ⌘ L

열려있는 탭 이동 : ⌘ ⇧ [ , ]

커밋 창 열기 : ⌘ K

코드 줄 변경 : 이동할 코드 줄에 커서를 두고 ⎇ ⇧ ↑↓

라인 전체 복사 : ⌘ D

라인 전체 삭제 : ⌘ ⌫

단어별 선택 : ⎇ ←→

단어별 이동 : ⎇ ⇧ ←→

오류 발생 영역으로 이동 : F2

오류 해결 방법 제안 : ⎇ ↩︎

라인 합치기 : ⌘ ⇧ J

현재 파일에서 찾기 : ⌘ F

현재 파일에서 변경하기 : ⌘ R

코드 라인 정렬 : ⌘ ⎇ L

Sequelize Migration

도커를 통해 데이터베이스를 띄우고 express를 실행시켜 연결을 해보았다. MySQL과 연결하여 데이터베이스를 사용하기 위해서 Sequelize를 사용하여 연결까지 성공적으로 연결을 진행하였다.

기존에 시퀄라이즈를 사용할때는 모델을 모두 정의한 후 데이터베이스를 생성하고 모델의 수정사항이 있을때마다 **Sync({ force: false || true })**옵션을 통해 데이터베이스를 수정하며 진행했다. 물론 혼자 사용하는 데이터베이스고 서비스를 하지 않는 디비여서 이런방식으로 사용해도 무방하지만 실무에서 사용하는 데이터베이스는 많은 데이터가 있고 구조의 변경이 일어날때 마다 데이터를 백업한다던지 새로 덤프 한다는 것은 현실적으로 어려움이 있다.

이러한 문제점을 보완하기 위해 ORM에서는 마이그레이션 기능을 지원한다. 마이그레이션이란 어떤 운영환경에서 다른 환경으로 환경의 변화를 위해 옮겨지는 작업을 의미한다.

데이터베이스 마이그레이션이란.

데이터베이스 마이그레이션이란 하나의 데이터베이스를 다른 종류의 데이터베이스로 데이터를 옮기는 경우 혹은 두개의 데이터베이스를 하나의 시스템으로 합치거나 분할 혹은 데이터베이스 모델의 구조적 변경을 진행 하는 모든 과정을 의미한다.
데이터 베이스 마이그레이션이란?

그렇다면 시퀄라이즈에서 제공하는 Migration 기능에는 어떤 기능이 있을까? 시퀄라이즈에서는 몇가지 명령어를 통해 마이그레이션 기능을 사용할 수 있다고 한다.

자세히 보기

Doker Mysql(sequelize)

Docker MySQL Express 연결하기

이전 도커로 express앱을 띄운 후 연결 확인 후 데이터 베이스를 도커로 실행 한 후 express와 연결하는 테스트를 진행해보도록 하자.

먼저 docker-compose.yml에 mysql이미지를 추가해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql:
image: mysql:5.7
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
restart: always
environment:
MYSQL_DATABASE: # Database Name
MYSQL_USER: # User name
MYSQL_PASSWORD: # Password
MYSQL_ROOT_PASSWORD: # Root Password
ports:
- "3306:3306"
volumes:
- ./data:/var/lib/mysql
- ./mysql.conf:/etc/mysql/conf.d

docker-compose up 명령 실행 후 mysql이 실행중인 것을 확인하고 docker exec -it #{name} bash 를 통해 mysql로 접근이 가능하다.

자세히 보기

Docker Node.js nodemon

도커를 활용하여 Express를 구동하기 위해 이전 포스팅을 통해 기본적인 앱을 띄워 보았다. 도커를 통해 express를 실행하였지만 코드의 수정이 있을 때 마다 빌드를 다시 해주어야 하는 문제점이 있었다.
node.js에서는 nodemon이라는 모듈을 사용하여 개발환경에서 코드의 변경사항이 감지되었을때 자동으로 코드의 반영사항을 포함하기 위해 서버를 재시동 해주며 개발을 진행한다.

도커를 통해 띄운 express를 로컬에서 작업 후 변경사항을 반영해주기 위해서는 도커의 작업 디렉토리와 로컬 작업 디렉토리를 볼륨 연결 설정을 통해 연결해주고 nodemon으로 express를 구동해주면 된다.

  1. docker-compose.yml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    version: "3.8"

    services:
    mysql:
    image: mysql:5.7
    command:
    --default-authentication-plugin=mysql_native_password
    --character-set-server=utf8mb4
    --collation-server=utf8mb4_unicode_ci
    restart: always
    environment:
    MYSQL_DATABASE: test
    MYSQL_USER: test
    MYSQL_PASSWORD: 1210ss
    MYSQL_ROOT_PASSWORD: 1210ss
    ports:
    - "3306:3306"
    volumes:
    - ./data:/var/lib/mysql
    - ./mysql.conf:/etc/mysql/conf.d

    docker-test:
    build:
    context: .
    args:
    PORT: "4000"
    image: docker-node-app
    container_name: docker-node-app
    volumes:
    - .:/usr/src/app
    - /usr/src/app/node_modules
    ports:
    - "1210:4000"
    docker-compose.yml 파일을 통해 여러 컨테이너를 한번에 관리해주는 방식으로 하나의 서비스를 위해 실행하거나 존재해야하는 이미지들을 한 파일을 통해 정의하는 방식이다.

mysql은 이 후 사용할 예정이므로 넘어가도록 하고 volumes옵션이 중요한 부분이다.

volumes은 다음과 같이 작성해 주면된다. <로컬 작업 디렉토리>:<도커 컨테이너 디렉토리> 이것은 로컬 디렉토리와 도커의 디렉토리를 연결하겠다는 의미로 코드의 변경이나 생성 삭제와 같은 작업의 결과를 공유해준다.

이 후 nodemon을 통해 express 를 실행하고 로컬에서 작업 후 변경사항이 생기게 되면 도커에서 실행중인 express가 재시동 되며 수정 사항을 반영하게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
FROM node:12

ARG PORT
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# . 은 현재 디렉토리의 모든것을 /usr/src/app으로 복사한다는 의미다.
COPY . /usr/src/app
RUN npm install

RUN npm install -g nodemon
# Bundle app source

EXPOSE $PORT

# 도커에서 nodemon을 실행하기 위해 필요한 옵션
CMD ["nodemon", "-L", "app.js"]

컨테이너를 다시 빌드 후 접속하고 코드를 수정하면 변경사항이 자동으로 반영되는 모습을 확인 할 수 있다.

Docker 개발환경 세팅하기

Docker 개발 환경 구축

회사에서 처음 클론 받은 레포지토리의 개발 환경 구축을 위해 도커환경을 구축하며 사용하던 명령어들과 도커를 이용하여 프로젝트 환경을 세팅하는 기본적인 것들에 대해서 기록하고자 글을 남깁니다.

자세히 보기