안녕하세요 레이군 입니다.
오늘은... 홈 오토메이션의 꽃이라고 할 수 있는 자동화에 대해서 끄적거려 보려고 합니다.
당연히 자동화 관련 글도 있을줄 알았는데, 뭔가 자동화 예제는 많은데...
정작 자동화란? 에 대한게 없어서 완전 생 초짜분들은 접근이 어려운것 같더라구요...
(제가 그랬어요.... 아는게 없으니 뭘 찾아볼수도 없더라구요...ㅠ.ㅜ)
그래서! 한번 써보려고 합니다... 부족하겠지만 그런 부분은 다른 고수님들이 보충해 주시겠지요 ^^;
오토메이션등 각종 설정을 !include 명령을 사용하여 개별 yaml파일로 분리해둔 상태입니다.
hass.io 등과는 다를 수 있으니 참조하시기 바랍니다.
https://www.home-assistant.io/docs/automation/
자동화 관련은 공홈을 참조하시기 바랍니다.
1. 자동화(오토메이션) 이란?
2. 자동화를 위한 기본 조건
3. 자동화 기본 예제
4. 자동화 구성시 유의사항
5. template를 사용하여 자동화를 단순화 / 입맛대로 바꾸기
1. 자동화(오토메이션) 이란?
자동화란, 글자 그대로 특정 동작을 사람이 실행하지 않고 자체적으로 실행할 수 있게 만드는것 입니다.
자동화가 어려운것 같지만, 저희는 실제로 이미 구성된 자동화를 실생활에서 많이 사용하고 있습니다.
제 생각에 가장 쉽게 접할 수 있고 사용하고 있는 자동화는, 센서등인것 같습니다.
움직임이 감지되면 -> 불이 켜진다. -> xx초 후 불이 꺼진다
이 단순한것으로 사람들은 많이 편리해지고, 상시 가동이 아니라서 에너지도 절약되고, 밤에 움직이기도 안전해지죠.
여기에 약간의 변수를 첨가하면, 다음과 같습니다.
움직임이 감지되면 -> 불이 켜진다.(단, 주변의 밝기가 일정 수준 이하일때만) -> xx초 후 불이 꺼진다
요즘 나오는 대부분의 센서등은 위 조건이 자동으로 입력된 상태로 출고됩니다.
여기에 일부 센서등은 xx초를 조절할 수 있어서 특정 시간동안 불을 켜둘수도 있지요.
스마트폰을 사용하고 있습니다.
다른일 때문에 잠시 스마트폰을 놔두면, 일정 시간 이후에 화면이 꺼지죠(기본 설정상태라면)
이것도 xx초 동안 동작이 없으면 -> 화면을 꺼라(잠궈라)
여기에 충전중 시계모드 설정등을 해두면
xx초 동안 동작이 없으면 -> 화면을 꺼라(다만 충전중인경우, 시계모드 설정 후 화면을 계속 켜둠)
별거 아닌거 같죠? 하지만 이렇듯 우리는 실생활에서 이미 자동화에 익숙해져 있습니다.
자동화, 어렵지 않죠? 별거 아니겠죠? 자 그러니까 한번 공부해 봅시다~
(사실 드럽게 어려워요........아니 뭔 변수가 이렇게 많아...!)
2. 자동화를 위한 기본 조건
자동화는 기본적으로 2가지로 이루어 집니다.
xx 하면 -> yy 해라
여기서 xx는 트리거, yy는 액션 이라고 불립니다.
조금 더 추가하면, 3가지로 이루어 집니다.
xx 하면(단, zz할때) ->yy 해라
마찬가지로 xx는 트리거, yy는 액션이고... 중간에 있는 zz는 컨디션 이라고 불립니다.
1. 필수 - 자동화를 실행할 수 있는 트리거(방아쇠) - or값으로 동작합니다.
https://www.home-assistant.io/docs/automation/trigger/
자동화란, 특정 상황에서 특정 동작을 실행하는게 기본입니다. 그 특정 상황을 인지하기 위해서는 트리거가 필요합니다.
움직임이 감지되면 -> 불 켠다(단, 주변의 밝기가 일정 수준 이하일때만) -> xx초 후 불 꺼짐
위 예제에서라면, 움직임이 감지된다 라는 트리거가 있는거죠.
트리거는 상태값을 불러올 수 있는 거의 모든것으로 할 수 있습니다.
sun 센서 사용시, 일출 / 일몰을 기준으로 하여 특정 각도, 시간으로 트리거 가능
time 센서 사용시, 특정 시간으로 트리거 가능
도어센서 사용시, 문열림시, 문 닫힘시 등 상태로 트리거 가능
온습도 센서 사용시, 온도나 습도등에 따라 트리거 가능
등등등등....정말 HA에 연결하거나 불러올 수 있는 데이터 대부분은 트리거로 쓸 수 있습니다.
2. 필수 - 자동화 트리거 동작시 실행할 액션
https://www.home-assistant.io/docs/automation/action/
트리거로 특정 상황을 지정했다면 그때 실행할 동작을 지정해야겠죠?
상태값을 변경하거나 할 수 있는 모든게 액션으로 쓰일 수 있습니다.
움직임이 감지되면 -> 불 켠다(단, 주변의 밝기가 일정 수준 이하일때만) -> xx초 후 불 꺼짐
위 예제에선 불을 켜는것과 xx초 경과 후 불이 꺼지는게 액션이 됩니다.
불 켜기 -> xx초 경과 후 불 끄기 라는 1개의 액션일수도 있고...
불 켜기 -> xx초 동안 움직임이 없으면 -> 불 끄기 라는 2개의 액션 일수도 있습니다.
이건 센서등 종류에 따라 다른거라 조금 뒤에 얘기할께요~
여튼, 액션도 마찬가지로 상태값 변경이 되는 거의 대부분을 설정할 수 있습니다.
불을 켠다 / 플러그 스위치를 켠다 / IR리모트로 신호를 보낸다 / 구글홈에게 TTS를 날린다 / 노티를 날린다..
주로 자주 쓰는 자동화 액션은 이정도겠네요. 그 외에도 수없이 많습니다만...
그거 찾아야할 정도면 이미 고수라 이글 안 보셔도 되요~
3. 선택 - 트리거가 실행될 조건 지정(컨디션) - and 값으로 동작, or값으로 지정할 수 있습니다.
https://www.home-assistant.io/docs/automation/condition/
자동화라는건, 말 그대로 자동으로 움직이는거라... 원하지 않을때도 그 동작이 실행될 수 있습니다.
그러지 않기 위해서는 특정 조건이라는걸 만족시켜 주는게 통제하기 좋습니다.
움직임이 감지되면 -> 불 켠다(단, 주변의 밝기가 일정 수준 이하일때만) -> xx초 후 불 꺼짐
위 예제에서 컨디션은, 주변 밝기가 일정 수준 이하일때 만 움직임이 감지되는 트리거를 실행하게 됩니다.
이러면 한낮에 밝은곳에 있는 센서등이 동작하지 않으니 불필요한 전력소모를 줄일수도 있겠죠.
마찬가지로 HA에서 상태값을 불러올 수 있는 거의 모든것을 컨디션으로 쓸 수 있습니다.
sun 센서로 일몰시에만 동작시키거나,
device tracker 등 재실센서로 사람이 있을때만 동작시키거나,
특정 스위치가 on인 상태에서만 동작한다던가...
변수 통제를 위해서는 권장되는 부분이나, 꽤나 어려울 수 있는 부분입니다.
4. 선택 - 트리거 / 컨디션을 여러개 사용
센서등중 지속적인 움직임이 감지되면 불이 안 꺼지는 녀석들이 있는데, 이건 트리거가 2개 인겁니다.
xx초 후 불 꺼짐 : 불 켜짐 -> xx초 후 불 꺼짐 이라는 하나의 액션으로 동작, 보통 중간에 움직임이 있어도 꺼졌다가 다시 켜짐
xx초 동안 움직임이 없을때 불 꺼짐 : 불 켜짐 액션 -> xx초 동안 움직임이 없는지 확인하는 트리거 동작 -> 움직임이 없으면 불 꺼짐 액션
이런식으로 자동화란 1:1로 매칭되지 않는 경우도 많습니다.
3. 자동화 기본 예제
자 이제 위에 설명한 예를 HA의 자동화로 만들어 볼까요?
# automations.yaml 에 작성
# 자동화 이름 설정
- alias: Motion Light
# HA재시작 / 오토메이션 새로고침등 동작시 기본 상태값 설정
initial_state: 'on'
# 자동화 트리거 설정
trigger:
# 트리거 종류는 state(상태값 변경)
- platform: state
# 엔티티 ID는 binary_sensor.motion(모션센서)
entity_id: binary_sensor.motion
# 상태가 on 으로 변경될때(off -> on / 알수없음 -> on 등)
to: 'on'
# 다음 컨디션 일때만 트리거 동작
condition:
# 컨디션 종류는 상태값
- condition: state
# 엔티티 ID는 sensor.brightness(조도센서)
entity_id: sensor.brightness
# 엔티티의 상태값이 10 이하일때
below: '10'
# 컨디션 + 트리거가 만족할경우 다음 동작을 실행
action:
# 액션의 서비스는 light.turn_on 으로 라이트 켜기
- service: light.turn_on
# 엔티티 ID는 light.light1 으로 설정하여 해당 엔티티를 켬
entity_id: light.light1
# 30초 후
- delay: '00:00:30'
# 서비스 light.turn_off 호출
- service: light.turn_off
# 엔티티 ID는 light.light1 으로 해당 엔티티를 끔
entity_id: light.light1
자 이렇게 하면 조도센서 10 이하인 상태로 모션센서 감지시 -> light1을 켜고, 30초 후 light1을 끈다.
라는 자동화가 완성됩니다.
자동화는 기본적으로 위에서 아래로 진행됩니다.
액션에 서비스가 3개가 있다면, 1 / 2 / 3 번 순서로 진행이 되는거죠.
단 1개의 서비스에 entity가 여러개(light.light1, light.light2, light.light3 형태) 로 들어가 있는경우...
이건 입력순서대로 되는게 아닌거 같더라구요....랜덤인가...?
여튼.. 참 쉽죠.......?
쉽긴 개뿔 ㅠ.ㅜ 아니 뭐 이런 단순한거 하나 하는데 몇줄을 적어야 하는건지...ㄷㄷ
자 그런데... 여기서 문제!
액션이 light1을 켜고 -> 30초 대기 -> light1을 끄고 입니다.
그 사이에 사람이 움직이면요??
그래도 30초 후에 꺼져요...액션 자체가 그리 지정되어 있어요...
거기다 더 큰 문제는! 트리거가 모션센서 to: on 이죠?
to 라는건 현 상태가 아닌 on 으로 변경될때를 이야기 합니다.
모션센서는 짧아야 5초 / 보통 20~30초, 길면 1~2분의 디텍트 딜레이가 있습니다.
보통 딜레이 시간동안 움직임이 없어야 off로 인식이 되죠.
20초 짜리 딜레이를 가진 모션센서로 동작시켰는데, 동작 후 25초쯤에 움직였어요.
그러면 모션센서는 이미 on 되어 있고 -> 5초 후(딜레이가 30초 이므로) light1은 꺼지고...
트리거는 모션센서 to: on 이기때문에 현 상태가 on일때는 동작이 안되고... 불은 안켜지죠.
자 그러면 이 부분을 개선하기 위해 좀 더 보강을 해봅니다.
# automations.yaml 에 작성
- alias: Motion Light on
initial_state: 'on'
trigger:
- platform: state
entity_id: binary_sensor.motion
# 상태가 on 으로 변경될때(off -> on / 알수없음 -> on 등)
to: 'on'
condition:
- condition: state
entity_id: sensor.brightness
below: '10'
action:
- service: light.turn_on
entity_id: light.light1
- alias: Motion Light off
initial_state: 'on'
trigger:
- platform: state
entity_id: binary_sensor.motion
# 상태가 off 으로 변경될때(on -> off / 알수없음 -> off 등)
to: 'off'
# off 상태로 변경된지 30초 이후에 트리거
for: '00:00:30'
condition:
- condition: state
# 엔티티 ID는 light.light1
entity_id: light.light1
# 엔티티의 상태값이 on 일때(불이 켜져있을때)
state: 'on'
action:
# 서비스 light.turn_off 호출
- service: light.turn_off
# 엔티티 ID는 light.light1 으로 해당 엔티티를 끔
entity_id: light.light1
자동화를 2개로 나눴어요!
이렇게 하면 Motion Light On 자동화로 조도가 10 이하일때 모션센서가 on 되면 light1이 켜지고...
Motion Light Off 자동화로 light1이 켜진 상태에서 모션센서가 off되고 30초 후 light1이 꺼집니다.
(모션센서의 디텍트 딜레이가 길다면, for은 생략해도 됩니다 자동화는 상황에 따라 유동적이니까요~)
그런데......
겨우 이거 하는데 자동화를 2개 만드는건 왠지 싫죠?
그러면 조금 복잡하겠지만 어떻게 하나로 줄일 수 없을까요?
당연히 있습니다!
조금 복잡한 방법과 많이 복잡한 방법이 있는데 전 아직 초보니까 조금 복잡한걸로 해볼께요
(완벽하게 원하는 자동화는 아니지만, 간단하게 하는건 이정도로...)
이번에 쓸건, wait_template 라는겁니다.
https://www.home-assistant.io/docs/scripts/#wait
wait_template란, 특정 시간 내에 지정된 상태로 변경되면 다음 액션을 실행,
만약 지정 시간 내에 특정동작이 실행되지 않으면 continue_on_timeout 옵션에 따라 다음 액션 실행여부를 결정합니다.
지금은 어차피 light.turn_off 가 진행되어야 하니 continue_on_timeout 옵션은 무시하겠습니다.(기본값이 on이라 안 써도 되요)
# automations.yaml 에 작성
- alias: Motion Light
initial_state: 'on'
trigger:
- platform: state
entity_id: binary_sensor.motion
to: 'on'
condition:
- condition: state
entity_id: sensor.brightness
below: '10'
action:
- service: light.turn_on
entity_id: light.light1
# 지정 시간 내에 모션센서의 상태값이 off로 변경되면(혹은 지정 시간이 지나면)
- wait_template: "{{ is_state('binary_sensor.motion', 'off') }}"
# 시간은 5분으로 설정함
timeout: '00:05:00'
- service: light.turn_off
entity_id: light.light1
자 이렇게 하면 조도 10이하에서 모션센서가 on 되면 light1을 켜고
5분이 경과하거나 그 이내에 모션센서가 off로 변경되면 light1을 끕니다.
여기서 더 완벽하게 하려면, 중간에 모션센서가 혹시 off로 변경되어도 바로 꺼지지 않게 하고 싶은데..
그러면 위에서 설명한 많이 복잡한 방법으로 가는거라...
좀 더 나중에...!
4. 자동화 구성시 유의사항
자동화를 구성할때는 생각보다 많은걸 신경써야 합니다.
위 예제처럼 달랑 모션으로 라이트 켜고 / 끄고 하는것만 해도...
1. 컨디션으로 조도센서의 값을 얼마로 넣을것인가
2. delay로 30초 지정해도 상관이 없는가
3. 모션센서의 디텍트 딜레이가 얼마나 되는가
4. delay를 쓰지 않는 경우 끄는 타이밍을 어떻게 잡을것인가
5. 모션센서가 on 상태에서 light1이 꺼지지 않게 할 수 없는가
이 모든것들을 고려하다 보면, 오토메이션 하나가 점점 방대해집니다.
하지만 그만큼 각종 변수에 대한 통제가 이루어지기 때문에 원하는 자동화가 만들어 집니다.
좀 더 편하고 원하는대로 만들 수 있는 자동화 구성을 위해 한발짝 더 전진해 봅시다~
5. template를 사용하여 자동화를 단순화 / 입맛대로 바꾸기
자동화를 단순하게 한다면, 트리거/상태가 적기때문에 그만큼 사용자가 자동화에 맞춰서 움직여야 합니다.
1개의 자동화로 모션 감지 -> 불켜기 -> delay 30초 -> 불끄기
로 설정했다면, 30초 이상 불이 켜져있게 할 수 없습니다.
어쩔 수 없이 꺼졌다가 다시 모션센서를 감지 시켜서 불을 켜야하죠.
2개의 자동화로 on / off용 두개로 나눈다면 모션 감지시 불이 켜지고, 혹시 모션이 off로 바뀐다고 해도 30초 내에
다시 모션이 감지되면 불 꺼짐이 동작하지 않습니다. 이정도면 원하는 자동화가 만들어 지는거죠.
하지만 자동화 양이 점점 많아지다 보면, 하나에도 몇줄씩 잡아먹는 자동화 항목 하나하나가 많아보입니다.
그래서 template 라는것에 손을 대게 됩니다.
각종 값으로 계산을 할수도 있고, 특정 상태값이 만족할때 ture / false 값을 반환할수도 있고...
상태에 따라 특정 문자열을 출력할수도 있습니다.
저도 아주 기본밖에 모르는 부분이지만... 이걸로 아주 여러가지를 할 수 있습니다.(그만큼 복잡한게 함정 ㄷㄷ)
위에 설명한 모션 on / off 두가지의 자동화를 하나로 통합하는걸 해볼까요?
# automations.yaml 에 작성
- alias: Motion Light template
initial_state: 'on'
trigger:
- platform: state
entity_id: binary_sensor.motion
to: 'on'
- platform: state
entity_id: binary_sensor.motion
# 상태가 off 으로 변경될때(on -> off / 알수없음 -> off 등)
to: 'off'
# off로 변경 후 30초 동안 유지되는 경우 트리거됨
for: '00:00:30'
condition:
# 컨디션은 다음 하위 컨디션중 일부가 만족할때 동작
- condition: or
conditions:
# 첫번째 컨디션의 종류는 상태값
- condition: state
entity_id: sensor.brightness
below: '10'
# 두번째 컨디션의 종류는 상태값
- condition: state
entity_id: light.light1
state: 'on'
action:
# 액션의 서비스는 template로 설정, 다음 값을 만족할때 만족되는 값을 반환함
# light.turn_ 뒤에 binary_sensor.motion의 state 값을 붙여서 service를 호출
# 모션센서가 on 상태라면 light.turn_on 서비스 / 모션센서가 off라면 light.turn_off
- service_template: 'light.turn_{{ states.binary_sensor.motion.state }}'
# 엔티티 ID는 light.light1 으로 설정
entity_id: light.light1
자 이렇게 하면...
조도값이 10 이하이거나 / light1이 켜져있는 상태에서만 트리거를 인식하고
모션이 켜지거나 / 모션이 꺼진상태로 30초 동안 유지될때 오토메이션을 트리거 하고,
액션은 states.binary_sensor.motion.state 로 모션센서의 state 값을 light.turn_ 뒤에 붙여서 service를 실행합니다.
단순화 하긴 했는데...
이정도로 입맛대로 바꾼다고 하기는 좀 그렇죠?
자 그러면.. 다른 시나리오를 한번 짜보겠습니다!
저희집 거실에 있는 고퀄 스위치 + 샤오미 버튼을 조합한 자동화 시나리오 입니다.
(고퀄이 물리버튼이 아니라 직접 보면서 켜고/꺼야해서 너무 불편해서 만든 자동화...ㄷㄷ)
# 자동화 이름 설정
- alias: Livingroom light control
initial_state: 'on'
trigger:
# 트리거 플랫폼은 이벤터
- platform: event
# 타입은 샤오미 버튼 클릭
event_type: xiaomi_aqara.click
event_data:
# 엔티티 이름 지정
entity_id: binary_sensor.switch_123
# 액션 설정
action:
# 서비스는 템플릿으로 if문 형태 만족시 해당 문자열을 출력함("큰 따옴표" 사이의 값을 사용)
# 싱글클릭 and (top_right or top_left가 켜져있을때) = switch.turn_off 서비스 호출
## 아래 예제에는 template 문구 사이에 # 으로 주석을 넣었으나, 문법 오류이므로 반드시 삭제 필요 ##
- service_template: "{% if trigger.event.data.click_type == 'single' and
(is_state('switch.top_right', 'on') or is_state('switch.top_left', 'on')) %}
switch.turn_off
# 싱글클릭 and (center_right or center_left 가 켜짐) and (tor_right or top_left가 꺼짐)
# = switch_turn_of 서비스 호출
{% elif trigger.event.data.click_type == 'single' and
(is_state('switch.center_right', 'on') or is_state('switch.center_left', 'on'))
and (is_state('switch.top_right', 'off') or is_state('switch.top_left', 'off')) %}
switch.turn_on
# 별도 조건 없이 싱글클릭시 = switch.turn_on 서비스 호출
{% elif trigger.event.data.click_type == 'single' %} switch.turn_on
# 별도 조건 없이 더블클릭시 = switch.turn_off 서비스 호출
{% elif trigger.event.data.click_type == 'double' %} switch.turn_off
# if문 종료
{% endif %}"
# 호출할 데이터를 템플릿으로 지정함
data_template:
# 호출시 엔티티 ID를 다음 값으로 지정
# 싱글클릭 and (top_right or top_left가 on인 경우) = 다음 엔티티를 지정 switch.top_left, switch.top_right
entity_id: "{% if trigger.event.data.click_type == 'single' and (is_state('switch.top_right', 'on')
or is_state('switch.top_left', 'on')) %}
switch.top_left, switch.top_right
# 싱글클릭 and (center_right or center_left 가 켜짐) and (tor_right or top_left가 꺼짐)
# = 다음 엔티티를 지정 switch.top_left, switch.top_right
{% elif trigger.event.data.click_type == 'single' and (is_state('switch.center_right', 'on')
or is_state('switch.center_left', 'on')) and (is_state('switch.top_right', 'off')
or is_state('switch.top_left', 'off')) %}
switch.top_left, switch.top_right
# 별도 조건 없이 싱글 클릭인 경우 = switch.center_left, switch.center_right 를 지정
{% elif trigger.event.data.click_type == 'single' %}
switch.center_left, switch.center_right
# 별도 조건없이 더블클릭인 경우 = bottom_left, center_left, center_right, top_left, top_right
# 를 지정
{% elif trigger.event.data.click_type == 'double' %}
switch.bottom_left, switch.center_left, switch.center_right, switch.top_left, switch.top_right
# if문 종료
{% endif %}"
※ 템플릿 구문 중간에 #으로 주석 넣은 부분은 지워주셔야 합니다.
템플릿은 처음 " 부터 마지막 " 사이에 있는 모든 글자를 기반으로 하기때문에
주석처리는 소용이 없습니다. 설명을 위해 첨부한 부분이므로 반드시 지우셔야 합니다.
위와 같이 하면 다음 순서로 자동화가 이루어 집니다.
싱글클릭 -> top_right 혹은 top_left가 켜져 있는가?
ㄴ yes -> switch.turn_off 서비스 + top_right, top_left 엔티티 지정
ㄴ no -> 다음 if문 확인
싱글 클릭 -> cneter_left 혹은 center_right 가 켜져 있고, top_right 혹은 top_left가 켜져 있는가?
ㄴ yes -> switch.turn_on 서비스 + top_right, top_left 엔티티 지정
ㄴ no -> 다음 if문 확인
싱글 클릭 -> switch.turn_on 서비스 + center_left, center_right 엔티티 지정하여 불 켜기
더블클릭 -> switch.turn_off 서비스 + 모든 엔티티 지정하여 불 끄기
top_left : 거실 주등, top_right : 식탁등 -> 주로 식사할때 켬
center_left : 거실 보조등, center_right : 주방등 -> 평상시 켜는 전등
그래서 저희집에선 이렇게 동작합니다.
거실 보조등이나 주방 등이 꺼져있는 상태로 싱글클릭 -> 거실 + 주방등 점등
거실보조등이나 주방등이 켜져있고, 거실 주등 혹은 식탁등이 꺼진상태로 싱글클릭 -> 식탁, 거실 주등 점등
거실 및 식탁등이 다 켜진 상태로 싱글클릭 -> 식탁, 거실 주등 소등
어떠한 상태에서든 더블클릭 -> 모든 등 소등
후아.......길다옹...!
제 실력으로는 여기까지네요....나머지는 더 고수님들이 도와주실꺼예요!!!
모두모두 열심히 공부하고 테스트 해보고 실패해보고... 그러면서 얻은 경험을 공유해주세요~~
지식은 나누면 배가되는 마법! 빠밤~
'SmartHome. IoT > SmartHome 기본' 카테고리의 다른 글
홈 IoT의 가장 기본, 플랫폼 이란? / 스마트홈 구축시 생각할 것들 (0) | 2022.01.15 |
---|---|
HomeAssistant(HA) 에 대한 기본적인 이해. (0) | 2022.01.15 |
라즈베리 초보자를 위한, Docker의 개념에 대한 이해. (0) | 2022.01.15 |
HA(Home Assistant)에 테마를 적용해 봅시다! (0) | 2022.01.04 |
HA(Home Assistant)의 각종 상태값을 파일로 내보내는 방법 (0) | 2022.01.04 |