GitHub Actions 에서 Only actions in <ID> are allowed for this repository 에러가 발생할 경우
Workflow 로그를 확인하면 다음과 같은 문구의 에러가 발생한다.
Error
Only actions in "novenber11th" are allowed for this repository
이 경우 Setting -> Actions 메뉴에서 Actions permissions 가 Enable local and third party Actions for this repository 로 설정되어 있는지 확인한다. 에러가 발생할 당시에는 해당 값이 Enable local Actions only for this repository 로 설정되어 있었다.
먼저 client 소켓에서 sendMessage 함수로 메시지를 보낼 경우에는 @MessageMapping 어노테이션으로 받을 수 있다. 두 번째로 @RequestMapping을 사용할 경우에는 웹 소켓이 연동된 Client와 무관하게 외부의 GET 질의로 이벤트를 Trigger 할 수 있다.
- 메시지를 응답하는 방식도 2가지다.
첫 번째는 @SendTo 어노테이션을 사용하여 해당 topics를 수신하는 Client Websocket에 메시지를 전달할 수 있다. 이 경우 해당 함수는 리턴할 타입을 정의해야하며 반환값 리턴을 통해 Client에 메시지를 전달한다.
두 번째는 SimpMessagingTemplate를 사용하는 방식이다. @SendTo 어노테이션을 사용하지 않고SimpMessagingTemplate로 응답값을 보낼 수 있으며, 이 경우 해당 함수의 리턴값은 void로 처리해야 한다. SimpMessagingTemplate의 convertAndSend 함수를 사용하면 특정 유저에게만 메시지를 보낼 수 있다.
@RestController
public classTestController{
@Autowired
private SimpMessagingTemplate webSocket;
@MessageMapping("/sendTo")
@SendTo("/topics/sendTo")
public String SendToMessage() throws Exception {
return"SendTo";
}
@MessageMapping("/Template")
public voidSendTemplateMessage() {
webSocket.convertAndSend("/topics/template" , "Template");
}
@RequestMapping(value="/api")
public voidSendAPI() {
webSocket.convertAndSend("/topics/api" , "API");
}
}
2. React 코드 구현
1) 프로젝트 생성
npx create-react-app websocket_react
2) 관련 라이브러리 추가
- sockjs-client, react-stomp 라이브러리 추가
yarn add sockjs-client react-stomp
3) 테스트 App 코드 작성
- react-stomp 라이브러리를 사용하여 웹소켓을 주고 받을 SockJsClient 컴포넌트를 생성한다.
SockJsClient 생성 시 url은 WebSocket Config에서 Endpoint로 추가한 주소를 지정한다. topics는 서버가 메시지를 보낼 시 수신할 토픽을 지정한다. 다중 지정할 수 있다.
예제에서는 서버에서 3가지 방식으로 발신하는 모든 메시지를 수신한다.
- SendTo, SendTemplate 버튼은 위 Controller에서 지정한 함수를 트리거하는 이벤트를 작성한다.
버튼 클릭 시 SockJsClient의 ref가 지정된 websocket에서 각 sendMessage 함수를 사용하여 서버에 메시지를 보낸다.
함수형 프로그래밍은 사이드 이펙트(side effect)가 없다는 것이 특징입니다. 이는 함수 외부에 있는 데이터 의존하지 않으며, 함수 외부에 있는 데이터를 변경하지 않는 것을 의미합니다. ‘함수형'의 모든 것은 이러한 속성에서 파생된다는 점을 명심해야 합니다.
다음은 비 함수형 function의 예제입니다.
다음은 비 함수형 function의 예제입니다.
var a = 0;
functionincrement1() {
return a += 1;
}
(역주 : increment1 함수가 외부 데이터 변수인 a 에 의존합니다.)
다음은 함수형 function의 예제입니다.
increment2(a) {
return a + 1;
}
반복문 대신에 map과 reduce를 사용하십시오.
Map
map은 함수와 배열 원소를 사용합니다. 먼저 비어있는 배열을 새롭게 생성합니다. 원본 배열의 각 원소에 대해 함수를 실행하고 반환 값을 새로운 배열에 삽입합니다. 모든 과정이 끝나면 새로운 배열을 반환합니다.
아래의 비 함수형 코드는 이름의 배열을 임의로 할당된 코드명으로 변경합니다.
var names = [“Mary”, “Isla”, “Sam”];
var code_names = [“Mr. Pink”, “Mr. Orange”, “Mr. Blonde”];
for(var i in code_names) {
var randomIndex = Math.floor(Math.random() * code_names.length);
var randomValue = code_names[randomIndex];
names[i] = randomValue;
}
(역주 : 실제 이름 리스트인 names를 반복문 수행 과정 내에서 직접 변경합니다.)
console.log(names);
# => ["Mr. Blonde", "Mr. Pink", "Mr. Pink"]
위 코드를 for 반복문 대신 map 함수를 사용하면 다음과 같습니다.
var names = [“Mary”, “Isla”, “Sam”];
var code_names = [“Mr. Pink”, “Mr. Orange”, “Mr. Blonde”];
names = names.map(function(item) {
var randomIndex = Math.floor(Math.random() * code_names.length);
var randomValue = code_names[randomIndex];
return randomValue;
});
(역주 : names에 대한 변경은 map 함수가 완료된 후 return 과정에서 이루어집니다.)
console.log(names);
# => ["Mr. Orange", "Mr. Orange", "Mr. Blonde"]
Reduce
reduce 또한 함수와 배열 원소를 사용합니다. 각 원소를 조합하여 생성된 값을 반환합니다.
다음 예제는 ‘Sam’이라는 단어를 문자열 목록에서 찾아 카운트합니다.
var sentences = [
‘Mary read a story to Sam and Isla’,
‘Isla cuddled Sam’,
‘Sam chortled’
];
var sam_count = 0;
for(var i in sentences) {
var results = sentences[i].match(/Sam/g);
if(results) {
sam_count += results.length;
}
}
console.log(sam_count);
# => 3
동일한 코드를 reduce로 작성하면 다음과 같습니다.
var sentences = [
‘Mary read a story to Sam and Isla’,
‘Isla cuddled Sam’,
‘Sam chortled’
];
var sam_count = sentences.reduce(
function(previousValue, currentValue) {
var results = currentValue.match(/Sam/g);
if(results) {
previousValue += results.length;
}
return previousValue;
},
0
);
console.log(sam_count);
# => 3
map과 reduce의 장점
한 줄로 간단하게 처리할 수 있습니다.
map과 reduce에서는 반복에서 가장 중요한 부분인 배열, 연산, 반환 값이 항상 같은 위치에 있다.
반복문의 코드는 이전에 선언된 변수에 영향을 미칠 수 있다. map과 reduce는 일반적으로 함수형으로 작동합니다. (역주 : map과 reduce는 함수형 프로그래밍 개념에 따라 기존 변수에 대한 사이드 이펙트가 없도록 구현하는 것이 원칙입니다.
map과 reduce는 원소 단위의 연산입니다. 반복문은 사람이 한 줄 단위로 로직을 읽고 이해해야 합니다. 반면에 map과 reduce는 복잡한 알고리즘과 원소의 추상적인 상태를 빠르게 이해할 수 있는 블록 단위의 코드를 제공합니다.
map과 reduce와 유사한 기능을 가진 다양한 함수(filter, all, any, find 등)가 있습니다.
명령형으로 작성하지 말고 선언형으로 작성하십시오.
아래 예제 프로그램은 세 대의 차량에서 레이스를 진행합니다. 각 단계에서 차량은 앞으로 이동하거나 정지합니다. 프로그램은 각 단계 별 차량의 위치를 출력합니다. 5단계가 진행된 후 레이스를 종료합니다.
“남은 시간이 있다면 레이스를 실행하고 출력합니다. 그리고 시간을 다시 확인합니다.” 각 레이스의 단계에 대해 더 자세히 알고 싶다면 구현된 함수를 읽으면 됩니다.
코드 자체가 내용을 설명하고 있기 때문에 주석을 추가하지 않아도 됩니다.
코드를 함수로 나누는 것은 코드를 더 읽기 쉽게 만들기 때문에 고민이 필요하지 않습니다.
위 코드는 함수를 사용하지만 외부 데이터(변수)에 의존적이기 때문에 함수형 프로그래밍의 조건을 만족하지 않습니다. 코드의 함수는 상태 값을 매개변수로 전달받아 사용하지 않습니다. 이러한 방식은 외부 변수의 변화에 의해 함수의 결괏값이 달라질 수 있습니다. 각 함수가 실제로 무엇을 하는지 확인하기 위해 정독이 필요합니다. 함수 내에서 외부 변수를 사용한다면 변수의 출처를 찾고 다른 함수에서 해당 변수를 변경하는지 확인해야 합니다.